|
3 | 3 |
|
4 | 4 | from typing import Any, Dict, List, Sequence |
5 | 5 |
|
6 | | -from amazon.opentelemetry.distro.exporter.otlp.aws.logs.otlp_aws_logs_exporter import OTLPAwsLogExporter |
7 | | - |
8 | 6 | from opentelemetry.attributes import BoundedAttributes |
9 | 7 | from opentelemetry._events import Event |
10 | 8 | from opentelemetry.sdk._logs import LoggerProvider |
11 | | -from opentelemetry.sdk._logs.export import BatchLogRecordProcessor |
12 | 9 | from opentelemetry.sdk._events import EventLoggerProvider |
13 | 10 | from opentelemetry.sdk.trace import ReadableSpan |
14 | 11 |
|
| 12 | +GEN_AI_SYSTEM_MESSAGE = "gen_ai.system.message" |
| 13 | +GEN_AI_USER_MESSAGE = "gen_ai.user.message" |
| 14 | +GEN_AI_ASSISTANT_MESSAGE = "gen_ai.assistant.message" |
| 15 | + |
15 | 16 | _logger = logging.getLogger(__name__) |
16 | 17 |
|
17 | 18 | class LLOHandler: |
@@ -134,103 +135,57 @@ def _extract_gen_ai_prompt_events(self, span: ReadableSpan, attributes: Dict[str |
134 | 135 |
|
135 | 136 | event = None |
136 | 137 | if role == "system": |
137 | | - event = self._get_gen_ai_system_message_event( |
138 | | - span_ctx, |
139 | | - prompt_timestamp, |
140 | | - event_attributes, |
141 | | - body |
| 138 | + event = self._get_gen_ai_event( |
| 139 | + name=GEN_AI_SYSTEM_MESSAGE, |
| 140 | + span_ctx=span_ctx, |
| 141 | + timestamp=prompt_timestamp, |
| 142 | + attributes=event_attributes, |
| 143 | + body=body |
142 | 144 | ) |
143 | 145 | elif role == "user": |
144 | | - event = self._get_gen_ai_user_message_event( |
145 | | - span_ctx, |
146 | | - prompt_timestamp, |
147 | | - event_attributes, |
148 | | - body |
| 146 | + event = self._get_gen_ai_event( |
| 147 | + name=GEN_AI_USER_MESSAGE, |
| 148 | + span_ctx=span_ctx, |
| 149 | + timestamp=prompt_timestamp, |
| 150 | + attributes=event_attributes, |
| 151 | + body=body |
149 | 152 | ) |
150 | 153 | elif role == "assistant": |
151 | | - event = self._get_gen_ai_assistant_message_event( |
152 | | - span_ctx, |
153 | | - prompt_timestamp, |
154 | | - event_attributes, |
155 | | - body |
| 154 | + event = self._get_gen_ai_event( |
| 155 | + name=GEN_AI_ASSISTANT_MESSAGE, |
| 156 | + span_ctx=span_ctx, |
| 157 | + timestamp=prompt_timestamp, |
| 158 | + attributes=event_attributes, |
| 159 | + body=body |
156 | 160 | ) |
157 | 161 | elif role in ["function", "unknown"]: |
158 | | - # TODO: Need to define a custom event and emit |
159 | | - pass |
| 162 | + event = self._get_gen_ai_event( |
| 163 | + name=f"gen_ai.{gen_ai_system}.message", |
| 164 | + span_ctx=span_ctx, |
| 165 | + timestamp=prompt_timestamp, |
| 166 | + attributes=event_attributes, |
| 167 | + body=body |
| 168 | + ) |
160 | 169 |
|
161 | 170 | if event: |
162 | 171 | events.append(event) |
163 | 172 |
|
164 | 173 | return events |
165 | 174 |
|
166 | | - def _get_gen_ai_system_message_event( |
167 | | - self, |
168 | | - span_ctx, |
169 | | - timestamp, |
170 | | - event_attributes, |
171 | | - body |
172 | | - ): |
173 | | - """ |
174 | | - Create and return a `gen_ai.system.message` Event. |
175 | | - """ |
176 | | - return Event( |
177 | | - name="gen_ai.system.message", |
178 | | - timestamp=timestamp, |
179 | | - attributes=event_attributes, |
180 | | - body=body, |
181 | | - trace_id=span_ctx.trace_id, |
182 | | - span_id=span_ctx.span_id, |
183 | | - trace_flags=span_ctx.trace_flags, |
184 | | - ) |
185 | | - |
186 | | - def _get_gen_ai_user_message_event( |
187 | | - self, |
188 | | - span_ctx, |
189 | | - timestamp, |
190 | | - event_attributes, |
191 | | - body |
192 | | - ): |
193 | | - """ |
194 | | - Create and return a `gen_ai.user.message` Event. |
195 | | - """ |
196 | | - return Event( |
197 | | - name="gen_ai.user.message", |
198 | | - timestamp=timestamp, |
199 | | - attributes=event_attributes, |
200 | | - body=body, |
201 | | - trace_id=span_ctx.trace_id, |
202 | | - span_id=span_ctx.span_id, |
203 | | - trace_flags=span_ctx.trace_flags, |
204 | | - ) |
205 | | - |
206 | | - def _get_gen_ai_assistant_message_event( |
| 175 | + def _get_gen_ai_event( |
207 | 176 | self, |
| 177 | + name, |
208 | 178 | span_ctx, |
209 | 179 | timestamp, |
210 | | - event_attributes, |
| 180 | + attributes, |
211 | 181 | body |
212 | 182 | ): |
213 | | - """ |
214 | | - Create and return a `gen_ai.assistant.message` Event. |
215 | | -
|
216 | | - According to the OTel spec, assistant message events may contain tool_calls, |
217 | | - if available. In our implementation, tool call information is not available |
218 | | - directly in the span attributes we're processing - it exists in separate |
219 | | - related spans. |
220 | | -
|
221 | | - Thus without implementing complex span correlation, we cannot reliable extract |
222 | | - tool_calls for assistant messages. This limitation is acceptable per the OTel |
223 | | - spec since tool_calls are only required when available. However, this will |
224 | | - lead to reduction in data quality. |
225 | | -
|
226 | | - ref: https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-events/#event-gen_aiassistantmessage |
227 | | - """ |
228 | 183 | return Event( |
229 | | - name="gen_ai.assistant.message", |
| 184 | + name=name, |
230 | 185 | timestamp=timestamp, |
231 | | - attributes=event_attributes, |
| 186 | + attributes=attributes, |
232 | 187 | body=body, |
233 | 188 | trace_id=span_ctx.trace_id, |
234 | 189 | span_id=span_ctx.span_id, |
235 | | - trace_flags=span_ctx.trace_flags, |
| 190 | + trace_flags=span_ctx.trace_flags |
236 | 191 | ) |
0 commit comments