Skip to content

Commit 7c2cf63

Browse files
committed
Prometheus exporter support for auto instrumentation
1 parent 13d5735 commit 7c2cf63

File tree

4 files changed

+123
-10
lines changed

4 files changed

+123
-10
lines changed

exporter/opentelemetry-exporter-prometheus/pyproject.toml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@ classifiers = [
2626
]
2727
dependencies = [
2828
"opentelemetry-api ~= 1.12",
29-
"opentelemetry-sdk ~= 1.12",
29+
# DONOTMERGE: confirm that this will becomes ~= 1.20 in the next release
30+
"opentelemetry-sdk ~= 1.20.0.dev",
3031
"prometheus_client >= 0.5.0, < 1.0.0",
3132
]
3233

3334
[project.optional-dependencies]
3435
test = []
3536

36-
[project.entry-points.opentelemetry_metric_reader]
37-
prometheus = "opentelemetry.exporter.prometheus:PrometheusMetricReader"
37+
[project.entry-points.opentelemetry_metrics_exporter]
38+
prometheus = "opentelemetry.exporter.prometheus:_prometheus_metric_exporter_entrypoint"
3839

3940
[project.urls]
4041
Homepage = "https://github.com/open-telemetry/opentelemetry-python/tree/main/exporter/opentelemetry-exporter-prometheus"
@@ -43,10 +44,7 @@ Homepage = "https://github.com/open-telemetry/opentelemetry-python/tree/main/exp
4344
path = "src/opentelemetry/exporter/prometheus/version.py"
4445

4546
[tool.hatch.build.targets.sdist]
46-
include = [
47-
"/src",
48-
"/tests",
49-
]
47+
include = ["/src", "/tests"]
5048

5149
[tool.hatch.build.targets.wheel]
5250
packages = ["src/opentelemetry"]

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@
6666
from itertools import chain
6767
from json import dumps
6868
from logging import getLogger
69+
from os import environ
6970
from re import IGNORECASE, UNICODE, compile
7071
from typing import Dict, Sequence, Tuple, Union
7172

73+
from prometheus_client import start_http_server
7274
from prometheus_client.core import (
7375
REGISTRY,
7476
CounterMetricFamily,
@@ -78,6 +80,10 @@
7880
)
7981
from prometheus_client.core import Metric as PrometheusMetric
8082

83+
from opentelemetry.sdk.environment_variables import (
84+
OTEL_EXPORTER_PROMETHEUS_HOST,
85+
OTEL_EXPORTER_PROMETHEUS_PORT,
86+
)
8187
from opentelemetry.sdk.metrics import Counter
8288
from opentelemetry.sdk.metrics import Histogram as HistogramInstrument
8389
from opentelemetry.sdk.metrics import (
@@ -282,7 +288,6 @@ def _translate_to_prometheus(
282288
isinstance(metric.data, Sum)
283289
and not should_convert_sum_to_gauge
284290
):
285-
286291
metric_family_id = "|".join(
287292
[pre_metric_family_id, CounterMetricFamily.__name__]
288293
)
@@ -303,7 +308,6 @@ def _translate_to_prometheus(
303308
isinstance(metric.data, Gauge)
304309
or should_convert_sum_to_gauge
305310
):
306-
307311
metric_family_id = "|".join(
308312
[pre_metric_family_id, GaugeMetricFamily.__name__]
309313
)
@@ -324,7 +328,6 @@ def _translate_to_prometheus(
324328
metric_family_id
325329
].add_metric(labels=label_values, value=value)
326330
elif isinstance(metric.data, Histogram):
327-
328331
metric_family_id = "|".join(
329332
[pre_metric_family_id, HistogramMetricFamily.__name__]
330333
)
@@ -375,3 +378,18 @@ def _create_info_metric(
375378
info = InfoMetricFamily(name, description, labels=attributes)
376379
info.add_metric(labels=list(attributes.keys()), value=attributes)
377380
return info
381+
382+
383+
def _prometheus_metric_exporter_entrypoint() -> MetricReader:
384+
"""Implementation of opentelemetry_metrics_exporter entrypoint for prometheus exporter
385+
386+
This allows users to use the prometheus exporter with opentelemetry-instrument.
387+
"""
388+
389+
# Default values are specified in
390+
# https://github.com/open-telemetry/opentelemetry-specification/blob/v1.24.0/specification/configuration/sdk-environment-variables.md#prometheus-exporter
391+
start_http_server(
392+
port=int(environ.get(OTEL_EXPORTER_PROMETHEUS_PORT, "9464")),
393+
addr=environ.get(OTEL_EXPORTER_PROMETHEUS_HOST, "localhost"),
394+
)
395+
return PrometheusMetricReader()
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# pylint: disable=no-self-use
16+
17+
import os
18+
from unittest import TestCase
19+
from unittest.mock import ANY, Mock, patch
20+
21+
from opentelemetry.exporter.prometheus import (
22+
_prometheus_metric_exporter_entrypoint,
23+
)
24+
from opentelemetry.sdk._configuration import _import_exporters
25+
from opentelemetry.sdk.environment_variables import (
26+
OTEL_EXPORTER_PROMETHEUS_HOST,
27+
OTEL_EXPORTER_PROMETHEUS_PORT,
28+
)
29+
30+
31+
class TestEntrypoints(TestCase):
32+
def test_import_exporters(self) -> None:
33+
"""
34+
Tests that the entrypoint can be loaded and doesnt't have a typo in the name
35+
"""
36+
(
37+
_trace_exporters,
38+
metric_exporters,
39+
_logs_exporters,
40+
) = _import_exporters(
41+
trace_exporter_names=[],
42+
metric_exporter_names=["prometheus"],
43+
log_exporter_names=[],
44+
)
45+
46+
self.assertEqual(
47+
metric_exporters,
48+
{"prometheus": _prometheus_metric_exporter_entrypoint},
49+
)
50+
51+
@patch("opentelemetry.exporter.prometheus.start_http_server")
52+
@patch.dict(os.environ)
53+
def test_starts_http_server_defaults(
54+
self, mock_start_http_server: Mock
55+
) -> None:
56+
_prometheus_metric_exporter_entrypoint()
57+
mock_start_http_server.assert_called_once_with(
58+
port=9464, addr="localhost"
59+
)
60+
61+
@patch("opentelemetry.exporter.prometheus.start_http_server")
62+
@patch.dict(os.environ, {OTEL_EXPORTER_PROMETHEUS_HOST: "1.2.3.4"})
63+
def test_starts_http_server_host_envvar(
64+
self, mock_start_http_server: Mock
65+
) -> None:
66+
_prometheus_metric_exporter_entrypoint()
67+
mock_start_http_server.assert_called_once_with(
68+
port=ANY, addr="1.2.3.4"
69+
)
70+
71+
@patch("opentelemetry.exporter.prometheus.start_http_server")
72+
@patch.dict(os.environ, {OTEL_EXPORTER_PROMETHEUS_PORT: "9999"})
73+
def test_starts_http_server_port_envvar(
74+
self, mock_start_http_server: Mock
75+
) -> None:
76+
_prometheus_metric_exporter_entrypoint()
77+
mock_start_http_server.assert_called_once_with(port=9999, addr=ANY)

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,23 @@
678678
experimental feature and the name of this variable and its behavior can change
679679
in a non-backwards compatible way.
680680
"""
681+
682+
OTEL_EXPORTER_PROMETHEUS_HOST = "OTEL_EXPORTER_PROMETHEUS_HOST"
683+
"""
684+
.. envvar:: OTEL_EXPORTER_PROMETHEUS_HOST
685+
686+
The :envvar::`OTEL_EXPORTER_PROMETHEUS_HOST` environment variable configures the host used by
687+
the Prometheus exporter. The default value is "localhost". This is an experimental environment
688+
variable and the name of this variable and its behavior can change in a non-backwards
689+
compatible way.
690+
"""
691+
692+
OTEL_EXPORTER_PROMETHEUS_PORT = "OTEL_EXPORTER_PROMETHEUS_PORT"
693+
"""
694+
.. envvar:: OTEL_EXPORTER_PROMETHEUS_PORT
695+
696+
The :envvar::`OTEL_EXPORTER_PROMETHEUS_PORT` environment variable configures the port used by
697+
the Prometheus exporter. The default value is 9464. This is an experimental environment
698+
variable and the name of this variable and its behavior can change in a non-backwards
699+
compatible way.
700+
"""

0 commit comments

Comments
 (0)