1717
1818class LLOHandler :
1919 """
20- Utility class for handling Large Language Objects (LLO).
21- This class identifies LLO attributes, emits them as log records, and filters
22- them out from telemetry data.
20+ Utility class for handling Large Language Objects (LLO) in OpenTelemetry spans.
21+
22+ LLOHandler performs three primary functions:
23+ 1. Identifies Large Language Objects (LLO) content in spans
24+ 2. Extracts and transforms these attributes into OpenTelemetry Gen AI Events
25+ 3. Filters LLO from spans
2326 """
2427 def __init__ (self , logger_provider : LoggerProvider ):
28+ """
29+ Initialize an LLOHandler with the specified logger provider.
30+
31+ Args:
32+ logger_provider: The OpenTelemetry LoggerProvider used for emitting events.
33+ Global LoggerProvider instance injected from our AwsOpenTelemetryConfigurator
34+ """
2535 self ._logger_provider = logger_provider
2636
2737 self ._event_logger_provider = EventLoggerProvider (logger_provider = self ._logger_provider )
@@ -35,9 +45,15 @@ def __init__(self, logger_provider: LoggerProvider):
3545
3646 def process_spans (self , spans : Sequence [ReadableSpan ]) -> List [ReadableSpan ]:
3747 """
38- Perform LLO processing for each span:
48+ Performs LLO processing for each span:
3949 1. Emitting LLO attributes as Gen AI Events
4050 2. Filtering out LLO attributes from the span
51+
52+ Args:
53+ spans: A sequence of OpenTelemetry ReadableSpan objects to process
54+
55+ Returns:
56+ List of processed spans with LLO attributes removed
4157 """
4258 modified_spans = []
4359
@@ -62,7 +78,15 @@ def process_spans(self, spans: Sequence[ReadableSpan]) -> List[ReadableSpan]:
6278
6379 def _emit_llo_attributes (self , span : ReadableSpan , attributes : Dict [str , Any ]) -> None :
6480 """
65- Extract, transform, and emit LLO attributes as Gen AI Events
81+ Collects the Gen AI Events for each LLO attribute in the span and emits them
82+ using the event logger.
83+
84+ Args:
85+ span: The source ReadableSpan that potentially contains LLO attributes
86+ attributes: Dictionary of span attributes to process
87+
88+ Returns:
89+ None: Events are emitted via the event logger
6690 """
6791 all_events = []
6892 all_events .extend (self ._extract_gen_ai_prompt_events (span , attributes ))
@@ -74,7 +98,15 @@ def _emit_llo_attributes(self, span: ReadableSpan, attributes: Dict[str, Any]) -
7498
7599 def _filter_attributes (self , attributes : Dict [str , Any ]) -> Dict [str , Any ]:
76100 """
77- Filter out attributes that contain LLO from the span's attributes.
101+ Filter out attributes that contain LLO from the span's attributes. This
102+ method creates a new attributes dictionary that excludes any keys identified
103+ as containing LLO data (based on the configured patterns).
104+
105+ Args:
106+ attributes: Original dictionary of span attributes
107+
108+ Returns:
109+ Dict[str, Any]: New dictionary with LLO attributes removed
78110 """
79111 filtered_attributes = {}
80112
@@ -87,7 +119,17 @@ def _filter_attributes(self, attributes: Dict[str, Any]) -> Dict[str, Any]:
87119
88120 def _is_llo_attribute (self , key : str ) -> bool :
89121 """
90- Determine if a span attribute contains an LLO based on its key.
122+ Determine if a span attribute contains an LLO based on its key name.
123+
124+ Checks if theattribute key matches any of the configured patterns:
125+ 1. Exact math patterns (complete string equality)
126+ 2. Regex match patterns (regular expression matching)
127+
128+ Args:
129+ key: The attribute key to check
130+
131+ Returns:
132+ bool: True if the key matches an LLO pattern, False otherwise
91133 """
92134 return (
93135 any (pattern == key for pattern in self ._exact_match_patterns ) or
@@ -98,14 +140,22 @@ def _is_llo_attribute(self, key: str) -> bool:
98140 def _extract_gen_ai_prompt_events (self , span : ReadableSpan , attributes : Dict [str , Any ]) -> List [Event ]:
99141 """
100142 Extract gen_ai prompt events from attributes. Each item `gen_ai.prompt.{n}.content`
101- maps has an associated `gen_ai.prompt.{n}.role` that we map to an Event type.
143+ maps has an associated `gen_ai.prompt.{n}.role` that determines the Event
144+ type to be created.
102145
103146 `gen_ai.prompt.{n}.role`:
104147 1. `system` -> `gen_ai.system.message` Event
105148 2. `user` -> `gen_ai.user.message` Event
106149 3. `assistant` -> `gen_ai.assistant.message` Event
107- 4. `function` -> custom Event - TBD
108- 5. `unknown` -> custom Event - TBD
150+ 4. `function` -> `gen_ai.{gen_ai.system}.message` custom Event
151+ 5. `unknown` -> `gen_ai.{gen_ai.system}.message` custom Event
152+
153+ Args:
154+ span: The source ReadableSpan that potentially contains LLO attributes
155+ attributes: Dictionary of span attributes to process
156+
157+ Returns:
158+ List[Event]: List of OpenTelemetry Events created from prompt attributes
109159 """
110160 events = []
111161 span_ctx = span .context
@@ -180,6 +230,19 @@ def _get_gen_ai_event(
180230 attributes ,
181231 body
182232 ):
233+ """
234+ Create and return a Gen AI Event with the provided parameters.
235+
236+ Args:
237+ name: The name/type of the event (e.g., gen_ai.system.message)
238+ span_ctx: The span context to extract trace/span IDs from
239+ timestamp: The timestamp for the event
240+ attributes: Additional attributes to include with the event
241+ body: The event body containing content and role information
242+
243+ Returns:
244+ Event: A fully configured OpenTelemetry Gen AI Event object
245+ """
183246 return Event (
184247 name = name ,
185248 timestamp = timestamp ,
0 commit comments