Skip to content

Commit ee23dfa

Browse files
authored
Upgrade google-cloud-trace dep to ~=1.1 (#170)
1 parent e5f7d7a commit ee23dfa

6 files changed

Lines changed: 104 additions & 75 deletions

File tree

e2e-test-server/constraints.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ click==7.1.2
55
Flask==1.1.2
66
google-api-core==1.26.3
77
google-auth==1.30.0
8-
google-cloud-core==1.6.0
98
google-cloud-pubsub==2.4.1
10-
google-cloud-trace==0.24.0
9+
google-cloud-trace==1.5.0
1110
googleapis-common-protos==1.53.0
1211
grpc-google-iam-v1==0.12.3
1312
grpcio==1.37.0

opentelemetry-exporter-gcp-trace/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Add optional resource attributes to trace spans with regex
66
([#145](https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/pull/145))
7+
- Upgrade `google-cloud-trace` dependency to version 1.1 or newer.
78

89
## Version 1.0.0
910

opentelemetry-exporter-gcp-trace/setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ package_dir=
2525
=src
2626
packages=find_namespace:
2727
install_requires =
28-
google-cloud-trace >=0.24.0, <1.0.0
28+
google-cloud-trace ~= 1.1
2929
opentelemetry-api ~= 1.0
3030
opentelemetry-sdk ~= 1.0
3131

opentelemetry-exporter-gcp-trace/src/opentelemetry/exporter/cloud_trace/__init__.py

Lines changed: 89 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,22 @@
5151
import logging
5252
import re
5353
from 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

5665
import google.auth
5766
import opentelemetry.trace as trace_api
5867
import 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
6170
from google.protobuf.timestamp_pb2 import Timestamp
6271
from google.rpc import code_pb2, status_pb2
6372
from 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
329340
SPAN_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
339350
def _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
454466
def _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})

opentelemetry-exporter-gcp-trace/tests/test_cloud_trace_exporter.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
from unittest import mock
1818

1919
import pkg_resources
20-
from google.cloud.trace_v2.proto.trace_pb2 import AttributeValue
21-
from google.cloud.trace_v2.proto.trace_pb2 import Span as ProtoSpan
22-
from google.cloud.trace_v2.proto.trace_pb2 import TruncatableString
20+
from google.cloud.trace_v2.types import AttributeValue, BatchWriteSpansRequest
21+
from google.cloud.trace_v2.types import Span as ProtoSpan
22+
from google.cloud.trace_v2.types import TruncatableString
2323
from google.rpc import code_pb2
2424
from google.rpc.status_pb2 import Status
2525
from opentelemetry.exporter.cloud_trace import (
@@ -175,7 +175,10 @@ def test_export(self):
175175

176176
self.assertTrue(client.batch_write_spans.called)
177177
client.batch_write_spans.assert_called_with(
178-
"projects/{}".format(self.project_id), [cloud_trace_spans]
178+
request=BatchWriteSpansRequest(
179+
name="projects/{}".format(self.project_id),
180+
spans=[cloud_trace_spans],
181+
)
179182
)
180183

181184
def test_extract_status_code_unset(self):

opentelemetry-exporter-gcp-trace/tests/test_integration_cloud_trace_exporter.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
import grpc
1616
from google.cloud.trace_v2 import TraceServiceClient
17-
from google.cloud.trace_v2.gapic.transports import trace_service_grpc_transport
17+
from google.cloud.trace_v2.services.trace_service.transports.grpc import (
18+
TraceServiceGrpcTransport,
19+
)
1820
from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
1921
from opentelemetry.sdk.resources import Resource
2022
from opentelemetry.sdk.trace import _Span as Span
@@ -58,9 +60,8 @@ def test_export(self):
5860

5961
# Setup the trace exporter.
6062
channel = grpc.insecure_channel(self.address)
61-
transport = trace_service_grpc_transport.TraceServiceGrpcTransport(
62-
channel=channel
63-
)
63+
transport = TraceServiceGrpcTransport(channel=channel)
64+
6465
client = TraceServiceClient(transport=transport)
6566
trace_exporter = CloudTraceSpanExporter(self.project_id, client=client)
6667

0 commit comments

Comments
 (0)