|
27 | 27 |
|
28 | 28 | import backoff |
29 | 29 | import httpx |
| 30 | +from opentelemetry import context as otel_context_api |
30 | 31 | from opentelemetry import trace as otel_trace_api |
31 | 32 | from opentelemetry.sdk.trace import ReadableSpan, TracerProvider |
32 | 33 | from opentelemetry.sdk.trace.export import SpanExporter |
|
66 | 67 | ) |
67 | 68 | from langfuse._client.propagation import ( |
68 | 69 | PropagatedExperimentAttributes, |
| 70 | + _detach_context_token_safely, |
69 | 71 | _propagate_attributes, |
| 72 | + _set_langfuse_trace_id_in_baggage, |
70 | 73 | ) |
71 | 74 | from langfuse._client.resource_manager import LangfuseResourceManager |
72 | 75 | from langfuse._client.span import ( |
@@ -1178,39 +1181,54 @@ def _start_as_current_otel_span_with_processed_media( |
1178 | 1181 | name=name, |
1179 | 1182 | end_on_exit=end_on_exit if end_on_exit is not None else True, |
1180 | 1183 | ) as otel_span: |
| 1184 | + baggage_token = None |
| 1185 | + |
| 1186 | + if otel_span.is_recording(): |
| 1187 | + context_with_app_root_claim = _set_langfuse_trace_id_in_baggage( |
| 1188 | + trace_id=self._get_otel_trace_id(otel_span), |
| 1189 | + context=otel_context_api.get_current(), |
| 1190 | + ) |
| 1191 | + baggage_token = otel_context_api.attach(context_with_app_root_claim) |
| 1192 | + |
1181 | 1193 | span_class = self._get_span_class( |
1182 | 1194 | as_type or "generation" |
1183 | 1195 | ) # default was "generation" |
1184 | | - common_args = { |
1185 | | - "otel_span": otel_span, |
1186 | | - "langfuse_client": self, |
1187 | | - "environment": self._environment, |
1188 | | - "release": self._release, |
1189 | | - "input": input, |
1190 | | - "output": output, |
1191 | | - "metadata": metadata, |
1192 | | - "version": version, |
1193 | | - "level": level, |
1194 | | - "status_message": status_message, |
1195 | | - } |
1196 | 1196 |
|
1197 | | - if span_class in [ |
1198 | | - LangfuseGeneration, |
1199 | | - LangfuseEmbedding, |
1200 | | - ]: |
1201 | | - common_args.update( |
1202 | | - { |
1203 | | - "completion_start_time": completion_start_time, |
1204 | | - "model": model, |
1205 | | - "model_parameters": model_parameters, |
1206 | | - "usage_details": usage_details, |
1207 | | - "cost_details": cost_details, |
1208 | | - "prompt": prompt, |
1209 | | - } |
1210 | | - ) |
1211 | | - # For span-like types (span, agent, tool, chain, retriever, evaluator, guardrail), no generation properties needed |
| 1197 | + try: |
| 1198 | + common_args = { |
| 1199 | + "otel_span": otel_span, |
| 1200 | + "langfuse_client": self, |
| 1201 | + "environment": self._environment, |
| 1202 | + "release": self._release, |
| 1203 | + "input": input, |
| 1204 | + "output": output, |
| 1205 | + "metadata": metadata, |
| 1206 | + "version": version, |
| 1207 | + "level": level, |
| 1208 | + "status_message": status_message, |
| 1209 | + } |
| 1210 | + |
| 1211 | + if span_class in [ |
| 1212 | + LangfuseGeneration, |
| 1213 | + LangfuseEmbedding, |
| 1214 | + ]: |
| 1215 | + common_args.update( |
| 1216 | + { |
| 1217 | + "completion_start_time": completion_start_time, |
| 1218 | + "model": model, |
| 1219 | + "model_parameters": model_parameters, |
| 1220 | + "usage_details": usage_details, |
| 1221 | + "cost_details": cost_details, |
| 1222 | + "prompt": prompt, |
| 1223 | + } |
| 1224 | + ) |
| 1225 | + # For span-like types (span, agent, tool, chain, retriever, evaluator, guardrail), no generation properties needed |
| 1226 | + |
| 1227 | + yield span_class(**common_args) # type: ignore[arg-type] |
1212 | 1228 |
|
1213 | | - yield span_class(**common_args) # type: ignore[arg-type] |
| 1229 | + finally: |
| 1230 | + if baggage_token is not None: |
| 1231 | + _detach_context_token_safely(baggage_token) |
1214 | 1232 |
|
1215 | 1233 | def _get_current_otel_span(self) -> Optional[otel_trace_api.Span]: |
1216 | 1234 | current_span = otel_trace_api.get_current_span() |
|
0 commit comments