4545)
4646from aws_durable_execution_sdk_python_otel .log_filter import install_log_filter
4747from aws_durable_execution_sdk_python_otel .otel_plugin_config import (
48- DEFAULT_WORKFLOW_SPAN_NAME ,
48+ OtelPluginConfig ,
49+ )
50+ from aws_durable_execution_sdk_python_otel .provider import create_tracer_provider
51+ from aws_durable_execution_sdk_python_otel .instrumentations import (
52+ register_standalone_instrumentations ,
4953)
5054
5155
@@ -80,42 +84,60 @@ class InvocationOtelPlugin(DurableInstrumentationPlugin):
8084 original logical operation.
8185
8286 Args:
83- trace_provider: OpenTelemetry tracer provider used to create spans.
84- Optional; when omitted, the globally configured tracer provider
85- (``opentelemetry.trace.get_tracer_provider()``) is used.
86- context_extractor: Optional extractor for upstream context. Defaults to
87- AWS X-Ray header extraction.
88- instrument_name: Instrumentation scope name registered with the tracer.
87+ config: Shared plugin configuration (the same OtelPluginConfig accepted
88+ by ExecutionOtelPlugin). When omitted, defaults are used (X-Ray
89+ extractor, "Workflow" span name, log enrichment on). When no provider
90+ is configured, an OTLP provider is auto-configured (matching
91+ ExecutionOtelPlugin and the JS SDK plugins); set
92+ ``use_default_tracer_provider=True`` on the config to use the globally
93+ configured tracer provider instead (e.g. the ADOT Lambda layer).
8994 """
9095
9196 DEFAULT_INSTRUMENT_NAME = "aws-durable-execution-sdk-python"
9297
93- def __init__ (
94- self ,
95- trace_provider : SdkTracerProvider | None = None ,
96- context_extractor : ContextExtractor | None = None ,
97- instrument_name : str = DEFAULT_INSTRUMENT_NAME ,
98- enrich_logger : bool = True ,
99- workflow_span_name : str = DEFAULT_WORKFLOW_SPAN_NAME ,
100- ) -> None :
101- """Initialize the plugin with an OpenTelemetry tracer provider.
98+ def __init__ (self , config : OtelPluginConfig | None = None ) -> None :
99+ """Initialize the plugin from a shared OtelPluginConfig.
100+
101+ Accepts the same OtelPluginConfig as ExecutionOtelPlugin so both plugins
102+ share one configuration surface (context extractor, instrumentation
103+ name, provider selection, exporter/propagator settings, log
104+ enrichment). Like ExecutionOtelPlugin and the JS SDK plugins, it
105+ auto-configures an OTLP provider when nothing is supplied; pass
106+ ``use_default_tracer_provider=True`` to use the globally configured
107+ (e.g. ADOT) provider instead.
102108
103109 The tracer provider is configured with this plugin's deterministic ID
104110 generator so spans for a durable execution share stable trace and
105- logical operation identifiers. When no provider is supplied, the
106- globally configured tracer provider is used.
111+ logical operation identifiers.
107112
108- When enrich_logger is enabled (default), the plugin installs a logging
109- filter on the root logger at invocation start that stamps the active
110- OTel trace context onto every emitted log record.
113+ When `` enrich_logger`` is enabled (default), the plugin installs a
114+ logging filter that stamps the active OTel trace context onto every
115+ emitted log record.
111116 """
112- self ._enrich_logger = enrich_logger
113- self ._workflow_span_name = workflow_span_name
117+ self ._config = config or OtelPluginConfig ()
114118 self ._context_extractor : ContextExtractor = (
115- context_extractor or xray_context_extractor
119+ self . _config . context_extractor or xray_context_extractor
116120 )
121+ self ._workflow_span_name = self ._config .workflow_span_name
122+ self ._enrich_logger = self ._config .enrich_logger
123+
124+ # Like ExecutionOtelPlugin (and the JS SDK plugins), InvocationOtelPlugin
125+ # auto-configures an OTLP provider when nothing is supplied. Resolve the
126+ # effective "use the global provider" decision up front so that
127+ # instrumentation registration matches what create_tracer_provider does.
128+ self ._use_default = self ._config .use_default_tracer_provider
129+ if self ._use_default is None :
130+ self ._use_default = False
131+
132+ self ._id_generator = DeterministicIdGenerator ()
133+ result = create_tracer_provider (
134+ self ._config ,
135+ id_generator = self ._id_generator ,
136+ default_use_global = False ,
137+ )
138+ self ._provider = result .tracer_provider
139+ self ._owns_provider = result .owns_provider
117140
118- self ._provider = trace_provider or trace .get_tracer_provider ()
119141 # Deterministic trace stitching requires the SDK TracerProvider, which
120142 # exposes id_generator/sampler. The API's default ProxyTracerProvider
121143 # (returned before an SDK provider is configured) does not. Rather than
@@ -128,16 +150,25 @@ def __init__(
128150 self ._provider
129151 )
130152 else :
131- self ._id_generator = DeterministicIdGenerator ()
132153 logger .warning (
133154 "InvocationOtelPlugin expected an SDK TracerProvider "
134155 "(opentelemetry.sdk.trace.TracerProvider) but got %s. Spans will "
135156 "not use deterministic IDs. "
136157 "Ensure the OpenTelemetry SDK is configured (e.g. via the ADOT "
137- "Lambda layer) or pass an explicit trace_provider ." ,
158+ "Lambda layer) or pass an explicit tracer_provider ." ,
138159 type (self ._provider ).__name__ ,
139160 )
140- self ._tracer : Tracer = self ._provider .get_tracer (instrument_name )
161+ self ._tracer : Tracer = self ._provider .get_tracer (self ._config .instrument_name )
162+
163+ try :
164+ register_standalone_instrumentations (
165+ self ._config ,
166+ self ._provider if self ._owns_provider else None ,
167+ owns_provider = self ._owns_provider ,
168+ use_default_tracer_provider = self ._use_default ,
169+ )
170+ except Exception :
171+ logger .exception ("Failed to register standalone instrumentations" )
141172
142173 # per invocation status:
143174 self ._execution_arn = ""
0 commit comments