-
Notifications
You must be signed in to change notification settings - Fork 424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(langchain): auto-instrument with langgraph #12208
base: main
Are you sure you want to change the base?
Conversation
|
BenchmarksBenchmark execution time: 2025-02-06 23:07:56 Comparing candidate commit 2431cae in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 394 metrics, 2 unstable metrics. |
@@ -74,6 +109,9 @@ def _llmobs_set_tags( | |||
log.warning("Unsupported operation : %s", operation) | |||
return | |||
|
|||
if asbool(os.getenv("_DD_TRACE_LANGCHAIN_LINKING_ENABLED")): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
open to suggestions on the variable name here 😄
|
||
instance = _extract_bound(instance) | ||
|
||
self._instances[span] = instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bit funky here, but this is associating spans with their instances. while this could be done directly in _llmobs_set_tags
for individual spans, the span linking logic works by looking for the caller and identifying if it's a chain. To do that, we need a way to associate a different span with an isntance.
This is all sorta predicated on the fact that we don't have an intermediary for associating traced steps. Unlike the pregel_loop_tick
which we could utilize for langgraph
, all steps of a chain are iterated over directly in chain.invoke
, with no means for us to jump between each step as they are being executed, only before and making these kinds of connections and setting these variables.
Datadog ReportBranch report: ✅ 0 Failed, 130 Passed, 1378 Skipped, 4m 44.97s Total duration (35m 12.56s time saved) |
5696d35
to
ad56495
Compare
52e9c96
to
3f08852
Compare
Adds gated auto-instrumentation for langchain with langgraph
Complications with linking
The primary obstacle was that, unlike with LangGraph, where we had an intermediary function to patch between tasks executed by the graph, we don't have that for LangChain LCEL chains. Their steps are executed in a loop inside their
invoke
method, which blocks us from jumping in between the steps to make the links.Additionally, LangChain elements that we trace are sometimes embedded in other
Runnable
types:RunnableBinding
, which binds an instance inside of itRunnableParallel
, which can run multipleRunnables
(some of which we might trace) in parallel, which have the parallel items in asteps__
attributeSomething I tried to overcome this was to flatten/flatmap the items of the list of steps to extract these.
To overcome linking between steps, I recorded the instance of each traced Runnable, mapping its ID to its span, and vice versa, to be able to grab instances if needed. Additionally, for each Runnable item in the chain, I marked them as a chain step by adding them to a set of steps to later check against.
Setting links
Link setting is split into setting the input links (
"to": "input"
) and output links ("to": "output"
)Input Links
Input links are set by:
input --> input
from the parent span.output --> input
link. If the step contains multiple spans (ie from aRunnableParallel
), add all of those spans as links with the sameoutput --> input
attributeThe index of the previously traced step in the chain (
-1
if not found or is not a chain step) is returned for use in output linkage.Output Links
Output links are set by:
steps
attribute), set theoutput --> output
link from the current span onto the parent span.Checklist
Reviewer Checklist