diff --git a/opentelemetry-exporter-gcp-trace/CHANGELOG.md b/opentelemetry-exporter-gcp-trace/CHANGELOG.md index feb5eb93..f5779172 100644 --- a/opentelemetry-exporter-gcp-trace/CHANGELOG.md +++ b/opentelemetry-exporter-gcp-trace/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Update span and attribute limits to match Cloud Trace backend + ## Version 1.14.0 Released 2026-08-03 diff --git a/opentelemetry-exporter-gcp-trace/src/opentelemetry/exporter/cloud_trace/__init__.py b/opentelemetry-exporter-gcp-trace/src/opentelemetry/exporter/cloud_trace/__init__.py index 4b06e25e..11b296a1 100644 --- a/opentelemetry-exporter-gcp-trace/src/opentelemetry/exporter/cloud_trace/__init__.py +++ b/opentelemetry-exporter-gcp-trace/src/opentelemetry/exporter/cloud_trace/__init__.py @@ -137,12 +137,12 @@ MAX_NUM_LINKS = 128 -MAX_NUM_EVENTS = 32 -MAX_EVENT_ATTRS = 4 -MAX_LINK_ATTRS = 32 -MAX_SPAN_ATTRS = 32 -MAX_ATTR_KEY_BYTES = 128 -MAX_ATTR_VAL_BYTES = 16 * 1024 # 16 kilobytes +MAX_NUM_EVENTS = 256 +MAX_EVENT_ATTRS = 1024 +MAX_LINK_ATTRS = 1024 +MAX_SPAN_ATTRS = 1024 +MAX_ATTR_KEY_BYTES = 512 +MAX_ATTR_VAL_BYTES = 64 * 1024 # 64 kilobytes def _create_default_client() -> TraceServiceClient: @@ -260,7 +260,7 @@ def _translate_to_cloud_trace( trace_types.Span( name=span_name, span_id=span_id, - display_name=_get_truncatable_str_object(span.name, 128), + display_name=_get_truncatable_str_object(span.name, 1024), start_time=start_time, end_time=end_time, parent_span_id=parent_id, @@ -400,7 +400,7 @@ def _extract_events( trace_types.Span.TimeEvent( time=_get_time_from_ns(event.timestamp), annotation=trace_types.Span.TimeEvent.Annotation( - description=_get_truncatable_str_object(event.name, 256), + description=_get_truncatable_str_object(event.name, 1024), attributes=_extract_attributes( event.attributes, MAX_EVENT_ATTRS ), diff --git a/opentelemetry-exporter-gcp-trace/tests/test_cloud_trace_exporter.py b/opentelemetry-exporter-gcp-trace/tests/test_cloud_trace_exporter.py index 69c3bced..9abe4499 100644 --- a/opentelemetry-exporter-gcp-trace/tests/test_cloud_trace_exporter.py +++ b/opentelemetry-exporter-gcp-trace/tests/test_cloud_trace_exporter.py @@ -102,8 +102,12 @@ def setUpClass(cls): cls.example_span_id = "95bb5edabd45950f" cls.example_time_in_ns = 1589919268850900051 cls.example_time_stamp = _get_time_from_ns(cls.example_time_in_ns) - cls.str_20kb = "a" * 20 * 1024 - cls.str_16kb = "a" * 16 * 1024 + cls.str_70kb = "a" * 70 * 1024 + cls.str_64kb = "a" * 64 * 1024 + cls.str_1100 = "a" * 1100 + cls.str_1024 = "a" * 1024 + cls.str_600 = "a" * 600 + cls.str_512 = "a" * 512 cls.str_300 = "a" * 300 cls.str_256 = "a" * 256 cls.str_128 = "a" * 128 @@ -338,10 +342,10 @@ def test_agent_attribute_priority(self): def test_attribute_value_truncation(self): # shouldn't truncate self.assertEqual( - _format_attribute_value(self.str_300), + _format_attribute_value(self.str_600), AttributeValue( string_value=TruncatableString( - value=self.str_300, + value=self.str_600, truncated_byte_count=0, ) ), @@ -349,11 +353,11 @@ def test_attribute_value_truncation(self): # huge string should truncate self.assertEqual( - _format_attribute_value(self.str_20kb), + _format_attribute_value(self.str_70kb), AttributeValue( string_value=TruncatableString( - value=self.str_16kb, - truncated_byte_count=(20 - 16) * 1024, + value=self.str_64kb, + truncated_byte_count=(70 - 64) * 1024, ) ), ) @@ -395,11 +399,11 @@ def test_list_attribute_value(self): def test_attribute_key_truncation(self): self.assertEqual( _extract_attributes( - {self.str_300: "attr_value"}, num_attrs_limit=4 + {self.str_600: "attr_value"}, num_attrs_limit=4 ), ProtoSpan.Attributes( attribute_map={ - self.str_128: AttributeValue( + self.str_512: AttributeValue( string_value=TruncatableString( value="attr_value", truncated_byte_count=0 ) @@ -504,7 +508,9 @@ def test_extract_multiple_events(self): def test_event_name_truncation(self): event1 = Event( - name=self.str_300, attributes={}, timestamp=self.example_time_in_ns + name=self.str_1100, + attributes={}, + timestamp=self.example_time_in_ns, ) self.assertEqual( _extract_events([event1]), @@ -514,8 +520,8 @@ def test_event_name_truncation(self): "time": self.example_time_stamp, "annotation": { "description": TruncatableString( - value=self.str_256, - truncated_byte_count=300 - 256, + value=self.str_1024, + truncated_byte_count=1100 - 1024, ), "attributes": {}, }, @@ -780,3 +786,23 @@ def test_extract_span_kind(self): self.assertEqual( _extract_span_kind(-1), ProtoSpan.SpanKind.SPAN_KIND_UNSPECIFIED ) + + def test_span_name_truncation(self): + exporter = CloudTraceSpanExporter(self.project_id) + span_data = Span( + name=self.str_1100, + context=SpanContext( + trace_id=int(self.example_trace_id, 16), + span_id=int(self.example_span_id, 16), + is_remote=False, + ), + ) + # pylint: disable=protected-access + translated_spans = exporter._translate_to_cloud_trace([span_data]) + self.assertEqual( + translated_spans[0].display_name, + TruncatableString( + value=self.str_1024, + truncated_byte_count=1100 - 1024, + ), + )