Skip to content

Commit 463d4c8

Browse files
committed
Add max_attr_value_length support to Jaeger exporter
This commit adds ability to specifiy maximum length for string attributes to the Jaeger exporter. This is similar to how Zipkin exporter supports `max_tag_value_length`.
1 parent 99128b3 commit 463d4c8

File tree

8 files changed

+634
-403
lines changed

8 files changed

+634
-403
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v0.18b0...HEAD)
88

9+
### Added
10+
- Add `max_attr_value_length` support to Jaeger exporter
11+
([#1633])(https://github.com/open-telemetry/opentelemetry-python/pull/11633)
12+
913
## [0.18b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v0.18b0) - 2021-02-16
1014

1115
### Added

exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
# insecure=True, # optional
4848
# credentials=xxx # optional channel creds
4949
# transport_format='protobuf' # optional
50+
# max_attr_value_length=None # optional
5051
)
5152
5253
# Create a BatchExportSpanProcessor and add the exporter to it
@@ -120,6 +121,7 @@ class JaegerSpanExporter(SpanExporter):
120121
insecure: True if collector has no encryption or authentication
121122
credentials: Credentials for server authentication.
122123
transport_format: Transport format for exporting spans to collector.
124+
max_attr_value_length: Max length string attribute values can have. Set to None to disable.
123125
"""
124126

125127
def __init__(
@@ -133,8 +135,10 @@ def __init__(
133135
insecure: Optional[bool] = None,
134136
credentials: Optional[ChannelCredentials] = None,
135137
transport_format: Optional[str] = None,
138+
max_attr_value_length: Optional[int] = None,
136139
):
137140
self.service_name = service_name
141+
self._max_attr_value_length = max_attr_value_length
138142
self.agent_host_name = _parameter_setter(
139143
param=agent_host_name,
140144
env_variable=environ.get(OTEL_EXPORTER_JAEGER_AGENT_HOST),
@@ -220,13 +224,15 @@ def _collector_http_client(self) -> Optional[Collector]:
220224
def export(self, spans) -> SpanExportResult:
221225
translator = Translate(spans)
222226
if self.transport_format == TRANSPORT_FORMAT_PROTOBUF:
223-
pb_translator = ProtobufTranslator(self.service_name)
227+
pb_translator = ProtobufTranslator(
228+
self.service_name, self._max_attr_value_length
229+
)
224230
jaeger_spans = translator._translate(pb_translator)
225231
batch = model_pb2.Batch(spans=jaeger_spans)
226232
request = PostSpansRequest(batch=batch)
227233
self._collector_grpc_client.PostSpans(request)
228234
else:
229-
thrift_translator = ThriftTranslator()
235+
thrift_translator = ThriftTranslator(self._max_attr_value_length)
230236
jaeger_spans = translator._translate(thrift_translator)
231237
batch = jaeger_thrift.Batch(
232238
spans=jaeger_spans,

exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import abc
16+
from typing import Optional
1617

1718
from opentelemetry.trace import SpanKind
1819

@@ -41,6 +42,9 @@ def _convert_int_to_i64(val):
4142

4243

4344
class Translator(abc.ABC):
45+
def __init__(self, max_attr_value_length: Optional[int] = None):
46+
self._max_attr_value_length = max_attr_value_length
47+
4448
@abc.abstractmethod
4549
def _translate_span(self, span):
4650
"""Translates span to jaeger format.

exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/protobuf.py

+26-9
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,31 @@ def _get_binary_key_value(key: str, value: bytes) -> model_pb2.KeyValue:
7676

7777

7878
def _translate_attribute(
79-
key: str, value: types.AttributeValue
79+
key: str, value: types.AttributeValue, max_length: Optional[int]
8080
) -> Optional[model_pb2.KeyValue]:
8181
"""Convert the attributes to jaeger keyvalues."""
8282
translated = None
8383
if isinstance(value, bool):
8484
translated = _get_bool_key_value(key, value)
8585
elif isinstance(value, str):
86+
if max_length is not None:
87+
value = value[:max_length]
8688
translated = _get_string_key_value(key, value)
8789
elif isinstance(value, int):
8890
translated = _get_long_key_value(key, value)
8991
elif isinstance(value, float):
9092
translated = _get_double_key_value(key, value)
9193
elif isinstance(value, tuple):
92-
translated = _get_string_key_value(key, str(value))
94+
value = str(value)
95+
if max_length is not None:
96+
value = value[:max_length]
97+
translated = _get_string_key_value(key, value)
9398
return translated
9499

95100

96-
def _extract_resource_tags(span: ReadableSpan) -> Sequence[model_pb2.KeyValue]:
101+
def _extract_resource_tags(
102+
span: ReadableSpan, max_attr_value_length: Optional[int]
103+
) -> Sequence[model_pb2.KeyValue]:
97104
"""Extracts resource attributes from span and returns
98105
list of jaeger keyvalues.
99106
@@ -102,7 +109,7 @@ def _extract_resource_tags(span: ReadableSpan) -> Sequence[model_pb2.KeyValue]:
102109
"""
103110
tags = []
104111
for key, value in span.resource.attributes.items():
105-
tag = _translate_attribute(key, value)
112+
tag = _translate_attribute(key, value, max_attr_value_length)
106113
if tag:
107114
tags.append(tag)
108115
return tags
@@ -140,7 +147,10 @@ def _proto_timestamp_from_epoch_nanos(nsec: int) -> Timestamp:
140147

141148

142149
class ProtobufTranslator(Translator):
143-
def __init__(self, svc_name):
150+
def __init__(
151+
self, svc_name: str, max_attr_value_length: Optional[int] = None
152+
):
153+
super().__init__(max_attr_value_length)
144154
self.svc_name = svc_name
145155

146156
def _translate_span(self, span: ReadableSpan) -> model_pb2.Span:
@@ -161,7 +171,8 @@ def _translate_span(self, span: ReadableSpan) -> model_pb2.Span:
161171
flags = int(ctx.trace_flags)
162172

163173
process = model_pb2.Process(
164-
service_name=self.svc_name, tags=_extract_resource_tags(span)
174+
service_name=self.svc_name,
175+
tags=_extract_resource_tags(span, self.max_attr_value_length),
165176
)
166177
jaeger_span = model_pb2.Span(
167178
trace_id=trace_id,
@@ -183,12 +194,16 @@ def _extract_tags(
183194
translated = []
184195
if span.attributes:
185196
for key, value in span.attributes.items():
186-
key_value = _translate_attribute(key, value)
197+
key_value = _translate_attribute(
198+
key, value, self._max_attr_value_length
199+
)
187200
if key_value is not None:
188201
translated.append(key_value)
189202
if span.resource.attributes:
190203
for key, value in span.resource.attributes.items():
191-
key_value = _translate_attribute(key, value)
204+
key_value = _translate_attribute(
205+
key, value, self._max_attr_value_length
206+
)
192207
if key_value:
193208
translated.append(key_value)
194209

@@ -256,7 +271,9 @@ def _extract_logs(
256271
for event in span.events:
257272
fields = []
258273
for key, value in event.attributes.items():
259-
tag = _translate_attribute(key, value)
274+
tag = _translate_attribute(
275+
key, value, self._max_attr_value_length
276+
)
260277
if tag:
261278
fields.append(tag)
262279

exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/thrift.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,24 @@ def _get_trace_id_high(trace_id):
5858

5959

6060
def _translate_attribute(
61-
key: str, value: types.AttributeValue
61+
key: str, value: types.AttributeValue, max_length: Optional[int]
6262
) -> Optional[TCollector.Tag]:
6363
"""Convert the attributes to jaeger tags."""
6464
if isinstance(value, bool):
6565
return _get_bool_tag(key, value)
6666
if isinstance(value, str):
67+
if max_length is not None:
68+
value = value[:max_length]
6769
return _get_string_tag(key, value)
6870
if isinstance(value, int):
6971
return _get_long_tag(key, value)
7072
if isinstance(value, float):
7173
return _get_double_tag(key, value)
7274
if isinstance(value, tuple):
73-
return _get_string_tag(key, str(value))
75+
value = str(value)
76+
if max_length is not None:
77+
value = value[:max_length]
78+
return _get_string_tag(key, value)
7479
return None
7580

7681

@@ -111,12 +116,16 @@ def _extract_tags(self, span: ReadableSpan) -> Sequence[TCollector.Tag]:
111116
translated = []
112117
if span.attributes:
113118
for key, value in span.attributes.items():
114-
tag = _translate_attribute(key, value)
119+
tag = _translate_attribute(
120+
key, value, self._max_attr_value_length
121+
)
115122
if tag:
116123
translated.append(tag)
117124
if span.resource.attributes:
118125
for key, value in span.resource.attributes.items():
119-
tag = _translate_attribute(key, value)
126+
tag = _translate_attribute(
127+
key, value, self._max_attr_value_length
128+
)
120129
if tag:
121130
translated.append(tag)
122131

@@ -185,7 +194,9 @@ def _extract_logs(
185194
for event in span.events:
186195
fields = []
187196
for key, value in event.attributes.items():
188-
tag = _translate_attribute(key, value)
197+
tag = _translate_attribute(
198+
key, value, self._max_attr_value_length
199+
)
189200
if tag:
190201
fields.append(tag)
191202

0 commit comments

Comments
 (0)