Skip to content

Commit 805e4d1

Browse files
lievangnufede
authored andcommitted
feat(llmobs): support sending 5mb events (#14172)
Support sending 5mb events in the python sdk ### Testing All 5mb events show up from this script ``` for i in range(100): with LLMObs.agent( "test" ): LLMObs.annotate( input_data = "heeee" * 970_000, output_data = "bye", ) ``` [We get all 200 events ](https://dd.datad0g.com/llm/traces?query=%40ml_app%3A5mb-load-test-sdk%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=false&llmtgc=categories&llmtgl=volume&spanId=199578092099801838&start=1753304058676&end=1753908858676&paused=false) <img width="1123" height="256" alt="image" src="https://github.com/user-attachments/assets/c91ad30f-c979-431a-93aa-81fa10e7df75" /> ## 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)
1 parent 68a9246 commit 805e4d1

File tree

6 files changed

+21
-23
lines changed

6 files changed

+21
-23
lines changed

ddtrace/llmobs/_constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
DD_SITES_NEEDING_APP_SUBDOMAIN = {"datadoghq.com", "datadoghq.eu", "ddog-gov.com"}
6060

6161
EVP_PAYLOAD_SIZE_LIMIT = 5 << 20 # 5MB (actual limit is 5.1MB)
62-
EVP_EVENT_SIZE_LIMIT = (1 << 20) - 1024 # 999KB (actual limit is 1MB)
62+
EVP_EVENT_SIZE_LIMIT = 5_000_000 # 5MB LLM Obs event size limit
6363

6464
EXPERIMENT_CSV_FIELD_MAX_SIZE = 10 * 1024 * 1024
6565

ddtrace/llmobs/_writer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ def enqueue(self, event: LLMObsSpanEvent) -> None:
523523
should_truncate = raw_event_size >= EVP_EVENT_SIZE_LIMIT
524524
if should_truncate:
525525
logger.warning(
526-
"dropping event input/output because its size (%d) exceeds the event size limit (1MB)",
526+
"dropping event input/output because its size (%d) exceeds the event size limit (5MB)",
527527
raw_event_size,
528528
)
529529
event = _truncate_span_event(event)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
features:
3+
- |
4+
LLM Observability: Increases span event size limit from 1MB to 5MB.

tests/llmobs/_utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ def _large_event():
446446
"output": {
447447
"messages": [
448448
{
449-
"content": "A" * 900_000,
449+
"content": "A" * 2_000_000,
450450
"role": "assistant",
451451
},
452452
]
@@ -477,14 +477,14 @@ def _oversized_llm_event():
477477
"role": "system",
478478
"content": "You are an evil dark lord looking for his one ring to rule them all",
479479
},
480-
{"role": "user", "content": "A" * 700_000},
480+
{"role": "user", "content": "A" * 2_600_000},
481481
],
482482
"parameters": {"temperature": 0.9, "max_tokens": 256},
483483
},
484484
"output": {
485485
"messages": [
486486
{
487-
"content": "A" * 700_000,
487+
"content": "A" * 2_600_000,
488488
"role": "assistant",
489489
},
490490
]
@@ -507,8 +507,8 @@ def _oversized_workflow_event():
507507
"status": "ok",
508508
"meta": {
509509
"span.kind": "workflow",
510-
"input": {"value": "A" * 700_000},
511-
"output": {"value": "A" * 700_000},
510+
"input": {"value": "A" * 2_600_000},
511+
"output": {"value": "A" * 2_600_000},
512512
},
513513
"metrics": {"input_tokens": 64, "output_tokens": 128, "total_tokens": 192},
514514
}
@@ -527,8 +527,8 @@ def _oversized_retrieval_event():
527527
"status": "ok",
528528
"meta": {
529529
"span.kind": "retrieval",
530-
"input": {"documents": {"content": "A" * 700_000}},
531-
"output": {"value": "A" * 700_000},
530+
"input": {"documents": {"content": "A" * 2_600_000}},
531+
"output": {"value": "A" * 2_600_000},
532532
},
533533
"metrics": {"input_tokens": 64, "output_tokens": 128, "total_tokens": 192},
534534
}

tests/llmobs/test_llmobs_span_agent_writer.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,11 @@ def test_flush_queue_when_event_cause_queue_to_exceed_payload_limit(mock_send_pa
4949
llmobs_span_writer.enqueue(_large_event())
5050
llmobs_span_writer.enqueue(_large_event())
5151
llmobs_span_writer.enqueue(_large_event())
52-
llmobs_span_writer.enqueue(_large_event())
53-
llmobs_span_writer.enqueue(_large_event())
54-
llmobs_span_writer.enqueue(_large_event())
5552
llmobs_span_writer.periodic()
5653
mock_writer_logs.debug.assert_has_calls(
5754
[
5855
mock.call("manually flushing buffer because queueing next event will exceed EVP payload limit"),
59-
mock.call("encoded %d LLMObs %s events to be sent", 5, "span"),
56+
mock.call("encoded %d LLMObs %s events to be sent", 2, "span"),
6057
mock.call("encoded %d LLMObs %s events to be sent", 1, "span"),
6158
],
6259
any_order=True,
@@ -71,9 +68,9 @@ def test_truncating_oversized_events(mock_send_payload, mock_writer_logs):
7168
llmobs_span_writer.enqueue(_oversized_workflow_event())
7269
mock_writer_logs.warning.assert_has_calls(
7370
[
74-
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (1MB)", 1400724),
75-
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (1MB)", 1400464),
76-
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (1MB)", 1400445),
71+
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (5MB)", 5200724),
72+
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (5MB)", 5200464),
73+
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (5MB)", 5200445),
7774
]
7875
)
7976

tests/llmobs/test_llmobs_span_agentless_writer.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,11 @@ def test_flush_queue_when_event_cause_queue_to_exceed_payload_limit(mock_send_pa
4343
llmobs_span_writer.enqueue(_large_event())
4444
llmobs_span_writer.enqueue(_large_event())
4545
llmobs_span_writer.enqueue(_large_event())
46-
llmobs_span_writer.enqueue(_large_event())
47-
llmobs_span_writer.enqueue(_large_event())
48-
llmobs_span_writer.enqueue(_large_event())
4946
llmobs_span_writer.periodic()
5047
mock_writer_logs.debug.assert_has_calls(
5148
[
5249
mock.call("manually flushing buffer because queueing next event will exceed EVP payload limit"),
53-
mock.call("encoded %d LLMObs %s events to be sent", 5, "span"),
50+
mock.call("encoded %d LLMObs %s events to be sent", 2, "span"),
5451
mock.call("encoded %d LLMObs %s events to be sent", 1, "span"),
5552
],
5653
any_order=True,
@@ -64,9 +61,9 @@ def test_truncating_oversized_events(mock_writer_logs):
6461
llmobs_span_writer.enqueue(_oversized_workflow_event())
6562
mock_writer_logs.warning.assert_has_calls(
6663
[
67-
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (1MB)", 1400724),
68-
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (1MB)", 1400464),
69-
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (1MB)", 1400445),
64+
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (5MB)", 5200724),
65+
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (5MB)", 5200464),
66+
mock.call("dropping event input/output because its size (%d) exceeds the event size limit (5MB)", 5200445),
7067
]
7168
)
7269

0 commit comments

Comments
 (0)