Skip to content

Commit 0eb5df4

Browse files
committed
fix: correctly capture a parent id when a custom trace_id is set
1 parent f83b892 commit 0eb5df4

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

posthog/ai/langchain/callbacks.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import logging
77
import time
8-
import uuid
98
from dataclasses import dataclass
109
from typing import (
1110
Any,
@@ -402,9 +401,17 @@ def _pop_run_metadata(self, run_id: UUID) -> Optional[RunMetadataUnion]:
402401
def _get_trace_id(self, run_id: UUID):
403402
trace_id = self._trace_id or self._find_root_run(run_id)
404403
if not trace_id:
405-
trace_id = uuid.uuid4()
404+
return run_id
406405
return trace_id
407406

407+
def _get_parent_run_id(self, trace_id: Any, run_id: UUID, parent_run_id: Optional[UUID]):
408+
"""
409+
Replace the parent run ID with the trace ID for second level runs when a custom trace ID is set.
410+
"""
411+
if parent_run_id is not None and parent_run_id not in self._parent_tree:
412+
return trace_id
413+
return parent_run_id
414+
408415
def _pop_run_and_capture_trace_or_span(self, run_id: UUID, parent_run_id: Optional[UUID], outputs: Any):
409416
trace_id = self._get_trace_id(run_id)
410417
self._pop_parent_of_run(run_id)
@@ -414,7 +421,9 @@ def _pop_run_and_capture_trace_or_span(self, run_id: UUID, parent_run_id: Option
414421
if isinstance(run, GenerationMetadata):
415422
log.warning(f"Run {run_id} is not a generation but attempted to be captured as a trace or span.")
416423
return
417-
self._capture_trace_or_span(trace_id, run_id, run, outputs, parent_run_id)
424+
self._capture_trace_or_span(
425+
trace_id, run_id, run, outputs, self._get_parent_run_id(trace_id, run_id, parent_run_id)
426+
)
418427

419428
def _capture_trace_or_span(
420429
self,
@@ -462,7 +471,9 @@ def _pop_run_and_capture_generation(
462471
if not isinstance(run, GenerationMetadata):
463472
log.warning(f"Run {run_id} is not a generation but attempted to be captured as a generation.")
464473
return
465-
self._capture_generation(trace_id, run_id, run, response, parent_run_id)
474+
self._capture_generation(
475+
trace_id, run_id, run, response, self._get_parent_run_id(trace_id, run_id, parent_run_id)
476+
)
466477

467478
def _capture_generation(
468479
self,

posthog/test/ai/langchain/test_callbacks.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,3 +1265,27 @@ def get_weather(city: Literal["nyc", "sf"]):
12651265
assert len([call for call in calls if call["event"] == "$ai_generation"]) == 2
12661266
assert len([call for call in calls if call["event"] == "$ai_span"]) == 18
12671267
assert len([call for call in calls if call["event"] == "$ai_trace"]) == 1
1268+
1269+
1270+
@pytest.mark.parametrize("trace_id", ["test-trace-id", None])
1271+
def test_span_set_parent_ids(mock_client, trace_id):
1272+
prompt = ChatPromptTemplate.from_messages(
1273+
[
1274+
("system", "You are a helpful assistant."),
1275+
("user", "Who won the world series in 2020?"),
1276+
]
1277+
)
1278+
model = FakeMessagesListChatModel(
1279+
responses=[AIMessage(content="The Los Angeles Dodgers won the World Series in 2020.")]
1280+
)
1281+
callbacks = [CallbackHandler(mock_client, trace_id=trace_id)]
1282+
chain = prompt | model
1283+
chain.invoke({}, config={"callbacks": callbacks})
1284+
1285+
assert mock_client.capture.call_count == 3
1286+
1287+
span_props = mock_client.capture.call_args_list[0][1]
1288+
assert span_props["properties"]["$ai_trace_id"] == span_props["properties"]["$ai_parent_id"]
1289+
1290+
generation_props = mock_client.capture.call_args_list[1][1]
1291+
assert generation_props["properties"]["$ai_trace_id"] == generation_props["properties"]["$ai_parent_id"]

0 commit comments

Comments
 (0)