5151import logging
5252import re
5353from collections .abc import Sequence as SequenceABC
54- from typing import Any , Dict , List , Optional , Pattern , Sequence , Tuple
54+ from typing import (
55+ Any ,
56+ Dict ,
57+ List ,
58+ Optional ,
59+ Pattern ,
60+ Sequence ,
61+ Tuple ,
62+ overload ,
63+ )
5564
5665import google .auth
5766import opentelemetry .trace as trace_api
5867import pkg_resources
59- from google .cloud .trace_v2 import TraceServiceClient
60- from google .cloud .trace_v2 . proto import trace_pb2
68+ from google .cloud .trace_v2 import BatchWriteSpansRequest , TraceServiceClient
69+ from google .cloud .trace_v2 import types as trace_types
6170from google .protobuf .timestamp_pb2 import Timestamp
6271from google .rpc import code_pb2 , status_pb2
6372from opentelemetry .exporter .cloud_trace .version import __version__
@@ -99,7 +108,7 @@ def __init__(
99108 client = None ,
100109 resource_regex = None ,
101110 ):
102- self .client = client or TraceServiceClient ()
111+ self .client : TraceServiceClient = client or TraceServiceClient ()
103112 if not project_id :
104113 _ , self .project_id = google .auth .default ()
105114 else :
@@ -118,8 +127,10 @@ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
118127 """
119128 try :
120129 self .client .batch_write_spans (
121- "projects/{}" .format (self .project_id ),
122- self ._translate_to_cloud_trace (spans ),
130+ request = BatchWriteSpansRequest (
131+ name = "projects/{}" .format (self .project_id ),
132+ spans = self ._translate_to_cloud_trace (spans ),
133+ )
123134 )
124135 # pylint: disable=broad-except
125136 except Exception as ex :
@@ -130,14 +141,14 @@ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
130141
131142 def _translate_to_cloud_trace (
132143 self , spans : Sequence [ReadableSpan ]
133- ) -> List [Dict [ str , Any ] ]:
144+ ) -> List [trace_types . Span ]:
134145 """Translate the spans to Cloud Trace format.
135146
136147 Args:
137148 spans: Sequence of spans to convert
138149 """
139150
140- cloud_trace_spans = []
151+ cloud_trace_spans : List [ trace_types . Span ] = []
141152
142153 for span in spans :
143154 ctx = span .get_span_context ()
@@ -168,25 +179,23 @@ def _translate_to_cloud_trace(
168179 }
169180
170181 cloud_trace_spans .append (
171- {
172- "name" : span_name ,
173- "span_id" : span_id ,
174- "display_name" : _get_truncatable_str_object (
175- span .name , 128
176- ),
177- "start_time" : start_time ,
178- "end_time" : end_time ,
179- "parent_span_id" : parent_id ,
180- "attributes" : _extract_attributes (
182+ trace_types .Span (
183+ name = span_name ,
184+ span_id = span_id ,
185+ display_name = _get_truncatable_str_object (span .name , 128 ),
186+ start_time = start_time ,
187+ end_time = end_time ,
188+ parent_span_id = parent_id ,
189+ attributes = _extract_attributes (
181190 resources_and_attrs ,
182191 MAX_SPAN_ATTRS ,
183192 add_agent_attr = True ,
184193 ),
185- " links" : _extract_links (span .links ), # type: ignore[has-type]
186- " status" : _extract_status (span .status ), # type: ignore[arg-type]
187- " time_events" : _extract_events (span .events ),
188- " span_kind" : _extract_span_kind (span .kind ),
189- }
194+ links = _extract_links (span .links ), # type: ignore[has-type]
195+ status = _extract_status (span .status ), # type: ignore[arg-type]
196+ time_events = _extract_events (span .events ),
197+ span_kind = _extract_span_kind (span .kind ),
198+ )
190199 )
191200 # TODO: Leverage more of the Cloud Trace API, e.g.
192201 # same_process_as_parent_span and child_span_count
@@ -213,7 +222,7 @@ def _get_truncatable_str_object(str_to_convert: str, max_length: int):
213222 truncated bytes count."""
214223 truncated , truncated_byte_count = _truncate_str (str_to_convert , max_length )
215224
216- return trace_pb2 .TruncatableString (
225+ return trace_types .TruncatableString (
217226 value = truncated , truncated_byte_count = truncated_byte_count
218227 )
219228
@@ -248,11 +257,13 @@ def _extract_status(status: trace_api.Status) -> Optional[status_pb2.Status]:
248257 return status_proto
249258
250259
251- def _extract_links (links : Sequence [trace_api .Link ]) -> trace_pb2 .Span .Links :
260+ def _extract_links (
261+ links : Sequence [trace_api .Link ],
262+ ) -> Optional [trace_types .Span .Links ]:
252263 """Convert span.links"""
253264 if not links :
254265 return None
255- extracted_links = []
266+ extracted_links : List [ trace_types . Span . Link ] = []
256267 dropped_links = 0
257268 if len (links ) > MAX_NUM_LINKS :
258269 logger .warning (
@@ -271,25 +282,27 @@ def _extract_links(links: Sequence[trace_api.Link]) -> trace_pb2.Span.Links:
271282 trace_id = format_trace_id (link .context .trace_id )
272283 span_id = format_span_id (link .context .span_id )
273284 extracted_links .append (
274- {
275- " trace_id" : trace_id ,
276- " span_id" : span_id ,
277- " type" : "TYPE_UNSPECIFIED" ,
278- " attributes" : _extract_attributes (
285+ trace_types . Span . Link (
286+ trace_id = trace_id ,
287+ span_id = span_id ,
288+ type = "TYPE_UNSPECIFIED" ,
289+ attributes = _extract_attributes (
279290 link_attributes , MAX_LINK_ATTRS
280291 ),
281- }
292+ )
282293 )
283- return trace_pb2 .Span .Links (
294+ return trace_types .Span .Links (
284295 link = extracted_links , dropped_links_count = dropped_links
285296 )
286297
287298
288- def _extract_events (events : Sequence [Event ]) -> trace_pb2 .Span .TimeEvents :
299+ def _extract_events (
300+ events : Sequence [Event ],
301+ ) -> Optional [trace_types .Span .TimeEvents ]:
289302 """Convert span.events to dict."""
290303 if not events :
291304 return None
292- logs = []
305+ time_events : List [ trace_types . Span . TimeEvent ] = []
293306 dropped_annontations = 0
294307 if len (events ) > MAX_NUM_EVENTS :
295308 logger .warning (
@@ -305,42 +318,40 @@ def _extract_events(events: Sequence[Event]) -> trace_pb2.Span.TimeEvents:
305318 event .name ,
306319 MAX_EVENT_ATTRS ,
307320 )
308- logs .append (
309- {
310- "time" : _get_time_from_ns (event .timestamp ),
311- "annotation" : {
312- "description" : _get_truncatable_str_object (
313- event .name , 256
314- ),
315- "attributes" : _extract_attributes (
321+ time_events .append (
322+ trace_types .Span .TimeEvent (
323+ time = _get_time_from_ns (event .timestamp ),
324+ annotation = trace_types .Span .TimeEvent .Annotation (
325+ description = _get_truncatable_str_object (event .name , 256 ),
326+ attributes = _extract_attributes (
316327 event .attributes , MAX_EVENT_ATTRS
317328 ),
318- } ,
319- }
329+ ) ,
330+ )
320331 )
321- return trace_pb2 .Span .TimeEvents (
322- time_event = logs ,
332+ return trace_types .Span .TimeEvents (
333+ time_event = time_events ,
323334 dropped_annotations_count = dropped_annontations ,
324335 dropped_message_events_count = 0 ,
325336 )
326337
327338
328339# pylint: disable=no-member
329340SPAN_KIND_MAPPING = {
330- trace_api .SpanKind .INTERNAL : trace_pb2 .Span .SpanKind .INTERNAL ,
331- trace_api .SpanKind .CLIENT : trace_pb2 .Span .SpanKind .CLIENT ,
332- trace_api .SpanKind .SERVER : trace_pb2 .Span .SpanKind .SERVER ,
333- trace_api .SpanKind .PRODUCER : trace_pb2 .Span .SpanKind .PRODUCER ,
334- trace_api .SpanKind .CONSUMER : trace_pb2 .Span .SpanKind .CONSUMER ,
341+ trace_api .SpanKind .INTERNAL : trace_types .Span .SpanKind .INTERNAL ,
342+ trace_api .SpanKind .CLIENT : trace_types .Span .SpanKind .CLIENT ,
343+ trace_api .SpanKind .SERVER : trace_types .Span .SpanKind .SERVER ,
344+ trace_api .SpanKind .PRODUCER : trace_types .Span .SpanKind .PRODUCER ,
345+ trace_api .SpanKind .CONSUMER : trace_types .Span .SpanKind .CONSUMER ,
335346}
336347
337348
338349# pylint: disable=no-member
339350def _extract_span_kind (
340351 span_kind : trace_api .SpanKind ,
341- ) -> trace_pb2 . Span . SpanKind :
352+ ) -> int :
342353 return SPAN_KIND_MAPPING .get (
343- span_kind , trace_pb2 .Span .SpanKind .SPAN_KIND_UNSPECIFIED
354+ span_kind , trace_types .Span .SpanKind .SPAN_KIND_UNSPECIFIED
344355 )
345356
346357
@@ -419,19 +430,19 @@ def _extract_attributes(
419430 attrs : types .Attributes ,
420431 num_attrs_limit : int ,
421432 add_agent_attr : bool = False ,
422- ) -> trace_pb2 .Span .Attributes :
433+ ) -> trace_types .Span .Attributes :
423434 """Convert span.attributes to dict."""
424435 attributes_dict = BoundedDict (
425436 num_attrs_limit
426- ) # type: BoundedDict[str, trace_pb2 .AttributeValue]
437+ ) # type: BoundedDict[str, trace_types .AttributeValue]
427438 invalid_value_dropped_count = 0
428- for key , value in attrs .items () if attrs else []:
429- key = _truncate_str (key , 128 )[0 ]
439+ for ot_key , ot_value in attrs .items () if attrs else []:
440+ key = _truncate_str (ot_key , 128 )[0 ]
430441 if key in LABELS_MAPPING : # pylint: disable=consider-using-get
431442 key = LABELS_MAPPING [key ]
432- value = _format_attribute_value (value )
443+ value = _format_attribute_value (ot_value )
433444
434- if value :
445+ if value is not None :
435446 attributes_dict [key ] = value
436447 else :
437448 invalid_value_dropped_count += 1
@@ -444,16 +455,30 @@ def _extract_attributes(
444455 _strip_characters (__version__ ),
445456 )
446457 )
447- return trace_pb2 .Span .Attributes (
448- attribute_map = attributes_dict ,
458+ return trace_types .Span .Attributes (
459+ attribute_map = dict ( attributes_dict ) ,
449460 dropped_attributes_count = attributes_dict .dropped
450461 + invalid_value_dropped_count ,
451462 )
452463
453464
465+ @overload
454466def _format_attribute_value (
455467 value : types .AttributeValue ,
456- ) -> trace_pb2 .AttributeValue :
468+ ) -> trace_types .AttributeValue :
469+ ...
470+
471+
472+ @overload
473+ def _format_attribute_value (
474+ value : Any ,
475+ ) -> Optional [trace_types .AttributeValue ]:
476+ ...
477+
478+
479+ def _format_attribute_value (
480+ value ,
481+ ) -> Optional [trace_types .AttributeValue ]:
457482 if isinstance (value , bool ):
458483 value_type = "bool_value"
459484 elif isinstance (value , int ):
@@ -478,4 +503,4 @@ def _format_attribute_value(
478503 )
479504 return None
480505
481- return trace_pb2 .AttributeValue (** {value_type : value })
506+ return trace_types .AttributeValue (** {value_type : value })
0 commit comments