Skip to content

Commit edf4d6c

Browse files
authored
Adds user agent string to grpc headers (#3009)
1 parent e4a4410 commit edf4d6c

File tree

6 files changed

+58
-6
lines changed

6 files changed

+58
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121
([#3038](https://github.com/open-telemetry/opentelemetry-python/pull/3038))
2222
- Fix: Avoid generator in metrics _ViewInstrumentMatch.collect()
2323
([#3035](https://github.com/open-telemetry/opentelemetry-python/pull/3035)
24+
- [exporter-otlp-proto-grpc] add user agent string
25+
([#3009](https://github.com/open-telemetry/opentelemetry-python/pull/3009))
2426

2527
## Version 1.14.0/0.35b0 (2022-11-04)
2628

exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,7 @@
6969
API
7070
---
7171
"""
72+
from .version import __version__
73+
74+
_USER_AGENT_HEADER_VALUE = "OTel OTLP Exporter Python/" + __version__
75+
_OTLP_GRPC_HEADERS = [("user-agent", _USER_AGENT_HEADER_VALUE)]

exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454
from opentelemetry.sdk.resources import Resource as SDKResource
5555
from opentelemetry.sdk.metrics.export import MetricsData
5656
from opentelemetry.util.re import parse_env_headers
57+
from opentelemetry.exporter.otlp.proto.grpc import (
58+
_OTLP_GRPC_HEADERS,
59+
)
5760

5861
logger = getLogger(__name__)
5962
SDKDataT = TypeVar("SDKDataT")
@@ -251,6 +254,10 @@ def __init__(
251254
self._headers = tuple(temp_headers.items())
252255
elif isinstance(self._headers, dict):
253256
self._headers = tuple(self._headers.items())
257+
if self._headers is None:
258+
self._headers = tuple(_OTLP_GRPC_HEADERS)
259+
else:
260+
self._headers = self._headers + tuple(_OTLP_GRPC_HEADERS)
254261

255262
self._timeout = timeout or int(
256263
environ.get(OTEL_EXPORTER_OTLP_TIMEOUT, 10)

exporter/opentelemetry-exporter-otlp-proto-grpc/tests/logs/test_otlp_logs_exporter.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
OTLPLogExporter,
2727
)
2828
from opentelemetry.exporter.otlp.proto.grpc.exporter import _translate_value
29+
from opentelemetry.exporter.otlp.proto.grpc.version import __version__
2930
from opentelemetry.proto.collector.logs.v1.logs_service_pb2 import (
3031
ExportLogsServiceRequest,
3132
ExportLogsServiceResponse,
@@ -249,6 +250,13 @@ def test_otlp_exporter_endpoint(self, mock_secure, mock_insecure):
249250
)
250251
mock_method.reset_mock()
251252

253+
def test_otlp_headers_from_env(self):
254+
# pylint: disable=protected-access
255+
self.assertEqual(
256+
self.exporter._headers,
257+
(("user-agent", "OTel OTLP Exporter Python/" + __version__),),
258+
)
259+
252260
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter._expo")
253261
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.sleep")
254262
def test_unavailable(self, mock_sleep, mock_expo):

exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_metrics_exporter.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
2727
OTLPMetricExporter,
2828
)
29+
from opentelemetry.exporter.otlp.proto.grpc.version import __version__
2930
from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import (
3031
ExportMetricsServiceRequest,
3132
ExportMetricsServiceResponse,
@@ -413,14 +414,24 @@ def test_otlp_headers_from_env(self, mock_ssl_channel, mock_secure):
413414
exporter = OTLPMetricExporter()
414415
# pylint: disable=protected-access
415416
self.assertEqual(
416-
exporter._headers, (("key1", "value1"), ("key2", "VALUE=2"))
417+
exporter._headers,
418+
(
419+
("key1", "value1"),
420+
("key2", "VALUE=2"),
421+
("user-agent", "OTel OTLP Exporter Python/" + __version__),
422+
),
417423
)
418424
exporter = OTLPMetricExporter(
419425
headers=(("key3", "value3"), ("key4", "value4"))
420426
)
421427
# pylint: disable=protected-access
422428
self.assertEqual(
423-
exporter._headers, (("key3", "value3"), ("key4", "value4"))
429+
exporter._headers,
430+
(
431+
("key3", "value3"),
432+
("key4", "value4"),
433+
("user-agent", "OTel OTLP Exporter Python/" + __version__),
434+
),
424435
)
425436

426437
@patch.dict(

exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
3030
OTLPSpanExporter,
3131
)
32+
from opentelemetry.exporter.otlp.proto.grpc.version import __version__
3233
from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
3334
ExportTraceServiceRequest,
3435
ExportTraceServiceResponse,
@@ -275,21 +276,36 @@ def test_otlp_headers_from_env(self, mock_ssl_channel, mock_secure):
275276
exporter = OTLPSpanExporter()
276277
# pylint: disable=protected-access
277278
self.assertEqual(
278-
exporter._headers, (("key1", "value1"), ("key2", "VALUE=2"))
279+
exporter._headers,
280+
(
281+
("key1", "value1"),
282+
("key2", "VALUE=2"),
283+
("user-agent", "OTel OTLP Exporter Python/" + __version__),
284+
),
279285
)
280286
exporter = OTLPSpanExporter(
281287
headers=(("key3", "value3"), ("key4", "value4"))
282288
)
283289
# pylint: disable=protected-access
284290
self.assertEqual(
285-
exporter._headers, (("key3", "value3"), ("key4", "value4"))
291+
exporter._headers,
292+
(
293+
("key3", "value3"),
294+
("key4", "value4"),
295+
("user-agent", "OTel OTLP Exporter Python/" + __version__),
296+
),
286297
)
287298
exporter = OTLPSpanExporter(
288299
headers={"key5": "value5", "key6": "value6"}
289300
)
290301
# pylint: disable=protected-access
291302
self.assertEqual(
292-
exporter._headers, (("key5", "value5"), ("key6", "value6"))
303+
exporter._headers,
304+
(
305+
("key5", "value5"),
306+
("key6", "value6"),
307+
("user-agent", "OTel OTLP Exporter Python/" + __version__),
308+
),
293309
)
294310

295311
@patch.dict(
@@ -434,7 +450,11 @@ def test_otlp_exporter_otlp_compression_precendence(
434450
def test_otlp_headers(self, mock_ssl_channel, mock_secure):
435451
exporter = OTLPSpanExporter()
436452
# pylint: disable=protected-access
437-
self.assertIsNone(exporter._headers, None)
453+
# This ensures that there is no other header than standard user-agent.
454+
self.assertEqual(
455+
exporter._headers,
456+
(("user-agent", "OTel OTLP Exporter Python/" + __version__),),
457+
)
438458

439459
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.backoff")
440460
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.sleep")

0 commit comments

Comments
 (0)