@@ -225,6 +225,30 @@ def llm(
225225 raise
226226 self .stop_llm (invocation )
227227
228+ @contextmanager
229+ def embedding (
230+ self , invocation : EmbeddingInvocation | None = None
231+ ) -> Iterator [EmbeddingInvocation ]:
232+ """Context manager for Embedding invocations.
233+
234+ Only set data attributes on the invocation object, do not modify the span or context.
235+
236+ Starts the span on entry. On normal exit, finalizes the invocation and ends the span.
237+ If an exception occurs inside the context, marks the span as error, ends it, and
238+ re-raises the original exception.
239+ """
240+ if invocation is None :
241+ invocation = EmbeddingInvocation ()
242+ self .start_embedding (invocation )
243+ try :
244+ yield invocation
245+ except Exception as exc :
246+ self .fail_embedding (
247+ invocation , Error (message = str (exc ), type = type (exc ))
248+ )
249+ raise
250+ self .stop_embedding (invocation )
251+
228252 def start_embedding (
229253 self , invocation : EmbeddingInvocation
230254 ) -> EmbeddingInvocation :
@@ -249,11 +273,13 @@ def stop_embedding(
249273 return invocation
250274
251275 span = invocation .span
252- _apply_embedding_finish_attributes (span , invocation )
253- self ._record_embedding_metrics (invocation , span )
254- # Detach context and end span
255- otel_context .detach (invocation .context_token )
256- span .end ()
276+ try :
277+ _apply_embedding_finish_attributes (span , invocation )
278+ self ._record_embedding_metrics (invocation , span )
279+ finally :
280+ # Detach context and end span even if finishing fails
281+ otel_context .detach (invocation .context_token )
282+ span .end ()
257283 return invocation
258284
259285 def fail_embedding (
@@ -265,13 +291,17 @@ def fail_embedding(
265291 return invocation
266292
267293 span = invocation .span
268- _apply_embedding_finish_attributes (invocation .span , invocation )
269- _apply_error_attributes (invocation .span , error )
270- error_type = getattr (error .type , "__qualname__" , None )
271- self ._record_embedding_metrics (invocation , span , error_type = error_type )
272- # Detach context and end span
273- otel_context .detach (invocation .context_token )
274- span .end ()
294+ try :
295+ _apply_embedding_finish_attributes (invocation .span , invocation )
296+ _apply_error_attributes (invocation .span , error )
297+ error_type = getattr (error .type , "__qualname__" , None )
298+ self ._record_embedding_metrics (
299+ invocation , span , error_type = error_type
300+ )
301+ finally :
302+ # Detach context and end span even if finishing fails
303+ otel_context .detach (invocation .context_token )
304+ span .end ()
275305 return invocation
276306
277307
0 commit comments