44# license information.
55# --------------------------------------------------------------------------
66import logging
7- from typing import Dict , Optional
8- from .._models import VariantAssignmentReason , EvaluationEvent
7+ import inspect
8+ from typing import Dict , Optional , Callable
9+ from .._models import VariantAssignmentReason , EvaluationEvent , TargetingContext
10+
11+ logger = logging .getLogger (__name__ )
912
1013try :
1114 from azure .monitor .events .extension import track_event as azure_monitor_track_event # type: ignore
12- from opentelemetry import trace , baggage , context
1315 from opentelemetry .context .context import Context
1416 from opentelemetry .sdk .trace import Span , SpanProcessor
1517
1618 HAS_AZURE_MONITOR_EVENTS_EXTENSION = True
1719except ImportError :
1820 HAS_AZURE_MONITOR_EVENTS_EXTENSION = False
19- logging .warning (
21+ logger .warning (
2022 "azure-monitor-events-extension is not installed. Telemetry will not be sent to Application Insights."
2123 )
2224 SpanProcessor = object # type: ignore
@@ -114,23 +116,18 @@ def publish_telemetry(evaluation_event: EvaluationEvent) -> None:
114116 track_event (EVENT_NAME , evaluation_event .user , event_properties = event )
115117
116118
117- def attach_targeting_info (targeting_id : str ) -> None :
118- """
119- Attaches the targeting ID to the current span and baggage.
120-
121- :param str targeting_id: The targeting ID to attach.
122- """
123- if not HAS_AZURE_MONITOR_EVENTS_EXTENSION :
124- return
125- context .attach (baggage .set_baggage (MICROSOFT_TARGETING_ID , targeting_id ))
126- trace .get_current_span ().set_attribute (TARGETING_ID , targeting_id )
127-
128-
129119class TargetingSpanProcessor (SpanProcessor ):
130120 """
131121 A custom SpanProcessor that attaches the targeting ID to the span and baggage when a new span is started.
122+ :keyword Callable[[], TargetingContext] targeting_context_accessor: Callback function to get the current targeting
123+ context if one isn't provided.
132124 """
133125
126+ def __init__ (self , ** kwargs ) -> None :
127+ self ._targeting_context_accessor : Optional [Callable [[], TargetingContext ]] = kwargs .pop (
128+ "targeting_context_accessor" , None
129+ )
130+
134131 def on_start (self , span : Span , parent_context : Optional [Context ] = None ) -> None :
135132 """
136133 Attaches the targeting ID to the span and baggage when a new span is started.
@@ -140,6 +137,20 @@ def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None
140137 """
141138 if not HAS_AZURE_MONITOR_EVENTS_EXTENSION :
142139 return
143- target_baggage = baggage .get_baggage (MICROSOFT_TARGETING_ID , parent_context )
144- if target_baggage is not None and isinstance (target_baggage , str ):
145- span .set_attribute (TARGETING_ID , target_baggage )
140+ if self ._targeting_context_accessor and callable (self ._targeting_context_accessor ):
141+ if inspect .iscoroutinefunction (self ._targeting_context_accessor ):
142+ logger .warning ("Async targeting_context_accessor is not supported." )
143+ return
144+ targeting_context = self ._targeting_context_accessor ()
145+ if not targeting_context or not isinstance (targeting_context , TargetingContext ):
146+ logger .warning (
147+ "targeting_context_accessor did not return a TargetingContext. Received type %s." ,
148+ type (targeting_context ),
149+ )
150+ return
151+ if not targeting_context .user_id :
152+ logger .debug ("TargetingContext does not have a user ID." )
153+ return
154+ span .set_attribute (TARGETING_ID , targeting_context .user_id )
155+
156+
0 commit comments