Skip to content

Commit 5a61bcf

Browse files
fix(llmobs): llmobs can be re-enabled on fork with agentless enabled [backport 3.3] (#13037)
Backport 269b3d8 from #12889 to 3.3. Due to a regression in #11961, agentless writers fail to init in LLMObs on fork, as the `agentless_url` is not passed down in `recreate`, resulting in: ``` File "/app/.venv/lib/python3.11/site-packages/ddtrace/llmobs/_writer.py", line 255, in __init__ raise ValueError("agentless_url is required for agentless mode") ValueError: agentless_url is required for agentless mode ``` The fix is passing the value down appropriately. ## Checklist - [x] PR author has checked that all the criteria below are met - The PR description includes an overview of the change - The PR description articulates the motivation for the change - The change includes tests OR the PR description describes a testing strategy - The PR description notes risks associated with the change, if any - Newly-added code is easy to change - The change follows the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) - The change includes or references documentation updates if necessary - Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [x] Reviewer has checked that all the criteria below are met - Title is accurate - All changes are related to the pull request's stated goal - Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes - Testing strategy adequately addresses listed risks - Newly-added code is easy to change - Release note makes sense to a user of the library - If necessary, author has acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment - Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting) Co-authored-by: Sam Brenner <[email protected]>
1 parent 30b7e35 commit 5a61bcf

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

ddtrace/llmobs/_writer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ def __init__(
274274
intake_url = agent.get_trace_url()
275275
headers[EVP_SUBDOMAIN_HEADER_NAME] = EVP_SUBDOMAIN_HEADER_VALUE
276276

277+
self.agentless_url = agentless_url
278+
277279
super(LLMObsSpanWriter, self).__init__(
278280
intake_url=intake_url,
279281
clients=clients,
@@ -326,6 +328,7 @@ def recreate(self):
326328
interval=self._interval,
327329
timeout=self._timeout,
328330
is_agentless=config._llmobs_agentless_enabled,
331+
agentless_url=self.agentless_url,
329332
)
330333

331334

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
LLM Observability: fixes an issue where LLMObs could not be enabled in a forked process when setting ``agentless_enabled=True`` or ``DD_LLMOBS_AGENTLESS_ENABLED=true``.

tests/llmobs/test_llmobs_service.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,28 @@ def test_llmobs_fork_recreates_and_restarts_span_writer():
13591359
llmobs_service.disable()
13601360

13611361

1362+
def test_llmobs_fork_recreates_and_restarts_agentless_span_writer():
1363+
"""Test that forking a process correctly recreates and restarts the LLMObsSpanWriter."""
1364+
with override_global_config(dict(_dd_api_key="<not-a-real-key>")):
1365+
with mock.patch("ddtrace.internal.writer.HTTPWriter._send_payload"):
1366+
llmobs_service.enable(_tracer=DummyTracer(), ml_app="test_app", agentless_enabled=True)
1367+
original_span_writer = llmobs_service._instance._llmobs_span_writer
1368+
pid = os.fork()
1369+
if pid: # parent
1370+
assert llmobs_service._instance._llmobs_span_writer == original_span_writer
1371+
assert llmobs_service._instance._llmobs_span_writer.status == ServiceStatus.RUNNING
1372+
else: # child
1373+
assert llmobs_service._instance._llmobs_span_writer != original_span_writer
1374+
assert llmobs_service._instance._llmobs_span_writer.status == ServiceStatus.RUNNING
1375+
llmobs_service.disable()
1376+
os._exit(12)
1377+
1378+
_, status = os.waitpid(pid, 0)
1379+
exit_code = os.WEXITSTATUS(status)
1380+
assert exit_code == 12
1381+
llmobs_service.disable()
1382+
1383+
13621384
def test_llmobs_fork_recreates_and_restarts_eval_metric_writer():
13631385
"""Test that forking a process correctly recreates and restarts the LLMObsEvalMetricWriter."""
13641386
with mock.patch("ddtrace.llmobs._writer.BaseLLMObsWriter.periodic"):

0 commit comments

Comments
 (0)