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 ,
1921from amazon .opentelemetry .distro .aws_span_metrics_processor_builder import AwsSpanMetricsProcessorBuilder
2022from amazon .opentelemetry .distro .otlp_udp_exporter import OTLPUdpMetricExporter , OTLPUdpSpanExporter
2123from amazon .opentelemetry .distro .sampler .aws_xray_remote_sampler import AwsXRayRemoteSampler
24+ from amazon .opentelemetry .distro .scope_based_exporter import ScopeBasedPeriodicExportingMetricReader
2225from opentelemetry .exporter .otlp .proto .http .metric_exporter import OTLPMetricExporter as OTLPHttpOTLPMetricExporter
26+ from opentelemetry .metrics import set_meter_provider
2327from opentelemetry .sdk ._configuration import (
2428 _get_exporter_names ,
2529 _get_id_generator ,
2832 _import_id_generator ,
2933 _import_sampler ,
3034 _init_logging ,
31- _init_metrics ,
3235 _OTelSDKConfigurator ,
3336)
3437from opentelemetry .sdk .environment_variables import (
4952 ObservableUpDownCounter ,
5053 UpDownCounter ,
5154)
52- from opentelemetry .sdk .metrics .export import AggregationTemporality , PeriodicExportingMetricReader
55+ from opentelemetry .sdk .metrics .export import (
56+ AggregationTemporality ,
57+ MetricExporter ,
58+ MetricReader ,
59+ PeriodicExportingMetricReader ,
60+ )
61+ from opentelemetry .sdk .metrics .view import DefaultAggregation , DropAggregation , View
5362from opentelemetry .sdk .resources import Resource , get_aggregated_resources
5463from opentelemetry .sdk .trace import TracerProvider
5564from opentelemetry .sdk .trace .export import BatchSpanProcessor , SpanExporter
5867from opentelemetry .semconv .resource import ResourceAttributes
5968from opentelemetry .trace import set_tracer_provider
6069
61- APP_SIGNALS_ENABLED_CONFIG = "OTEL_AWS_APP_SIGNALS_ENABLED"
70+ DEPRECATED_APP_SIGNALS_ENABLED_CONFIG = "OTEL_AWS_APP_SIGNALS_ENABLED"
6271APPLICATION_SIGNALS_ENABLED_CONFIG = "OTEL_AWS_APPLICATION_SIGNALS_ENABLED"
63- APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG = "OTEL_AWS_APP_SIGNALS_EXPORTER_ENDPOINT"
72+ APPLICATION_SIGNALS_RUNTIME_ENABLED_CONFIG = "OTEL_AWS_APPLICATION_SIGNALS_RUNTIME_ENABLED"
73+ DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG = "OTEL_AWS_APP_SIGNALS_EXPORTER_ENDPOINT"
6474APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG = "OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT"
6575METRIC_EXPORT_INTERVAL_CONFIG = "OTEL_METRIC_EXPORT_INTERVAL"
6676DEFAULT_METRIC_EXPORT_INTERVAL = 60000.0
@@ -112,13 +122,16 @@ def _initialize_components():
112122
113123 auto_resource : Dict [str , any ] = {}
114124 auto_resource = _customize_versions (auto_resource )
115- resource = get_aggregated_resources (
116- [
117- AwsEc2ResourceDetector (),
118- AwsEksResourceDetector (),
119- AwsEcsResourceDetector (),
120- ]
121- ).merge (Resource .create (auto_resource ))
125+ # auto_resource = _set_aws_attributes(auto_resource)
126+ resource = _customize_resource (
127+ get_aggregated_resources (
128+ [
129+ AwsEc2ResourceDetector (),
130+ AwsEksResourceDetector (),
131+ AwsEcsResourceDetector (),
132+ ]
133+ ).merge (Resource .create (auto_resource ))
134+ )
122135
123136 sampler_name = _get_sampler ()
124137 sampler = _custom_import_sampler (sampler_name , resource )
@@ -160,6 +173,27 @@ def _init_tracing(
160173 set_tracer_provider (trace_provider )
161174
162175
176+ def _init_metrics (
177+ exporters_or_readers : Dict [str , Union [Type [MetricExporter ], Type [MetricReader ]]],
178+ resource : Resource = None ,
179+ ):
180+ metric_readers = []
181+ views = []
182+
183+ for _ , exporter_or_reader_class in exporters_or_readers .items ():
184+ exporter_args = {}
185+
186+ if issubclass (exporter_or_reader_class , MetricReader ):
187+ metric_readers .append (exporter_or_reader_class (** exporter_args ))
188+ else :
189+ metric_readers .append (PeriodicExportingMetricReader (exporter_or_reader_class (** exporter_args )))
190+
191+ _customize_metric_exporters (metric_readers , views )
192+
193+ provider = MeterProvider (resource = resource , metric_readers = metric_readers , views = views )
194+ set_meter_provider (provider )
195+
196+
163197# END The OpenTelemetry Authors code
164198
165199
@@ -283,14 +317,9 @@ def _customize_span_processors(provider: TracerProvider, resource: Resource) ->
283317 # Construct meterProvider
284318 _logger .info ("AWS Application Signals enabled" )
285319 otel_metric_exporter = ApplicationSignalsExporterProvider ().create_exporter ()
286- export_interval_millis = float (os .environ .get (METRIC_EXPORT_INTERVAL_CONFIG , DEFAULT_METRIC_EXPORT_INTERVAL ))
287- _logger .debug ("Span Metrics export interval: %s" , export_interval_millis )
288- # Cap export interval to 60 seconds. This is currently required for metrics-trace correlation to work correctly.
289- if export_interval_millis > DEFAULT_METRIC_EXPORT_INTERVAL :
290- export_interval_millis = DEFAULT_METRIC_EXPORT_INTERVAL
291- _logger .info ("AWS Application Signals metrics export interval capped to %s" , export_interval_millis )
320+
292321 periodic_exporting_metric_reader = PeriodicExportingMetricReader (
293- exporter = otel_metric_exporter , export_interval_millis = export_interval_millis
322+ exporter = otel_metric_exporter , export_interval_millis = _get_metric_export_interval ()
294323 )
295324 meter_provider : MeterProvider = MeterProvider (resource = resource , metric_readers = [periodic_exporting_metric_reader ])
296325 # Construct and set application signals metrics processor
@@ -299,25 +328,68 @@ def _customize_span_processors(provider: TracerProvider, resource: Resource) ->
299328 return
300329
301330
331+ def _customize_metric_exporters (metric_readers : List [MetricReader ], views : List [View ]) -> None :
332+ if _is_application_signals_runtime_enabled ():
333+ system_metrics_scope_name = "opentelemetry.instrumentation.system_metrics"
334+ if 0 == len (metric_readers ):
335+ _logger .info ("Registered scope %s" , system_metrics_scope_name )
336+ views .append (View (meter_name = system_metrics_scope_name , aggregation = DefaultAggregation ()))
337+ views .append (View (instrument_name = "*" , aggregation = DropAggregation ()))
338+
339+ otel_metric_exporter = ApplicationSignalsExporterProvider ().create_exporter ()
340+ scope_based_periodic_exporting_metric_reader = ScopeBasedPeriodicExportingMetricReader (
341+ exporter = otel_metric_exporter ,
342+ export_interval_millis = _get_metric_export_interval (),
343+ registered_scope_names = {system_metrics_scope_name },
344+ )
345+ metric_readers .append (scope_based_periodic_exporting_metric_reader )
346+
347+
302348def _customize_versions (auto_resource : Dict [str , any ]) -> Dict [str , any ]:
303349 distro_version = version ("aws-opentelemetry-distro" )
304350 auto_resource [ResourceAttributes .TELEMETRY_AUTO_VERSION ] = distro_version + "-aws"
305351 _logger .debug ("aws-opentelementry-distro - version: %s" , auto_resource [ResourceAttributes .TELEMETRY_AUTO_VERSION ])
306352 return auto_resource
307353
308354
355+ def _customize_resource (resource : Resource ) -> Resource :
356+ service_name , is_unknown = get_service_attribute (resource )
357+ if is_unknown :
358+ _logger .debug ("No valid service name found" )
359+
360+ return resource .merge (Resource .create ({AWS_LOCAL_SERVICE : service_name }))
361+
362+
309363def _is_application_signals_enabled ():
310364 return (
311- os .environ .get (APPLICATION_SIGNALS_ENABLED_CONFIG , os .environ .get (APP_SIGNALS_ENABLED_CONFIG , "false" )).lower ()
365+ os .environ .get (
366+ APPLICATION_SIGNALS_ENABLED_CONFIG , os .environ .get (DEPRECATED_APP_SIGNALS_ENABLED_CONFIG , "false" )
367+ ).lower ()
312368 == "true"
313369 )
314370
315371
372+ def _is_application_signals_runtime_enabled ():
373+ return _is_application_signals_enabled () and (
374+ os .environ .get (APPLICATION_SIGNALS_RUNTIME_ENABLED_CONFIG , "true" ).lower () == "true"
375+ )
376+
377+
316378def _is_lambda_environment ():
317379 # detect if running in AWS Lambda environment
318380 return AWS_LAMBDA_FUNCTION_NAME_CONFIG in os .environ
319381
320382
383+ def _get_metric_export_interval ():
384+ export_interval_millis = float (os .environ .get (METRIC_EXPORT_INTERVAL_CONFIG , DEFAULT_METRIC_EXPORT_INTERVAL ))
385+ _logger .debug ("Span Metrics export interval: %s" , export_interval_millis )
386+ # Cap export interval to 60 seconds. This is currently required for metrics-trace correlation to work correctly.
387+ if export_interval_millis > DEFAULT_METRIC_EXPORT_INTERVAL :
388+ export_interval_millis = DEFAULT_METRIC_EXPORT_INTERVAL
389+ _logger .info ("AWS Application Signals metrics export interval capped to %s" , export_interval_millis )
390+ return export_interval_millis
391+
392+
321393class ApplicationSignalsExporterProvider :
322394 _instance : ClassVar ["ApplicationSignalsExporterProvider" ] = None
323395
@@ -353,7 +425,7 @@ def create_exporter(self):
353425 if protocol == "http/protobuf" :
354426 application_signals_endpoint = os .environ .get (
355427 APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
356- os .environ .get (APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG , "http://localhost:4316/v1/metrics" ),
428+ os .environ .get (DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG , "http://localhost:4316/v1/metrics" ),
357429 )
358430 _logger .debug ("AWS Application Signals export endpoint: %s" , application_signals_endpoint )
359431 return OTLPHttpOTLPMetricExporter (
@@ -369,7 +441,7 @@ def create_exporter(self):
369441
370442 application_signals_endpoint = os .environ .get (
371443 APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
372- os .environ .get (APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG , "localhost:4315" ),
444+ os .environ .get (DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG , "localhost:4315" ),
373445 )
374446 _logger .debug ("AWS Application Signals export endpoint: %s" , application_signals_endpoint )
375447 return OTLPGrpcOTLPMetricExporter (
0 commit comments