@@ -76,12 +76,16 @@ async def _fetch_trace_list_with_retry(
7676) -> Any :
7777 """Fetch trace list with rate limit retry logic."""
7878 list_retries = 0
79- rollout_id : Optional [str ] = None
79+ tracking_key : Optional [str ] = None # Could be rollout_id or trail_id
8080 if tags :
8181 for t in tags :
82- if isinstance (t , str ) and t .startswith ("rollout_id:" ):
83- rollout_id = t .split (":" , 1 )[1 ] if ":" in t else t
84- break
82+ if isinstance (t , str ):
83+ if t .startswith ("rollout_id:" ):
84+ tracking_key = t .split (":" , 1 )[1 ] if ":" in t else t
85+ break
86+ elif t .startswith ("trail_id:" ):
87+ tracking_key = t .split (":" , 1 )[1 ] if ":" in t else t
88+ break
8589 while list_retries < max_retries :
8690 try :
8791 traces = langfuse_client .api .trace .list (
@@ -124,17 +128,17 @@ async def _fetch_trace_list_with_retry(
124128 # Return 404 if we've retried max_retries
125129 # TODO: write some tests around proxy exception handling
126130 logger .error (
127- "Failed to fetch trace list after %d retries (rollout_id =%s): %s" ,
131+ "Failed to fetch trace list after %d retries (tracking_key =%s): %s" ,
128132 max_retries ,
129- rollout_id ,
133+ tracking_key ,
130134 e ,
131135 )
132136 raise HTTPException (
133137 status_code = 404 , detail = f"Failed to fetch traces after { max_retries } retries: { str (e )} "
134138 )
135139 else :
136140 # Catch all other exceptions
137- logger .error ("Failed to fetch trace list (rollout_id =%s): %s" , rollout_id , e )
141+ logger .error ("Failed to fetch trace list (tracking_key =%s): %s" , tracking_key , e )
138142 raise HTTPException (status_code = 500 , detail = f"Failed to fetch traces: { str (e )} " )
139143
140144
@@ -247,16 +251,16 @@ async def fetch_langfuse_traces(
247251
248252 # Get expected insertion_ids from Redis for completeness checking
249253 expected_ids : Set [str ] = set ()
250- if rollout_id :
251- expected_ids = get_insertion_ids (redis_client , rollout_id )
252- logger .info (f"Fetching traces for rollout_id '{ rollout_id } ', expecting { len (expected_ids )} insertion_ids" )
254+ if tracking_key :
255+ expected_ids = get_insertion_ids (redis_client , tracking_key )
256+ logger .info (f"Fetching traces for { tracking_label } '{ tracking_key } ', expecting { len (expected_ids )} insertion_ids" )
253257 if not expected_ids :
254258 logger .warning (
255- f"No expected insertion_ids found in Redis for rollout '{ rollout_id } '. Returning empty traces."
259+ f"No expected insertion_ids found in Redis for { tracking_label } '{ tracking_key } '. Returning empty traces."
256260 )
257261 raise HTTPException (
258262 status_code = 500 ,
259- detail = f"No expected insertion_ids found in Redis for rollout '{ rollout_id } '. Returning empty traces." ,
263+ detail = f"No expected insertion_ids found in Redis for { tracking_label } '{ tracking_key } '. Returning empty traces." ,
260264 )
261265
262266 # Track all traces we've collected across retry attempts
@@ -265,15 +269,15 @@ async def fetch_langfuse_traces(
265269 insertion_ids : Set [str ] = set () # Insertion IDs extracted from traces (for completeness check)
266270
267271 for retry in range (max_retries ):
268- # On first attempt, use rollout_id tag. On retries, target missing insertion_ids
272+ # On first attempt, use tracking tag. On retries, target missing insertion_ids
269273 if retry == 0 :
270274 fetch_tags = tags
271275 else :
272276 # Build targeted tags for missing insertion_ids
273277 missing_ids = expected_ids - insertion_ids
274278 fetch_tags = [f"insertion_id:{ id } " for id in missing_ids ]
275279 logger .info (
276- f"Retry { retry } : Targeting { len (fetch_tags )} missing insertion_ids for rollout '{ rollout_id } ' (last5): { [id [- 5 :] for id in sorted (missing_ids )[:10 ]]} { '...' if len (missing_ids ) > 10 else '' } "
280+ f"Retry { retry } : Targeting { len (fetch_tags )} missing insertion_ids for { tracking_label } '{ tracking_key } ' (last5): { [id [- 5 :] for id in sorted (missing_ids )[:10 ]]} { '...' if len (missing_ids ) > 10 else '' } "
277281 )
278282
279283 current_page = 1
@@ -329,7 +333,7 @@ async def fetch_langfuse_traces(
329333 insertion_id = _extract_tag_value (trace_dict .get ("tags" , []), "insertion_id:" )
330334 if insertion_id :
331335 insertion_ids .add (insertion_id )
332- logger .debug (f"Found insertion_id '{ insertion_id } ' for rollout '{ rollout_id } '" )
336+ logger .debug (f"Found insertion_id '{ insertion_id } ' for { tracking_label } '{ tracking_key } '" )
333337
334338 except Exception as e :
335339 logger .warning ("Failed to serialize trace %s: %s" , trace_info .id , e )
@@ -349,7 +353,7 @@ async def fetch_langfuse_traces(
349353 # If we have all expected completions or more, return traces. At least once is ok.
350354 if expected_ids <= insertion_ids :
351355 logger .info (
352- f"Traces complete for rollout '{ rollout_id } ': { len (insertion_ids )} /{ len (expected_ids )} insertion_ids found, returning { len (all_traces )} traces"
356+ f"Traces complete for { tracking_label } '{ tracking_key } ': { len (insertion_ids )} /{ len (expected_ids )} insertion_ids found, returning { len (all_traces )} traces"
353357 )
354358 if sample_size is not None and len (all_traces ) > sample_size :
355359 all_traces = random .sample (all_traces , sample_size )
@@ -366,16 +370,16 @@ async def fetch_langfuse_traces(
366370 wait_time = 2 ** retry
367371 still_missing = expected_ids - insertion_ids
368372 logger .info (
369- f"Attempt { retry + 1 } /{ max_retries } . Found { len (insertion_ids )} /{ len (expected_ids )} for rollout '{ rollout_id } '. Still missing (last5): { [id [- 5 :] for id in sorted (still_missing )[:10 ]]} { '...' if len (still_missing ) > 10 else '' } . Waiting { wait_time } s..."
373+ f"Attempt { retry + 1 } /{ max_retries } . Found { len (insertion_ids )} /{ len (expected_ids )} for { tracking_label } '{ tracking_key } '. Still missing (last5): { [id [- 5 :] for id in sorted (still_missing )[:10 ]]} { '...' if len (still_missing ) > 10 else '' } . Waiting { wait_time } s..."
370374 )
371375 await asyncio .sleep (wait_time )
372376
373377 logger .error (
374- f"Incomplete traces for rollout_id '{ rollout_id } ': Found { len (insertion_ids )} /{ len (expected_ids )} completions."
378+ f"Incomplete traces for { tracking_label } '{ tracking_key } ': Found { len (insertion_ids )} /{ len (expected_ids )} completions."
375379 )
376380 raise HTTPException (
377381 status_code = 404 ,
378- detail = f"Incomplete traces for rollout_id '{ rollout_id } ': Found { len (insertion_ids )} /{ len (expected_ids )} completions." ,
382+ detail = f"Incomplete traces for { tracking_label } '{ tracking_key } ': Found { len (insertion_ids )} /{ len (expected_ids )} completions." ,
379383 )
380384
381385 except ImportError :
@@ -431,8 +435,11 @@ async def pointwise_fetch_langfuse_trace(
431435 detail = f"Project ID '{ project_id } ' not found. Available projects: { list (config .langfuse_keys .keys ())} " ,
432436 )
433437
434- # Extract rollout_id from tags for Redis lookup
438+ # Extract tracking key ( rollout_id or trail_id) from tags for Redis lookup
435439 rollout_id = _extract_tag_value (tags , "rollout_id:" )
440+ trail_id = _extract_tag_value (tags , "trail_id:" )
441+ tracking_key = trail_id if trail_id else rollout_id
442+ tracking_label = "trail_id" if trail_id else "rollout_id"
436443
437444 try :
438445 # Import the Langfuse adapter
@@ -461,23 +468,23 @@ async def pointwise_fetch_langfuse_trace(
461468
462469 # Get insertion_ids from Redis to find the latest one
463470 expected_ids : Set [str ] = set ()
464- if rollout_id :
465- expected_ids = get_insertion_ids (redis_client , rollout_id )
471+ if tracking_key :
472+ expected_ids = get_insertion_ids (redis_client , tracking_key )
466473 logger .info (
467- f"Pointwise fetch for rollout_id '{ rollout_id } ', found { len (expected_ids )} insertion_ids in Redis"
474+ f"Pointwise fetch for { tracking_label } '{ tracking_key } ', found { len (expected_ids )} insertion_ids in Redis"
468475 )
469476 if not expected_ids :
470477 logger .warning (
471- f"No insertion_ids found in Redis for rollout '{ rollout_id } '. Cannot determine latest trace."
478+ f"No insertion_ids found in Redis for { tracking_label } '{ tracking_key } '. Cannot determine latest trace."
472479 )
473480 raise HTTPException (
474481 status_code = 500 ,
475- detail = f"No insertion_ids found in Redis for rollout '{ rollout_id } '. Cannot determine latest trace." ,
482+ detail = f"No insertion_ids found in Redis for { tracking_label } '{ tracking_key } '. Cannot determine latest trace." ,
476483 )
477484
478485 # Get the latest (last) insertion_id since UUID v7 is time-ordered
479486 latest_insertion_id = max (expected_ids ) # UUID v7 max = newest
480- logger .info (f"Targeting latest insertion_id: { latest_insertion_id } for rollout '{ rollout_id } '" )
487+ logger .info (f"Targeting latest insertion_id: { latest_insertion_id } for { tracking_label } '{ tracking_key } '" )
481488
482489 for retry in range (max_retries ):
483490 # Fetch trace list targeting the latest insertion_id
@@ -513,7 +520,7 @@ async def pointwise_fetch_langfuse_trace(
513520 if trace_full :
514521 trace_dict = _serialize_trace_to_dict (trace_full )
515522 logger .info (
516- f"Successfully fetched latest trace for rollout '{ rollout_id } ', insertion_id: { latest_insertion_id } "
523+ f"Successfully fetched latest trace for { tracking_label } '{ tracking_key } ', insertion_id: { latest_insertion_id } "
517524 )
518525 return LangfuseTracesResponse (
519526 project_id = project_id ,
@@ -525,17 +532,17 @@ async def pointwise_fetch_langfuse_trace(
525532 if retry < max_retries - 1 :
526533 wait_time = 2 ** retry
527534 logger .info (
528- f"Pointwise fetch attempt { retry + 1 } /{ max_retries } failed for rollout '{ rollout_id } ', insertion_id: { latest_insertion_id } . Retrying in { wait_time } s..."
535+ f"Pointwise fetch attempt { retry + 1 } /{ max_retries } failed for { tracking_label } '{ tracking_key } ', insertion_id: { latest_insertion_id } . Retrying in { wait_time } s..."
529536 )
530537 await asyncio .sleep (wait_time )
531538
532539 # After all retries failed
533540 logger .error (
534- f"Failed to fetch latest trace for rollout '{ rollout_id } ', insertion_id: { latest_insertion_id } after { max_retries } retries"
541+ f"Failed to fetch latest trace for { tracking_label } '{ tracking_key } ', insertion_id: { latest_insertion_id } after { max_retries } retries"
535542 )
536543 raise HTTPException (
537544 status_code = 404 ,
538- detail = f"Failed to fetch latest trace for rollout '{ rollout_id } ' after { max_retries } retries" ,
545+ detail = f"Failed to fetch latest trace for { tracking_label } '{ tracking_key } ' after { max_retries } retries" ,
539546 )
540547
541548 except ImportError :
0 commit comments