1818"""
1919
2020import logging
21+ import os
2122from abc import ABC , abstractmethod
2223from os import environ
2324from typing import Dict , Optional , Sequence , Tuple , Type
2425
2526from pkg_resources import iter_entry_points
2627
27- from opentelemetry import trace
2828from opentelemetry .environment_variables import (
2929 OTEL_LOGS_EXPORTER ,
30+ OTEL_METRICS_EXPORTER ,
3031 OTEL_PYTHON_ID_GENERATOR ,
3132 OTEL_TRACES_EXPORTER ,
3233)
34+ from opentelemetry .metrics import set_meter_provider
3335from opentelemetry .sdk ._logs import (
3436 LogEmitterProvider ,
3537 LoggingHandler ,
3638 set_log_emitter_provider ,
3739)
3840from opentelemetry .sdk ._logs .export import BatchLogProcessor , LogExporter
41+ from opentelemetry .sdk .environment_variables import (
42+ _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED ,
43+ )
44+ from opentelemetry .sdk .metrics import MeterProvider
45+ from opentelemetry .sdk .metrics .export import (
46+ MetricExporter ,
47+ PeriodicExportingMetricReader ,
48+ )
3949from opentelemetry .sdk .resources import Resource
4050from opentelemetry .sdk .trace import TracerProvider
4151from opentelemetry .sdk .trace .export import BatchSpanProcessor , SpanExporter
4252from opentelemetry .sdk .trace .id_generator import IdGenerator
4353from opentelemetry .semconv .resource import ResourceAttributes
54+ from opentelemetry .trace import set_tracer_provider
4455
4556_EXPORTER_OTLP = "otlp"
4657_EXPORTER_OTLP_PROTO_GRPC = "otlp_proto_grpc"
@@ -83,7 +94,7 @@ def _init_tracing(
8394 id_generator = id_generator (),
8495 resource = Resource .create (auto_resource ),
8596 )
86- trace . set_tracer_provider (provider )
97+ set_tracer_provider (provider )
8798
8899 for _ , exporter_class in exporters .items ():
89100 exporter_args = {}
@@ -92,6 +103,33 @@ def _init_tracing(
92103 )
93104
94105
106+ def _init_metrics (
107+ exporters : Dict [str , Type [MetricExporter ]],
108+ auto_instrumentation_version : Optional [str ] = None ,
109+ ):
110+ # if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name
111+ # from the env variable else defaults to "unknown_service"
112+ auto_resource = {}
113+ # populate version if using auto-instrumentation
114+ if auto_instrumentation_version :
115+ auto_resource [
116+ ResourceAttributes .TELEMETRY_AUTO_VERSION
117+ ] = auto_instrumentation_version
118+
119+ metric_readers = []
120+
121+ for _ , exporter_class in exporters .items ():
122+ exporter_args = {}
123+ metric_readers .append (
124+ PeriodicExportingMetricReader (exporter_class (** exporter_args ))
125+ )
126+
127+ provider = MeterProvider (
128+ resource = Resource .create (auto_resource ), metric_readers = metric_readers
129+ )
130+ set_meter_provider (provider )
131+
132+
95133def _init_logging (
96134 exporters : Dict [str , Type [LogExporter ]],
97135 auto_instrumentation_version : Optional [str ] = None ,
@@ -141,9 +179,15 @@ def _import_config_components(
141179
142180def _import_exporters (
143181 trace_exporter_names : Sequence [str ],
182+ metric_exporter_names : Sequence [str ],
144183 log_exporter_names : Sequence [str ],
145- ) -> Tuple [Dict [str , Type [SpanExporter ]], Dict [str , Type [LogExporter ]]]:
184+ ) -> Tuple [
185+ Dict [str , Type [SpanExporter ]],
186+ Dict [str , Type [MetricExporter ]],
187+ Dict [str , Type [LogExporter ]],
188+ ]:
146189 trace_exporters = {}
190+ metric_exporters = {}
147191 log_exporters = {}
148192
149193 for (exporter_name , exporter_impl ,) in _import_config_components (
@@ -154,6 +198,14 @@ def _import_exporters(
154198 else :
155199 raise RuntimeError (f"{ exporter_name } is not a trace exporter" )
156200
201+ for (exporter_name , exporter_impl ,) in _import_config_components (
202+ metric_exporter_names , "opentelemetry_metrics_exporter"
203+ ):
204+ if issubclass (exporter_impl , MetricExporter ):
205+ metric_exporters [exporter_name ] = exporter_impl
206+ else :
207+ raise RuntimeError (f"{ exporter_name } is not a metric exporter" )
208+
157209 for (exporter_name , exporter_impl ,) in _import_config_components (
158210 log_exporter_names , "opentelemetry_logs_exporter"
159211 ):
@@ -162,7 +214,7 @@ def _import_exporters(
162214 else :
163215 raise RuntimeError (f"{ exporter_name } is not a log exporter" )
164216
165- return trace_exporters , log_exporters
217+ return trace_exporters , metric_exporters , log_exporters
166218
167219
168220def _import_id_generator (id_generator_name : str ) -> IdGenerator :
@@ -178,14 +230,20 @@ def _import_id_generator(id_generator_name: str) -> IdGenerator:
178230
179231
180232def _initialize_components (auto_instrumentation_version ):
181- trace_exporters , log_exporters = _import_exporters (
233+ trace_exporters , metric_exporters , log_exporters = _import_exporters (
182234 _get_exporter_names (environ .get (OTEL_TRACES_EXPORTER )),
235+ _get_exporter_names (environ .get (OTEL_METRICS_EXPORTER )),
183236 _get_exporter_names (environ .get (OTEL_LOGS_EXPORTER )),
184237 )
185238 id_generator_name = _get_id_generator ()
186239 id_generator = _import_id_generator (id_generator_name )
187240 _init_tracing (trace_exporters , id_generator , auto_instrumentation_version )
188- _init_logging (log_exporters , auto_instrumentation_version )
241+ _init_metrics (metric_exporters , auto_instrumentation_version )
242+ logging_enabled = os .getenv (
243+ _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED , "false"
244+ )
245+ if logging_enabled .strip ().lower () == "true" :
246+ _init_logging (log_exporters , auto_instrumentation_version )
189247
190248
191249class _BaseConfigurator (ABC ):
0 commit comments