@@ -164,6 +164,8 @@ def on_end(self, span: ReadableSpan) -> None:
164164 import mlflow
165165 if not mlflow .active_run ():
166166 return
167+ if span .end_time is None or span .start_time is None :
168+ return
167169 duration_s = (span .end_time - span .start_time ) / 1_000_000_000.0
168170 name = span .name
169171 attrs = span .attributes or {}
@@ -181,7 +183,7 @@ def on_end(self, span: ReadableSpan) -> None:
181183 metrics : dict [str , float ] = {f"trace_{ name } _s" : duration_s }
182184 for key in ("tokens_used" , "llm_calls" , "api_calls" , "chunks_in" , "chunks_out" ):
183185 v = attrs .get (key )
184- if v :
186+ if isinstance ( v , ( int , float )) :
185187 # Normalize "tokens_used" → "tokens" for backward-compatible metric names.
186188 metric_key = "tokens" if key == "tokens_used" else key
187189 metrics [f"trace_{ name } _{ metric_key } " ] = float (v )
@@ -216,6 +218,8 @@ def on_start(self, span: Span, parent_context: Context | None = None) -> None:
216218
217219 def on_end (self , span : ReadableSpan ) -> None :
218220 trace_id = span .context .trace_id
221+ if span .end_time is None or span .start_time is None :
222+ return
219223 duration_s = (span .end_time - span .start_time ) / 1_000_000_000.0
220224 attrs = span .attributes or {}
221225 entry = self .flowers [trace_id ]
@@ -226,8 +230,10 @@ def on_end(self, span: ReadableSpan) -> None:
226230 entry ["total_s" ] = duration_s
227231 return
228232
229- tokens = int (attrs .get ("tokens_used" , 0 ) or 0 )
230- calls = int (attrs .get ("llm_calls" , 0 ) or 0 )
233+ raw_tokens = attrs .get ("tokens_used" , 0 ) or 0
234+ raw_calls = attrs .get ("llm_calls" , 0 ) or 0
235+ tokens = int (raw_tokens ) if isinstance (raw_tokens , (int , float )) else 0
236+ calls = int (raw_calls ) if isinstance (raw_calls , (int , float )) else 0
231237 entry ["steps" ][span .name ] = {
232238 "duration_s" : duration_s ,
233239 "tokens" : tokens ,
0 commit comments