2727 Dict ,
2828 Generic ,
2929 List ,
30+ Literal ,
31+ NewType ,
3032 Optional ,
3133 Tuple ,
34+ Type ,
3235 TypeVar ,
3336 Union ,
3437)
5356from opentelemetry .exporter .otlp .proto .grpc import (
5457 _OTLP_GRPC_CHANNEL_OPTIONS ,
5558)
59+ from opentelemetry .proto .collector .logs .v1 .logs_service_pb2 import (
60+ ExportLogsServiceRequest ,
61+ )
62+ from opentelemetry .proto .collector .logs .v1 .logs_service_pb2_grpc import (
63+ LogsServiceStub ,
64+ )
65+ from opentelemetry .proto .collector .metrics .v1 .metrics_service_pb2 import (
66+ ExportMetricsServiceRequest ,
67+ )
68+ from opentelemetry .proto .collector .metrics .v1 .metrics_service_pb2_grpc import (
69+ MetricsServiceStub ,
70+ )
71+ from opentelemetry .proto .collector .trace .v1 .trace_service_pb2 import (
72+ ExportTraceServiceRequest ,
73+ )
74+ from opentelemetry .proto .collector .trace .v1 .trace_service_pb2_grpc import (
75+ TraceServiceStub ,
76+ )
5677from opentelemetry .proto .common .v1 .common_pb2 import ( # noqa: F401
5778 AnyValue ,
5879 ArrayValue ,
5980 KeyValue ,
6081)
6182from opentelemetry .proto .resource .v1 .resource_pb2 import Resource # noqa: F401
83+ from opentelemetry .sdk ._logs import LogData
84+ from opentelemetry .sdk ._logs .export import LogExportResult
6285from opentelemetry .sdk ._shared_internal import DuplicateFilter
6386from opentelemetry .sdk .environment_variables import (
6487 _OTEL_PYTHON_EXPORTER_OTLP_GRPC_CREDENTIAL_PROVIDER ,
7194 OTEL_EXPORTER_OTLP_INSECURE ,
7295 OTEL_EXPORTER_OTLP_TIMEOUT ,
7396)
74- from opentelemetry .sdk .metrics .export import MetricsData
97+ from opentelemetry .sdk .metrics .export import MetricExportResult , MetricsData
7598from opentelemetry .sdk .resources import Resource as SDKResource
7699from opentelemetry .sdk .trace import ReadableSpan
100+ from opentelemetry .sdk .trace .export import SpanExportResult
77101from opentelemetry .util ._importlib_metadata import entry_points
78102from opentelemetry .util .re import parse_env_headers
79103
92116logger = getLogger (__name__ )
93117# This prevents logs generated when a log fails to be written to generate another log which fails to be written etc. etc.
94118logger .addFilter (DuplicateFilter ())
95- SDKDataT = TypeVar ("SDKDataT" )
119+ SDKDataT = TypeVar (
120+ "SDKDataT" ,
121+ TypingSequence [LogData ],
122+ MetricsData ,
123+ TypingSequence [ReadableSpan ],
124+ )
96125ResourceDataT = TypeVar ("ResourceDataT" )
97126TypingResourceT = TypeVar ("TypingResourceT" )
98- ExportServiceRequestT = TypeVar ("ExportServiceRequestT" )
99- ExportResultT = TypeVar ("ExportResultT" )
127+ ExportServiceRequestT = TypeVar (
128+ "ExportServiceRequestT" ,
129+ ExportTraceServiceRequest ,
130+ ExportMetricsServiceRequest ,
131+ ExportLogsServiceRequest ,
132+ )
133+ ExportResultT = TypeVar (
134+ "ExportResultT" ,
135+ LogExportResult ,
136+ MetricExportResult ,
137+ SpanExportResult ,
138+ )
139+ ExportStubT = TypeVar (
140+ "ExportStubT" , TraceServiceStub , MetricsServiceStub , LogsServiceStub
141+ )
100142
101143_ENVIRON_TO_COMPRESSION = {
102144 None : None ,
@@ -119,7 +161,10 @@ def environ_to_compression(environ_key: str) -> Optional[Compression]:
119161 if environ_key in environ
120162 else None
121163 )
122- if environ_value not in _ENVIRON_TO_COMPRESSION :
164+ if (
165+ environ_value not in _ENVIRON_TO_COMPRESSION
166+ and environ_value is not None
167+ ):
123168 raise InvalidCompressionValueException (environ_key , environ_value )
124169 return _ENVIRON_TO_COMPRESSION [environ_value ]
125170
@@ -151,7 +196,7 @@ def _load_credentials(
151196 certificate_file : Optional [str ],
152197 client_key_file : Optional [str ],
153198 client_certificate_file : Optional [str ],
154- ) -> Optional [ ChannelCredentials ] :
199+ ) -> ChannelCredentials :
155200 root_certificates = (
156201 _read_file (certificate_file ) if certificate_file else None
157202 )
@@ -214,7 +259,7 @@ def _get_credentials(
214259
215260# pylint: disable=no-member
216261class OTLPExporterMixin (
217- ABC , Generic [SDKDataT , ExportServiceRequestT , ExportResultT ]
262+ ABC , Generic [SDKDataT , ExportServiceRequestT , ExportResultT , ExportStubT ]
218263):
219264 """OTLP span exporter
220265
@@ -230,6 +275,8 @@ class OTLPExporterMixin(
230275
231276 def __init__ (
232277 self ,
278+ stub : ExportStubT ,
279+ result : ExportResultT ,
233280 endpoint : Optional [str ] = None ,
234281 insecure : Optional [bool ] = None ,
235282 credentials : Optional [ChannelCredentials ] = None ,
@@ -238,10 +285,11 @@ def __init__(
238285 ] = None ,
239286 timeout : Optional [float ] = None ,
240287 compression : Optional [Compression ] = None ,
241- channel_options : Optional [TypingSequence [Tuple [str , str ]]] = None ,
288+ channel_options : Optional [Tuple [Tuple [str , str ]]] = None ,
242289 ):
243290 super ().__init__ ()
244-
291+ self ._result = result
292+ self ._stub = stub
245293 self ._endpoint = endpoint or environ .get (
246294 OTEL_EXPORTER_OTLP_ENDPOINT , "http://localhost:4317"
247295 )
@@ -250,15 +298,12 @@ def __init__(
250298
251299 if parsed_url .scheme == "https" :
252300 insecure = False
301+ insecure_exporter = environ .get (OTEL_EXPORTER_OTLP_INSECURE )
253302 if insecure is None :
254- insecure = environ .get (OTEL_EXPORTER_OTLP_INSECURE )
255- if insecure is not None :
256- insecure = insecure .lower () == "true"
303+ if insecure_exporter is not None :
304+ insecure = insecure_exporter .lower () == "true"
257305 else :
258- if parsed_url .scheme == "http" :
259- insecure = True
260- else :
261- insecure = False
306+ insecure = parsed_url .scheme == "http"
262307
263308 if parsed_url .netloc :
264309 self ._endpoint = parsed_url .netloc
@@ -277,12 +322,12 @@ def __init__(
277322 overridden_options = {
278323 opt_name for (opt_name , _ ) in channel_options
279324 }
280- default_options = [
325+ default_options = tuple (
281326 (opt_name , opt_value )
282327 for opt_name , opt_value in _OTLP_GRPC_CHANNEL_OPTIONS
283328 if opt_name not in overridden_options
284- ]
285- self ._channel_options = tuple ( default_options ) + channel_options
329+ )
330+ self ._channel_options = default_options + channel_options
286331 else :
287332 self ._channel_options = tuple (_OTLP_GRPC_CHANNEL_OPTIONS )
288333
@@ -317,24 +362,25 @@ def __init__(
317362 compression = compression ,
318363 options = self ._channel_options ,
319364 )
320- self ._client = self ._stub (self ._channel )
365+ self ._client = self ._stub (self ._channel ) # type: ignore [reportCallIssue]
321366
322367 self ._shutdown_in_progress = threading .Event ()
323368 self ._shutdown = False
324369
325370 @abstractmethod
326371 def _translate_data (
327- self , data : TypingSequence [SDKDataT ]
372+ self ,
373+ data : SDKDataT ,
328374 ) -> ExportServiceRequestT :
329375 pass
330376
331377 def _export (
332378 self ,
333- data : Union [ TypingSequence [ ReadableSpan ], MetricsData ] ,
379+ data : SDKDataT ,
334380 ) -> ExportResultT :
335381 if self ._shutdown :
336382 logger .warning ("Exporter already shutdown, ignoring batch" )
337- return self ._result .FAILURE
383+ return self ._result .FAILURE # type: ignore [reportReturnType]
338384
339385 # FIXME remove this check if the export type for traces
340386 # gets updated to a class that represents the proto
@@ -347,10 +393,10 @@ def _export(
347393 metadata = self ._headers ,
348394 timeout = deadline_sec - time (),
349395 )
350- return self ._result .SUCCESS
396+ return self ._result .SUCCESS # type: ignore [reportReturnType]
351397 except RpcError as error :
352- retry_info_bin = dict (error .trailing_metadata ()).get (
353- "google.rpc.retryinfo-bin"
398+ retry_info_bin = dict (error .trailing_metadata ()).get ( # type: ignore [reportAttributeAccessIssue]
399+ "google.rpc.retryinfo-bin" # type: ignore [reportArgumentType]
354400 )
355401 # multiplying by a random number between .8 and 1.2 introduces a +/20% jitter to each backoff.
356402 backoff_seconds = 2 ** retry_num * random .uniform (0.8 , 1.2 )
@@ -362,7 +408,7 @@ def _export(
362408 + retry_info .retry_delay .nanos / 1.0e9
363409 )
364410 if (
365- error .code () not in _RETRYABLE_ERROR_CODES
411+ error .code () not in _RETRYABLE_ERROR_CODES # type: ignore [reportAttributeAccessIssue]
366412 or retry_num + 1 == _MAX_RETRYS
367413 or backoff_seconds > (deadline_sec - time ())
368414 or self ._shutdown
@@ -371,13 +417,13 @@ def _export(
371417 "Failed to export %s to %s, error code: %s" ,
372418 self ._exporting ,
373419 self ._endpoint ,
374- error .code (),
375- exc_info = error .code () == StatusCode .UNKNOWN ,
420+ error .code (), # type: ignore [reportAttributeAccessIssue]
421+ exc_info = error .code () == StatusCode .UNKNOWN , # type: ignore [reportAttributeAccessIssue]
376422 )
377- return self ._result .FAILURE
423+ return self ._result .FAILURE # type: ignore [reportReturnType]
378424 logger .warning (
379425 "Transient error %s encountered while exporting %s to %s, retrying in %.2fs." ,
380- error .code (),
426+ error .code (), # type: ignore [reportAttributeAccessIssue]
381427 self ._exporting ,
382428 self ._endpoint ,
383429 backoff_seconds ,
@@ -387,7 +433,7 @@ def _export(
387433 logger .warning ("Shutdown in progress, aborting retry." )
388434 break
389435 # Not possible to reach here but the linter is complaining.
390- return self ._result .FAILURE
436+ return self ._result .FAILURE # type: ignore [reportReturnType]
391437
392438 def shutdown (self , timeout_millis : float = 30_000 , ** kwargs ) -> None :
393439 if self ._shutdown :
0 commit comments