Skip to content

feat(llmobs): add LLM Observability SDK#3938

Merged
dd-mergequeue[bot] merged 42 commits into
mainfrom
rarguelloF/AIDM-708/llmobs-client
Oct 8, 2025
Merged

feat(llmobs): add LLM Observability SDK#3938
dd-mergequeue[bot] merged 42 commits into
mainfrom
rarguelloF/AIDM-708/llmobs-client

Conversation

@rarguelloF

@rarguelloF rarguelloF commented Sep 2, 2025

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR adds the Go SDK for the DataDog LLM Observability product (https://docs.datadoghq.com/llm_observability/instrumentation/sdk/).

It includes support for the main LLM Observability features:

  • Creating/annotating spans.
  • Context propagation.
  • Submitting evaluation metrics.
  • Datasets and Experiments.

It includes the following new options and changes in the ddtrace/tracer package:

  • WithLLMObsEnabled (equivalent to DD_LLMOBS_ENABLED) - false by default.
  • WithLLMObsMLApp (equivalent to DD_LLMOBS_ML_APP)
  • WithLLMObsProjectName (equivalent to DD_LLMOBS_PROJECT_NAME)
  • WithLLMObsAgentlessEnabled (equivalent to DD_LLMOBS_AGENTLESS_ENABLED)
  • Now the functions tracer.Start|Stop|Flush call internal/llmobs.Start|Stop|Flush respectively if llmobs is enabled and forwards the error (if applicable).
  • Raises the default max size of the X-Datadog-Tags header from 128 to 512. This was necessary to include the llmobs headers required for context propagation, and aligns with the default value in other tracers.

The llmobs public api is divided in the following packages:

  • llmobs contains the main spans / metrics functionality.
  • llmobs/experiment contains the api to work with LLM Observability Experiments.
  • llmobs/dataset contains the api to work with LLM Observability Dataset.

The llmobs internal api is divided in the following packages:

  • internal/llmobs: contains most of the core logic of llmobs, including the main worker that receives spans/metrics and flushes periodically or by demand.
  • internal/llmobs/transport: contains all the payload definitions and logic to communicate with the LLMObs backend.
  • internal/llmobs/config: contains the global configuration for all LLMObs features.

Motivation

Support DataDog LLM Observability in dd-trace-go.

Reviewer's Checklist

  • Changed code has unit tests for its functionality at or near 100% coverage.
  • System-Tests covering this feature have been added and enabled with the va.b.c-dev version tag.
  • There is a benchmark for any new code, or changes to existing code.
  • If this interacts with the agent in a new way, a system test has been added.
  • New code is free of linting errors. You can check this by running ./scripts/lint.sh locally.
  • Add an appropriate team label so this PR gets put in the right place for the release notes.
  • Non-trivial go.mod changes, e.g. adding new modules, are reviewed by @DataDog/dd-trace-go-guild.

Unsure? Have a question? Request a review!

@pr-commenter

pr-commenter Bot commented Sep 2, 2025

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2025-10-08 14:15:56

Comparing candidate commit 3c58818 in PR branch rarguelloF/AIDM-708/llmobs-client with baseline commit 23545d4 in branch main.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 15 metrics, 0 unstable metrics.

Comment thread llmobs/internal/dne_client.go Fixed
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Sep 2, 2025

Copy link
Copy Markdown

✅ Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 3c58818 | Docs | Was this helpful? Give us feedback!

Comment thread llmobs/internal/errors/errors.go Outdated
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2025 Datadog, Inc.

package errors

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a similar package that we merged a bit ago. Could it cover the use cases we have here, instead of creating a new package for it? We can add more functionality to the other package as needed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! I didn't know this existed. I already refactored the code to use this package, will push the changes shortly 🙏

Comment thread internal/llmobs/transport/transport.go Fixed

rarguelloF commented Oct 6, 2025

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

Comment thread ddtrace/tracer/context.go Outdated
Comment thread ddtrace/tracer/span.go Outdated
Comment thread llmobs/option.go Outdated
// ------------- Start options -------------

// StartSpanOption configures span creation. Use with Start*Span functions.
type StartSpanOption = func(cfg *illmobs.StartSpanConfig)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rarguelloF Is there any reason to use an alias here instead of defining the type as it's done here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch! this was unintended, will change it.

Comment thread llmobs/option.go Outdated
// ------------- Finish options -------------

// FinishSpanOption configures span finishing. Use with span.Finish().
type FinishSpanOption = func(cfg *illmobs.FinishSpanConfig)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous comment applies here too.

Comment thread llmobs/llmobs.go Outdated
Comment thread llmobs/experiment/experiment.go
Comment thread llmobs/experiment/experiment.go
@darccio

darccio commented Oct 6, 2025

Copy link
Copy Markdown
Member

It's possible I didn't catch more cases where I prefer to invert the conditional and exit earlier. I'm applying "The happy path is left-aligned" idiom.

@darccio

darccio commented Oct 6, 2025

Copy link
Copy Markdown
Member

@rarguelloF Please check my PR for avoiding interfaces as returned values #4028

@genesor genesor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, small comments about comments that we could benefit from.

Comment thread ddtrace/tracer/llmobs.go
"github.com/DataDog/dd-trace-go/v2/internal/llmobs"
)

type llmobsTracerAdapter struct{}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment here explaining why it exists, how and when it's used would be great

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense! adding it

Comment thread ddtrace/tracer/llmobs.go
return &llmobsSpanAdapter{span}, ctx
}

type llmobsSpanAdapter struct {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Comment thread ddtrace/tracer/context.go
return illmobs.ContextWithPropagatedLLMSpan(newCtx, propagatedLLMObs)
}

func propagatedLLMSpanFromTags(s *Span) *illmobs.PropagatedLLMSpan {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this function be in the llmobs package ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function reads the span's trace propagating tags (which are basically the tags that come from the X-Datadog-Tags header), which is all in private fields, so it cannot be outside of this package. I will add a clarifying comment on this function 👍

@rarguelloF

Copy link
Copy Markdown
Contributor Author

/merge

@dd-devflow-routing-codex

dd-devflow-routing-codex Bot commented Oct 8, 2025

Copy link
Copy Markdown

View all feedbacks in Devflow UI.

2025-10-08 14:01:10 UTC ℹ️ Start processing command /merge


2025-10-08 14:01:21 UTC ℹ️ MergeQueue: waiting for PR to be ready

This merge request is not mergeable yet, because of pending checks/missing approvals. It will be added to the queue as soon as checks pass and/or get approvals.
Note: if you pushed new commits since the last approval, you may need additional approval.
You can remove it from the waiting list with /remove command.


2025-10-08 14:34:38 UTC ℹ️ MergeQueue: merge request added to the queue

The expected merge time in main is approximately 18m (p90).


2025-10-08 14:53:54 UTC ℹ️ MergeQueue: This merge request was merged

@dd-mergequeue
dd-mergequeue Bot merged commit 5603e37 into main Oct 8, 2025
352 of 355 checks passed
@dd-mergequeue
dd-mergequeue Bot deleted the rarguelloF/AIDM-708/llmobs-client branch October 8, 2025 14:53
hannahkm pushed a commit that referenced this pull request Oct 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apm:ecosystem contrib/* related feature requests or bugs mergequeue-status: done

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants