33# Modifications Copyright The OpenTelemetry Authors. Licensed under the Apache License 2.0 License.
44import os
55from logging import Logger , getLogger
6- from typing import ClassVar , Dict , Type
6+ from typing import ClassVar , Dict , List , Type , Union
77
88from importlib_metadata import version
99from typing_extensions import override
1010
11+ from amazon .opentelemetry .distro ._aws_attribute_keys import AWS_LOCAL_SERVICE
12+ from amazon .opentelemetry .distro ._aws_resource_attribute_configurator import get_service_attribute
1113from amazon .opentelemetry .distro .always_record_sampler import AlwaysRecordSampler
1214from amazon .opentelemetry .distro .attribute_propagating_span_processor_builder import (
1315 AttributePropagatingSpanProcessorBuilder ,
1820from amazon .opentelemetry .distro .aws_span_metrics_processor_builder import AwsSpanMetricsProcessorBuilder
1921from amazon .opentelemetry .distro .otlp_udp_exporter import OTLPUdpMetricExporter , OTLPUdpSpanExporter
2022from amazon .opentelemetry .distro .sampler .aws_xray_remote_sampler import AwsXRayRemoteSampler
23+ from amazon .opentelemetry .distro .scope_based_exporter import ScopeBasedPeriodicExportingMetricReader
2124from opentelemetry .exporter .otlp .proto .http .metric_exporter import OTLPMetricExporter as OTLPHttpOTLPMetricExporter
25+ from opentelemetry .metrics import set_meter_provider
2226from opentelemetry .sdk ._configuration import (
2327 _get_exporter_names ,
2428 _get_id_generator ,
2731 _import_id_generator ,
2832 _import_sampler ,
2933 _init_logging ,
30- _init_metrics ,
3134 _OTelSDKConfigurator ,
3235)
3336from opentelemetry .sdk .environment_variables import (
4851 ObservableUpDownCounter ,
4952 UpDownCounter ,
5053)
51- from opentelemetry .sdk .metrics .export import AggregationTemporality , PeriodicExportingMetricReader
54+ from opentelemetry .sdk .metrics .export import (
55+ AggregationTemporality ,
56+ MetricExporter ,
57+ MetricReader ,
58+ PeriodicExportingMetricReader ,
59+ )
60+ from opentelemetry .sdk .metrics .view import DefaultAggregation , DropAggregation , View
5261from opentelemetry .sdk .resources import Resource , get_aggregated_resources
5362from opentelemetry .sdk .trace import TracerProvider
5463from opentelemetry .sdk .trace .export import BatchSpanProcessor , SpanExporter
5766from opentelemetry .semconv .resource import ResourceAttributes
5867from opentelemetry .trace import set_tracer_provider
5968
60- APP_SIGNALS_ENABLED_CONFIG = "OTEL_AWS_APP_SIGNALS_ENABLED"
69+ DEPRECATED_APP_SIGNALS_ENABLED_CONFIG = "OTEL_AWS_APP_SIGNALS_ENABLED"
6170APPLICATION_SIGNALS_ENABLED_CONFIG = "OTEL_AWS_APPLICATION_SIGNALS_ENABLED"
62- APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG = "OTEL_AWS_APP_SIGNALS_EXPORTER_ENDPOINT"
71+ APPLICATION_SIGNALS_RUNTIME_ENABLED_CONFIG = "OTEL_AWS_APPLICATION_SIGNALS_RUNTIME_ENABLED"
72+ DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG = "OTEL_AWS_APP_SIGNALS_EXPORTER_ENDPOINT"
6373APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG = "OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT"
6474METRIC_EXPORT_INTERVAL_CONFIG = "OTEL_METRIC_EXPORT_INTERVAL"
6575DEFAULT_METRIC_EXPORT_INTERVAL = 60000.0
@@ -111,13 +121,16 @@ def _initialize_components():
111121
112122 auto_resource : Dict [str , any ] = {}
113123 auto_resource = _customize_versions (auto_resource )
114- resource = get_aggregated_resources (
115- [
116- AwsEc2ResourceDetector (),
117- AwsEksResourceDetector (),
118- AwsEcsResourceDetector (),
119- ]
120- ).merge (Resource .create (auto_resource ))
124+ # auto_resource = _set_aws_attributes(auto_resource)
125+ resource = _customize_resource (
126+ get_aggregated_resources (
127+ [
128+ AwsEc2ResourceDetector (),
129+ AwsEksResourceDetector (),
130+ AwsEcsResourceDetector (),
131+ ]
132+ ).merge (Resource .create (auto_resource ))
133+ )
121134
122135 sampler_name = _get_sampler ()
123136 sampler = _custom_import_sampler (sampler_name , resource )
@@ -159,6 +172,27 @@ def _init_tracing(
159172 set_tracer_provider (trace_provider )
160173
161174
175+ def _init_metrics (
176+ exporters_or_readers : Dict [str , Union [Type [MetricExporter ], Type [MetricReader ]]],
177+ resource : Resource = None ,
178+ ):
179+ metric_readers = []
180+ views = []
181+
182+ for _ , exporter_or_reader_class in exporters_or_readers .items ():
183+ exporter_args = {}
184+
185+ if issubclass (exporter_or_reader_class , MetricReader ):
186+ metric_readers .append (exporter_or_reader_class (** exporter_args ))
187+ else :
188+ metric_readers .append (PeriodicExportingMetricReader (exporter_or_reader_class (** exporter_args )))
189+
190+ _customize_metric_exporters (metric_readers , views )
191+
192+ provider = MeterProvider (resource = resource , metric_readers = metric_readers , views = views )
193+ set_meter_provider (provider )
194+
195+
162196# END The OpenTelemetry Authors code
163197
164198
@@ -265,14 +299,9 @@ def _customize_span_processors(provider: TracerProvider, resource: Resource) ->
265299 # Construct meterProvider
266300 _logger .info ("AWS Application Signals enabled" )
267301 otel_metric_exporter = ApplicationSignalsExporterProvider ().create_exporter ()
268- export_interval_millis = float (os .environ .get (METRIC_EXPORT_INTERVAL_CONFIG , DEFAULT_METRIC_EXPORT_INTERVAL ))
269- _logger .debug ("Span Metrics export interval: %s" , export_interval_millis )
270- # Cap export interval to 60 seconds. This is currently required for metrics-trace correlation to work correctly.
271- if export_interval_millis > DEFAULT_METRIC_EXPORT_INTERVAL :
272- export_interval_millis = DEFAULT_METRIC_EXPORT_INTERVAL
273- _logger .info ("AWS Application Signals metrics export interval capped to %s" , export_interval_millis )
302+
274303 periodic_exporting_metric_reader = PeriodicExportingMetricReader (
275- exporter = otel_metric_exporter , export_interval_millis = export_interval_millis
304+ exporter = otel_metric_exporter , export_interval_millis = _get_metric_export_interval ()
276305 )
277306 meter_provider : MeterProvider = MeterProvider (resource = resource , metric_readers = [periodic_exporting_metric_reader ])
278307 # Construct and set application signals metrics processor
@@ -281,25 +310,68 @@ def _customize_span_processors(provider: TracerProvider, resource: Resource) ->
281310 return
282311
283312
313+ def _customize_metric_exporters (metric_readers : List [MetricReader ], views : List [View ]) -> None :
314+ if _is_application_signals_runtime_enabled ():
315+ system_metrics_scope_name = "opentelemetry.instrumentation.system_metrics"
316+ if 0 == len (metric_readers ):
317+ _logger .info ("Registered scope %s" , system_metrics_scope_name )
318+ views .append (View (meter_name = system_metrics_scope_name , aggregation = DefaultAggregation ()))
319+ views .append (View (instrument_name = "*" , aggregation = DropAggregation ()))
320+
321+ otel_metric_exporter = ApplicationSignalsExporterProvider ().create_exporter ()
322+ scope_based_periodic_exporting_metric_reader = ScopeBasedPeriodicExportingMetricReader (
323+ exporter = otel_metric_exporter ,
324+ export_interval_millis = _get_metric_export_interval (),
325+ registered_scope_names = {system_metrics_scope_name },
326+ )
327+ metric_readers .append (scope_based_periodic_exporting_metric_reader )
328+
329+
284330def _customize_versions (auto_resource : Dict [str , any ]) -> Dict [str , any ]:
285331 distro_version = version ("aws-opentelemetry-distro" )
286332 auto_resource [ResourceAttributes .TELEMETRY_AUTO_VERSION ] = distro_version + "-aws"
287333 _logger .debug ("aws-opentelementry-distro - version: %s" , auto_resource [ResourceAttributes .TELEMETRY_AUTO_VERSION ])
288334 return auto_resource
289335
290336
337+ def _customize_resource (resource : Resource ) -> Resource :
338+ service_name , is_unknown = get_service_attribute (resource )
339+ if is_unknown :
340+ _logger .debug ("No valid service name found" )
341+
342+ return resource .merge (Resource .create ({AWS_LOCAL_SERVICE : service_name }))
343+
344+
291345def _is_application_signals_enabled ():
292346 return (
293- os .environ .get (APPLICATION_SIGNALS_ENABLED_CONFIG , os .environ .get (APP_SIGNALS_ENABLED_CONFIG , "false" )).lower ()
347+ os .environ .get (
348+ APPLICATION_SIGNALS_ENABLED_CONFIG , os .environ .get (DEPRECATED_APP_SIGNALS_ENABLED_CONFIG , "false" )
349+ ).lower ()
294350 == "true"
295351 )
296352
297353
354+ def _is_application_signals_runtime_enabled ():
355+ return _is_application_signals_enabled () and (
356+ os .environ .get (APPLICATION_SIGNALS_RUNTIME_ENABLED_CONFIG , "true" ).lower () == "true"
357+ )
358+
359+
298360def _is_lambda_environment ():
299361 # detect if running in AWS Lambda environment
300362 return AWS_LAMBDA_FUNCTION_NAME_CONFIG in os .environ
301363
302364
365+ def _get_metric_export_interval ():
366+ export_interval_millis = float (os .environ .get (METRIC_EXPORT_INTERVAL_CONFIG , DEFAULT_METRIC_EXPORT_INTERVAL ))
367+ _logger .debug ("Span Metrics export interval: %s" , export_interval_millis )
368+ # Cap export interval to 60 seconds. This is currently required for metrics-trace correlation to work correctly.
369+ if export_interval_millis > DEFAULT_METRIC_EXPORT_INTERVAL :
370+ export_interval_millis = DEFAULT_METRIC_EXPORT_INTERVAL
371+ _logger .info ("AWS Application Signals metrics export interval capped to %s" , export_interval_millis )
372+ return export_interval_millis
373+
374+
303375class ApplicationSignalsExporterProvider :
304376 _instance : ClassVar ["ApplicationSignalsExporterProvider" ] = None
305377
@@ -335,7 +407,7 @@ def create_exporter(self):
335407 if protocol == "http/protobuf" :
336408 application_signals_endpoint = os .environ .get (
337409 APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
338- os .environ .get (APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG , "http://localhost:4316/v1/metrics" ),
410+ os .environ .get (DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG , "http://localhost:4316/v1/metrics" ),
339411 )
340412 _logger .debug ("AWS Application Signals export endpoint: %s" , application_signals_endpoint )
341413 return OTLPHttpOTLPMetricExporter (
@@ -351,7 +423,7 @@ def create_exporter(self):
351423
352424 application_signals_endpoint = os .environ .get (
353425 APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
354- os .environ .get (APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG , "localhost:4315" ),
426+ os .environ .get (DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG , "localhost:4315" ),
355427 )
356428 _logger .debug ("AWS Application Signals export endpoint: %s" , application_signals_endpoint )
357429 return OTLPGrpcOTLPMetricExporter (
0 commit comments