feat(llmobs): auto-tag git commit sha and repository url on spans and…#9446
feat(llmobs): auto-tag git commit sha and repository url on spans and…#9446gsvigruha wants to merge 3 commits into
Conversation
… experiments Attach git.commit.sha and git.repository_url to LLMObs spans and experiments, resolved under the widest set of circumstances (prod and local dev) without per-span cost. A new resolver (llmobs/git-metadata.js) reuses the existing file/env git metadata resolver and adds a git-CLI fallback (git rev-parse HEAD, git config --get remote.origin.url) for the typical dev checkout where no DD_GIT_* env vars or git.properties file exist. It honors DD_TRACE_GIT_METADATA_ENABLED, filters credentials out of the URL, only spawns git when a value is missing and git is available, and caches the result for the process lifetime so the subprocess never touches a hot path. Spans get the tags via the span processor (resolved once at enable) with user-supplied git.* tags winning; experiments fold them in as defaults under user tags on both spans and metrics. getCommitSHA is extracted in plugins/util/git.js and reused by getGitInformationDiscrepancy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Overall package sizeSelf size: 7.48 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.2 | 124.41 kB | 440.65 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
|
There was a problem hiding this comment.
More details
PR auto-tags LLMObs spans and experiments with git metadata (commit SHA and repository URL) resolved via file/env and git CLI. All 73 tests pass; tag merge order ensures user-supplied tags override system defaults; caching is process-lifetime to avoid hot-path subprocess spawns; credentials are filtered from URLs. No behavioral regressions detected.
📊 Validated against 73 scenarios · Open Bits AI session
🤖 Datadog Autotest · Commit 369b618 · What is Autotest? · Any feedback? Reach out in #autotest
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 369b6188a8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| * @returns {{ commitSHA: string | undefined, repositoryUrl: string | undefined }} | ||
| */ | ||
| function resolveLLMObsGitMetadata (config) { | ||
| if (cache) return cache |
There was a problem hiding this comment.
Keep disabled git metadata cache separate
When this resolver is first called with DD_TRACE_GIT_METADATA_ENABLED=false, it stores the empty disabled result in the single module-level cache; any later LLMObs initialization in the same process with git metadata enabled will hit this early return and never consult env/file/CLI metadata, so spans and experiments remain untagged. This call-order exists in multi-config test processes and matches the regression the shared git_metadata helper avoids by caching disabled and enabled results independently.
Useful? React with 👍 / 👎.
|
|
||
| // Only spawn the CLI when the file/env reads left something missing and git | ||
| // is actually installed — avoids failed subprocess spawns + error telemetry. | ||
| if ((!commitSHA || !repositoryUrl) && isGitAvailable()) { |
There was a problem hiding this comment.
Avoid running git outside a repository
When LLMObs starts in a production image that has the git binary but no checked-out .git directory and no DD_GIT_* metadata, isGitAvailable() passes and this block runs git rev-parse HEAD / git config --get remote.origin.url; checked outside a repo, git rev-parse HEAD exits 128 with fatal: not a git repository, and sanitizedExec logs that as a Git plugin error. That makes normal “metadata unavailable” startups emit error-level logs, so this fallback should first verify the cwd is inside a work tree or use a silent failure path.
Useful? React with 👍 / 👎.
| if (this.#gitCommitSHA) tags[GIT_COMMIT_SHA] = this.#gitCommitSHA | ||
| if (this.#gitRepositoryUrl) tags[GIT_REPOSITORY_URL] = this.#gitRepositoryUrl |
There was a problem hiding this comment.
Update LLMObs tests for injected git tags
With the default DD_TRACE_GIT_METADATA_ENABLED=true, real useLlmObs() tests run from this git checkout will now add git.commit.sha and git.repository_url to every formatted LLMObs span, but packages/dd-trace/test/llmobs/util.js still exact-matches the tag array length and expected entries. Existing SDK/plugin tests that call assertLlmObsSpanEvent without git tags will fail unless the helper accounts for these auto tags or the tests disable git metadata.
Useful? React with 👍 / 👎.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #9446 +/- ##
==========================================
- Coverage 98.41% 98.36% -0.05%
==========================================
Files 938 939 +1
Lines 126209 126293 +84
Branches 10744 10683 -61
==========================================
+ Hits 124207 124227 +20
- Misses 2002 2066 +64 Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
BenchmarksBenchmark execution time: 2026-07-20 23:37:31 Comparing candidate commit 30c2550 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 2325 metrics, 33 unstable metrics.
|
The new git.commit.sha / git.repository_url span tags are derived from the checkout the tests run in, so their values are environment-dependent and can't be pinned in the exact-tag assertions the LLMObs plugin harness makes. Disable DD_TRACE_GIT_METADATA_ENABLED in the useLlmObs harness so provider plugin tests stay deterministic; the git-tagging behavior itself is covered in span_processor.spec and git-metadata.spec. Also wrap an over-long tagMap.set call to satisfy max-len. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address review feedback on the LLMObs git metadata resolver: - Cache enabled and disabled results independently (mirroring git_metadata.js) so a disabled first call no longer short-circuits a later enabled initialization in the same process. - Gate the git-CLI fallback on the .git folder existing, not just on the git binary being installed. A production image that ships git but no checkout would otherwise run `git rev-parse HEAD` on every startup, get exit 128, and log it as a Git plugin error. The folder gate keeps the dev-env benefit (e.g. packed refs where .git exists but file parsing misses) while staying silent when there is no repository. Extends the resolver spec to cover both branches and restore 100% patch coverage. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… experiments
Attach git.commit.sha and git.repository_url to LLMObs spans and experiments, resolved under the widest set of circumstances (prod and local dev) without per-span cost.
A new resolver (llmobs/git-metadata.js) reuses the existing file/env git metadata resolver and adds a git-CLI fallback (git rev-parse HEAD, git config --get remote.origin.url) for the typical dev checkout where no DD_GIT_* env vars or git.properties file exist. It honors DD_TRACE_GIT_METADATA_ENABLED, filters credentials out of the URL, only spawns git when a value is missing and git is available, and caches the result for the process lifetime so the subprocess never touches a hot path.
Spans get the tags via the span processor (resolved once at enable) with user-supplied git.* tags winning; experiments fold them in as defaults under user tags on both spans and metrics. getCommitSHA is extracted in plugins/util/git.js and reused by getGitInformationDiscrepancy.
What does this PR do?
Motivation
Additional Notes