Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fa19e1f

Browse files
authored
Add and use missing metrics environment variables (open-telemetry#2968)
* Add and use missing metrics environment variables Fixes open-telemetry#2967 * Add missing environment variables * Remove redundant test * Add test case for HTTPS endpoint * Fix mocks
1 parent 8beae7d commit fa19e1f

File tree

6 files changed

+234
-6
lines changed

6 files changed

+234
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.13.0...HEAD)
99

10+
- Add and use missing metrics environment variables
11+
([#2968](https://github.com/open-telemetry/opentelemetry-python/pull/2968))
1012
- Enabled custom samplers via entry points
1113
([#2972](https://github.com/open-telemetry/opentelemetry-python/pull/2972))
1214
- Update log symbol names

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

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from opentelemetry.exporter.otlp.proto.grpc.exporter import (
2121
OTLPExporterMixin,
2222
get_resource_data,
23+
_get_credentials,
24+
environ_to_compression,
2325
)
2426
from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import (
2527
ExportMetricsServiceRequest,
@@ -30,7 +32,12 @@
3032
from opentelemetry.proto.common.v1.common_pb2 import InstrumentationScope
3133
from opentelemetry.proto.metrics.v1 import metrics_pb2 as pb2
3234
from opentelemetry.sdk.environment_variables import (
35+
OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE,
36+
OTEL_EXPORTER_OTLP_METRICS_COMPRESSION,
37+
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,
38+
OTEL_EXPORTER_OTLP_METRICS_HEADERS,
3339
OTEL_EXPORTER_OTLP_METRICS_INSECURE,
40+
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
3441
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
3542
)
3643
from opentelemetry.sdk.metrics import (
@@ -65,6 +72,7 @@ class OTLPMetricExporter(
6572
"""OTLP metric exporter
6673
6774
Args:
75+
endpoint: Target URL to which the exporter is going to send metrics
6876
max_export_batch_size: Maximum number of data points to export in a single request. This is to deal with
6977
gRPC's 4MB message size limit. If not set there is no limit to the number of data points in a request.
7078
If it is set and the number of data points exceeds the max, the request will be split.
@@ -91,6 +99,25 @@ def __init__(
9199
if insecure is not None:
92100
insecure = insecure.lower() == "true"
93101

102+
if (
103+
not insecure
104+
and environ.get(OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE) is not None
105+
):
106+
credentials = _get_credentials(
107+
credentials, OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE
108+
)
109+
110+
environ_timeout = environ.get(OTEL_EXPORTER_OTLP_METRICS_TIMEOUT)
111+
environ_timeout = (
112+
int(environ_timeout) if environ_timeout is not None else None
113+
)
114+
115+
compression = (
116+
environ_to_compression(OTEL_EXPORTER_OTLP_METRICS_COMPRESSION)
117+
if compression is None
118+
else compression
119+
)
120+
94121
instrument_class_temporality = {}
95122
if (
96123
environ.get(
@@ -125,13 +152,15 @@ def __init__(
125152
preferred_temporality=instrument_class_temporality,
126153
preferred_aggregation=preferred_aggregation,
127154
)
155+
128156
OTLPExporterMixin.__init__(
129157
self,
130-
endpoint=endpoint,
158+
endpoint=endpoint
159+
or environ.get(OTEL_EXPORTER_OTLP_METRICS_ENDPOINT),
131160
insecure=insecure,
132161
credentials=credentials,
133-
headers=headers,
134-
timeout=timeout,
162+
headers=headers or environ.get(OTEL_EXPORTER_OTLP_METRICS_HEADERS),
163+
timeout=timeout or environ_timeout,
135164
compression=compression,
136165
)
137166

exporter/opentelemetry-exporter-otlp-proto-grpc/tests/metrics/__init__.py

Whitespace-only changes.

exporter/opentelemetry-exporter-otlp-proto-grpc/tests/metrics/test_otlp_metrics_exporter.py renamed to exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_metrics_exporter.py

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@
1414

1515
# pylint: disable=too-many-lines
1616
from concurrent.futures import ThreadPoolExecutor
17+
from os.path import dirname
1718
from typing import List
1819
from unittest import TestCase
1920
from unittest.mock import patch
2021

2122
from google.protobuf.duration_pb2 import Duration
2223
from google.rpc.error_details_pb2 import RetryInfo
23-
from grpc import StatusCode, server
24+
from grpc import ChannelCredentials, Compression, StatusCode, server
2425

2526
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
2627
OTLPMetricExporter,
@@ -43,8 +44,14 @@
4344
Resource as OTLPResource,
4445
)
4546
from opentelemetry.sdk.environment_variables import (
47+
OTEL_EXPORTER_OTLP_COMPRESSION,
48+
OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE,
49+
OTEL_EXPORTER_OTLP_METRICS_COMPRESSION,
50+
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,
51+
OTEL_EXPORTER_OTLP_METRICS_HEADERS,
4652
OTEL_EXPORTER_OTLP_METRICS_INSECURE,
4753
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
54+
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
4855
)
4956
from opentelemetry.sdk.metrics import (
5057
Counter,
@@ -71,6 +78,8 @@
7178
)
7279
from opentelemetry.test.metrictestutil import _generate_gauge, _generate_sum
7380

81+
THIS_DIR = dirname(__file__)
82+
7483

7584
class MetricsServiceServicerUNAVAILABLEDelay(MetricsServiceServicer):
7685
# pylint: disable=invalid-name,unused-argument,no-self-use
@@ -119,6 +128,8 @@ def Export(self, request, context):
119128

120129

121130
class TestOTLPMetricExporter(TestCase):
131+
# pylint: disable=too-many-public-methods
132+
122133
def setUp(self):
123134

124135
self.exporter = OTLPMetricExporter()
@@ -348,6 +359,33 @@ def test_preferred_temporality(self):
348359
AggregationTemporality.CUMULATIVE,
349360
)
350361

362+
@patch.dict(
363+
"os.environ",
364+
{
365+
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: "collector:4317",
366+
OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE: THIS_DIR
367+
+ "/fixtures/test.cert",
368+
OTEL_EXPORTER_OTLP_METRICS_HEADERS: " key1=value1,KEY2 = value=2",
369+
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT: "10",
370+
OTEL_EXPORTER_OTLP_METRICS_COMPRESSION: "gzip",
371+
},
372+
)
373+
@patch(
374+
"opentelemetry.exporter.otlp.proto.grpc.exporter.OTLPExporterMixin.__init__"
375+
)
376+
def test_env_variables(self, mock_exporter_mixin):
377+
OTLPMetricExporter()
378+
379+
self.assertTrue(len(mock_exporter_mixin.call_args_list) == 1)
380+
_, kwargs = mock_exporter_mixin.call_args_list[0]
381+
382+
self.assertEqual(kwargs["endpoint"], "collector:4317")
383+
self.assertEqual(kwargs["headers"], " key1=value1,KEY2 = value=2")
384+
self.assertEqual(kwargs["timeout"], 10)
385+
self.assertEqual(kwargs["compression"], Compression.Gzip)
386+
self.assertIsNotNone(kwargs["credentials"])
387+
self.assertIsInstance(kwargs["credentials"], ChannelCredentials)
388+
351389
@patch(
352390
"opentelemetry.exporter.otlp.proto.grpc.exporter.ssl_channel_credentials"
353391
)
@@ -362,6 +400,29 @@ def test_no_credentials_error(
362400
OTLPMetricExporter(insecure=False)
363401
self.assertTrue(mock_ssl_channel.called)
364402

403+
@patch.dict(
404+
"os.environ",
405+
{OTEL_EXPORTER_OTLP_METRICS_HEADERS: " key1=value1,KEY2 = VALUE=2 "},
406+
)
407+
@patch(
408+
"opentelemetry.exporter.otlp.proto.grpc.exporter.ssl_channel_credentials"
409+
)
410+
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.secure_channel")
411+
# pylint: disable=unused-argument
412+
def test_otlp_headers_from_env(self, mock_ssl_channel, mock_secure):
413+
exporter = OTLPMetricExporter()
414+
# pylint: disable=protected-access
415+
self.assertEqual(
416+
exporter._headers, (("key1", "value1"), ("key2", "VALUE=2"))
417+
)
418+
exporter = OTLPMetricExporter(
419+
headers=(("key3", "value3"), ("key4", "value4"))
420+
)
421+
# pylint: disable=protected-access
422+
self.assertEqual(
423+
exporter._headers, (("key3", "value3"), ("key4", "value4"))
424+
)
425+
365426
@patch.dict(
366427
"os.environ",
367428
{OTEL_EXPORTER_OTLP_METRICS_INSECURE: "True"},
@@ -449,6 +510,43 @@ def test_otlp_exporter_endpoint(self, mock_secure, mock_insecure):
449510
)
450511
mock_method.reset_mock()
451512

513+
# pylint: disable=no-self-use
514+
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter._expo")
515+
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.insecure_channel")
516+
@patch.dict("os.environ", {OTEL_EXPORTER_OTLP_COMPRESSION: "gzip"})
517+
def test_otlp_exporter_otlp_compression_envvar(
518+
self, mock_insecure_channel, mock_expo
519+
):
520+
"""Just OTEL_EXPORTER_OTLP_COMPRESSION should work"""
521+
OTLPMetricExporter(insecure=True)
522+
mock_insecure_channel.assert_called_once_with(
523+
"localhost:4317", compression=Compression.Gzip
524+
)
525+
526+
# pylint: disable=no-self-use
527+
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.insecure_channel")
528+
@patch.dict("os.environ", {OTEL_EXPORTER_OTLP_COMPRESSION: "gzip"})
529+
def test_otlp_exporter_otlp_compression_kwarg(self, mock_insecure_channel):
530+
"""Specifying kwarg should take precedence over env"""
531+
OTLPMetricExporter(
532+
insecure=True, compression=Compression.NoCompression
533+
)
534+
mock_insecure_channel.assert_called_once_with(
535+
"localhost:4317", compression=Compression.NoCompression
536+
)
537+
538+
# pylint: disable=no-self-use
539+
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.insecure_channel")
540+
@patch.dict("os.environ", {})
541+
def test_otlp_exporter_otlp_compression_unspecified(
542+
self, mock_insecure_channel
543+
):
544+
"""No env or kwarg should be NoCompression"""
545+
OTLPMetricExporter(insecure=True)
546+
mock_insecure_channel.assert_called_once_with(
547+
"localhost:4317", compression=Compression.NoCompression
548+
)
549+
452550
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter._expo")
453551
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.sleep")
454552
def test_unavailable(self, mock_sleep, mock_expo):
@@ -1243,6 +1341,11 @@ def test_split_metrics_data_many_resources_scopes_metrics(self):
12431341
split_metrics_data,
12441342
)
12451343

1344+
@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.secure_channel")
1345+
def test_insecure_https_endpoint(self, mock_secure_channel):
1346+
OTLPMetricExporter(endpoint="https://ab.c:123", insecure=True)
1347+
mock_secure_channel.assert_called()
1348+
12461349

12471350
def _resource_metrics(
12481351
index: int, scope_metrics: List[ScopeMetrics]

opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,15 @@
335335
A scheme of https indicates a secure connection and takes precedence over this configuration setting.
336336
"""
337337

338+
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"
339+
"""
340+
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
341+
342+
The :envvar:`OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` target to which the metrics exporter is going to send metrics.
343+
The endpoint MUST be a valid URL host, and MAY contain a scheme (http or https), port and path.
344+
A scheme of https indicates a secure connection and takes precedence over this configuration setting.
345+
"""
346+
338347
OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = "OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE"
339348
"""
340349
.. envvar:: OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE
@@ -343,6 +352,16 @@
343352
TLS credentials of gRPC client for traces. Should only be used for a secure connection for tracing.
344353
"""
345354

355+
OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE = (
356+
"OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE"
357+
)
358+
"""
359+
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE
360+
361+
The :envvar:`OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE` stores the path to the certificate file for
362+
TLS credentials of gRPC client for metrics. Should only be used for a secure connection for exporting metrics.
363+
"""
364+
346365
OTEL_EXPORTER_OTLP_TRACES_HEADERS = "OTEL_EXPORTER_OTLP_TRACES_HEADERS"
347366
"""
348367
.. envvar:: OTEL_EXPORTER_OTLP_TRACES_HEADERS
@@ -351,6 +370,13 @@
351370
associated with gRPC or HTTP requests.
352371
"""
353372

373+
OTEL_EXPORTER_OTLP_METRICS_HEADERS = "OTEL_EXPORTER_OTLP_METRICS_HEADERS"
374+
"""
375+
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_HEADERS
376+
377+
The :envvar:`OTEL_EXPORTER_OTLP_METRICS_HEADERS` contains the key-value pairs to be used as headers for metrics
378+
associated with gRPC or HTTP requests.
379+
"""
354380

355381
OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = "OTEL_EXPORTER_OTLP_TRACES_COMPRESSION"
356382
"""
@@ -360,6 +386,16 @@
360386
exporter. If both are present, this takes higher precedence.
361387
"""
362388

389+
OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = (
390+
"OTEL_EXPORTER_OTLP_METRICS_COMPRESSION"
391+
)
392+
"""
393+
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_COMPRESSION
394+
395+
Same as :envvar:`OTEL_EXPORTER_OTLP_COMPRESSION` but only for the metric
396+
exporter. If both are present, this takes higher precedence.
397+
"""
398+
363399
OTEL_EXPORTER_OTLP_TRACES_TIMEOUT = "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT"
364400
"""
365401
.. envvar:: OTEL_EXPORTER_OTLP_TRACES_TIMEOUT
@@ -368,6 +404,14 @@
368404
wait for each batch export for spans.
369405
"""
370406

407+
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT"
408+
"""
409+
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_TIMEOUT
410+
411+
The :envvar:`OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` is the maximum time the OTLP exporter will
412+
wait for each batch export for metrics.
413+
"""
414+
371415
OTEL_EXPORTER_OTLP_METRICS_INSECURE = "OTEL_EXPORTER_OTLP_METRICS_INSECURE"
372416
"""
373417
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_INSECURE
@@ -501,3 +545,49 @@
501545
502546
The :envvar:`OTEL_EXPORTER_JAEGER_GRPC_INSECURE` is a boolean flag to True if collector has no encryption or authentication.
503547
"""
548+
549+
OTEL_METRIC_EXPORT_INTERVAL = "OTEL_METRIC_EXPORT_INTERVAL"
550+
"""
551+
.. envvar:: OTEL_METRIC_EXPORT_INTERVAL
552+
553+
The :envvar:`OTEL_METRIC_EXPORT_INTERVAL` is the time interval (in milliseconds) between the start of two export attempts.
554+
"""
555+
556+
OTEL_METRIC_EXPORT_TIMEOUT = "OTEL_METRIC_EXPORT_TIMEOUT"
557+
"""
558+
.. envvar:: OTEL_METRIC_EXPORT_TIMEOUT
559+
560+
The :envvar:`OTEL_METRIC_EXPORT_TIMEOUT` is the maximum allowed time (in milliseconds) to export data.
561+
"""
562+
563+
OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY = "OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY"
564+
"""
565+
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY
566+
567+
The :envvar:`OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY` is the clients private key to use in mTLS communication in PEM format.
568+
"""
569+
570+
OTEL_METRICS_EXEMPLAR_FILTER = "OTEL_METRICS_EXEMPLAR_FILTER"
571+
"""
572+
.. envvar:: OTEL_METRICS_EXEMPLAR_FILTER
573+
574+
The :envvar:`OTEL_METRICS_EXEMPLAR_FILTER` is the filter for which measurements can become Exemplars.
575+
"""
576+
577+
_OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION = (
578+
"OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION"
579+
)
580+
"""
581+
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION
582+
583+
The :envvar:`OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION` is the default aggregation to use for histogram instruments.
584+
"""
585+
586+
OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE = (
587+
"OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE"
588+
)
589+
"""
590+
.. envvar:: OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE
591+
592+
The :envvar:`OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE` is the client certificate/chain trust for clients private key to use in mTLS communication in PEM format.
593+
"""

0 commit comments

Comments
 (0)