4545 _initialize_components ,
4646 _OTelSDKConfigurator ,
4747)
48- from opentelemetry .sdk ._logs import LoggingHandler
48+ from opentelemetry .sdk ._logs import LoggingHandler , LogRecordProcessor
4949from opentelemetry .sdk ._logs ._internal .export import LogRecordExporter
5050from opentelemetry .sdk ._logs .export import (
5151 ConsoleLogRecordExporter ,
6565)
6666from opentelemetry .sdk .metrics .view import Aggregation
6767from opentelemetry .sdk .resources import SERVICE_NAME , Resource
68+ from opentelemetry .sdk .trace import SpanProcessor
6869from opentelemetry .sdk .trace .export import (
6970 ConsoleSpanExporter ,
7071 SimpleSpanProcessor ,
@@ -88,23 +89,23 @@ class Provider:
8889 def __init__ (self , resource = None , sampler = None , id_generator = None ):
8990 self .sampler = sampler
9091 self .id_generator = id_generator
91- self .processor = None
92+ self .processors = []
9293 self .resource = resource or Resource .create ({})
9394
9495 def add_span_processor (self , processor ):
95- self .processor = processor
96+ self .processors . append ( processor )
9697
9798
9899class DummyLoggerProvider :
99100 def __init__ (self , resource = None ):
100101 self .resource = resource
101- self .processor = DummyLogRecordProcessor ( DummyOTLPLogExporter ())
102+ self .processors = []
102103
103104 def add_log_record_processor (self , processor ):
104- self .processor = processor
105+ self .processors . append ( processor )
105106
106107 def get_logger (self , name , * args , ** kwargs ):
107- return DummyLogger (name , self .resource , self .processor )
108+ return DummyLogger (name , self .resource , self .processors )
108109
109110 def force_flush (self , * args , ** kwargs ):
110111 pass
@@ -115,10 +116,10 @@ class DummyMeterProvider(MeterProvider):
115116
116117
117118class DummyLogger :
118- def __init__ (self , name , resource , processor ):
119+ def __init__ (self , name , resource , processors ):
119120 self .name = name
120121 self .resource = resource
121- self .processor = processor
122+ self .processors = processors
122123
123124 def emit (
124125 self ,
@@ -133,7 +134,8 @@ def emit(
133134 attributes = None ,
134135 event_name = None ,
135136 ):
136- self .processor .emit (record )
137+ for processor in self .processors :
138+ processor .emit (record )
137139
138140
139141class DummyLogRecordProcessor :
@@ -357,10 +359,11 @@ def test_trace_init_default(self):
357359 provider = self .set_provider_mock .call_args [0 ][0 ]
358360 self .assertIsInstance (provider , Provider )
359361 self .assertIsInstance (provider .id_generator , RandomIdGenerator )
360- self .assertIsInstance (provider .processor , Processor )
361- self .assertIsInstance (provider .processor .exporter , Exporter )
362+ self .assertEqual (len (provider .processors ), 1 )
363+ self .assertIsInstance (provider .processors [0 ], Processor )
364+ self .assertIsInstance (provider .processors [0 ].exporter , Exporter )
362365 self .assertEqual (
363- provider .processor .exporter .service_name , "my-test-service"
366+ provider .processors [ 0 ] .exporter .service_name , "my-test-service"
364367 )
365368 self .assertEqual (
366369 provider .resource .attributes .get ("telemetry.auto.version" ),
@@ -380,8 +383,11 @@ def test_trace_init_otlp(self):
380383 provider = self .set_provider_mock .call_args [0 ][0 ]
381384 self .assertIsInstance (provider , Provider )
382385 self .assertIsInstance (provider .id_generator , RandomIdGenerator )
383- self .assertIsInstance (provider .processor , Processor )
384- self .assertIsInstance (provider .processor .exporter , OTLPSpanExporter )
386+ self .assertEqual (len (provider .processors ), 1 )
387+ self .assertIsInstance (provider .processors [0 ], Processor )
388+ self .assertIsInstance (
389+ provider .processors [0 ].exporter , OTLPSpanExporter
390+ )
385391 self .assertIsInstance (provider .resource , Resource )
386392 self .assertEqual (
387393 provider .resource .attributes .get ("service.name" ),
@@ -399,18 +405,25 @@ def test_trace_init_exporter_uses_exporter_args_map(self):
399405 )
400406
401407 provider = self .set_provider_mock .call_args [0 ][0 ]
402- exporter = provider .processor .exporter
408+ self .assertEqual (len (provider .processors ), 1 )
409+ exporter = provider .processors [0 ].exporter
403410 self .assertEqual (exporter .compression , "gzip" )
404411
405- def test_trace_init_custom_export_span_processor (self ):
412+ def test_trace_init_custom_span_processors (self ):
413+ span_processor = mock .Mock (spec = SpanProcessor )
406414 _init_tracing (
407415 {"otlp" : OTLPSpanExporter },
408416 id_generator = RandomIdGenerator (),
417+ span_processors = [span_processor ],
409418 export_span_processor = SimpleSpanProcessor ,
410419 )
411420
412421 provider = self .set_provider_mock .call_args [0 ][0 ]
413- self .assertTrue (isinstance (provider .processor , SimpleSpanProcessor ))
422+ self .assertEqual (len (provider .processors ), 2 )
423+ self .assertEqual (provider .processors [0 ], span_processor )
424+ self .assertTrue (
425+ isinstance (provider .processors [1 ], SimpleSpanProcessor )
426+ )
414427
415428 @patch .dict (environ , {OTEL_PYTHON_ID_GENERATOR : "custom_id_generator" })
416429 @patch ("opentelemetry.sdk._configuration.IdGenerator" , new = IdGenerator )
@@ -700,12 +713,16 @@ def test_logging_init_exporter(self):
700713 provider .resource .attributes .get ("service.name" ),
701714 "otlp-service" ,
702715 )
703- self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
716+ self .assertEqual (len (provider .processors ), 1 )
717+ self .assertIsInstance (
718+ provider .processors [0 ], DummyLogRecordProcessor
719+ )
704720 self .assertIsInstance (
705- provider .processor .exporter , DummyOTLPLogExporter
721+ provider .processors [ 0 ] .exporter , DummyOTLPLogExporter
706722 )
707723 getLogger (__name__ ).error ("hello" )
708- self .assertTrue (provider .processor .exporter .export_called )
724+ self .assertEqual (len (provider .processors ), 1 )
725+ self .assertTrue (provider .processors [0 ].exporter .export_called )
709726
710727 def test_logging_init_exporter_uses_exporter_args_map (self ):
711728 with ResetGlobalLoggingState ():
@@ -720,18 +737,27 @@ def test_logging_init_exporter_uses_exporter_args_map(self):
720737 )
721738 self .assertEqual (self .set_provider_mock .call_count , 1 )
722739 provider = self .set_provider_mock .call_args [0 ][0 ]
723- self .assertEqual (provider .processor .exporter .compression , "gzip" )
740+ self .assertEqual (len (provider .processors ), 1 )
741+ self .assertEqual (
742+ provider .processors [0 ].exporter .compression , "gzip"
743+ )
724744
725- def test_logging_init_custom_export_log_record_processor (self ):
745+ def test_logging_init_custom_log_record_processors (self ):
746+ log_record_processor = mock .Mock (spec = LogRecordProcessor )
726747 with ResetGlobalLoggingState ():
727748 resource = Resource .create ({})
728749 _init_logging (
729750 {"otlp" : DummyOTLPLogExporter },
730751 resource = resource ,
752+ log_record_processors = [log_record_processor ],
731753 export_log_record_processor = SimpleLogRecordProcessor ,
732754 )
733755 provider = self .set_provider_mock .call_args [0 ][0 ]
734- self .assertIsInstance (provider .processor , SimpleLogRecordProcessor )
756+ self .assertEqual (len (provider .processors ), 2 )
757+ self .assertEqual (provider .processors [0 ], log_record_processor )
758+ self .assertIsInstance (
759+ provider .processors [1 ], SimpleLogRecordProcessor
760+ )
735761
736762 @patch .dict (
737763 environ ,
@@ -752,12 +778,13 @@ def test_logging_init_exporter_without_handler_setup(self):
752778 provider .resource .attributes .get ("service.name" ),
753779 "otlp-service" ,
754780 )
755- self .assertIsInstance (provider .processor , DummyLogRecordProcessor )
781+ self .assertEqual (len (provider .processors ), 1 )
782+ self .assertIsInstance (provider .processors [0 ], DummyLogRecordProcessor )
756783 self .assertIsInstance (
757- provider .processor .exporter , DummyOTLPLogExporter
784+ provider .processors [ 0 ] .exporter , DummyOTLPLogExporter
758785 )
759786 getLogger (__name__ ).error ("hello" )
760- self .assertFalse (provider .processor .exporter .export_called )
787+ self .assertFalse (provider .processors [ 0 ] .exporter .export_called )
761788
762789 @patch .dict (
763790 environ ,
0 commit comments