Add dynamic session context (git branch, cwd, PR) to OTel log record attributes
Feature Request
Add dynamic session context as log record attributes (not resource attributes) so they reflect the current state at emit time, not just at session startup.
Motivation
I run an observability stack (OTel Collector → Prometheus + Loki → Grafana) to monitor Claude Code usage across my team. I want to answer questions like:
- Which git branches cost the most? (correlate
cost.usagewith branch context) - Which Linear tickets consumed the most tokens? (track
token.usageby ticket) - Which PRs took the longest? (associate
tool_resultdurations with PR numbers) - Which projects/repos are heaviest users? (break down usage by working directory)
Today, the only way to attach this context is via OTEL_RESOURCE_ATTRIBUTES, which is:
- Static — set once at process startup, frozen for the entire session
- Requires a shell wrapper — doesn't work with launchers like Conductor, Zed (ACP), or JetBrains
- Stale mid-session — if I switch branches or directories during a session, the attributes don't update
Proposed Solution
Add a small set of dynamic attributes to each log record at emit time, using the existing LogRecordProcessor.onEmit() pattern that Claude Code already uses for tool_name, duration_ms, success, etc.
Suggested attributes (using OTel semantic conventions where available):
| Attribute | Source | OTel Convention |
|---|---|---|
| vcs.ref.head.name | git branch --show-current | VCS semconv |
| vcs.repository.url.full | git remote get-url origin | VCS semconv |
| process.working_directory | process.cwd() | Common attribute |
| vcs.ref.head.revision | git rev-parse HEAD (short) | VCS semconv |
Optional derived attributes (high value for project management):
| Attribute | Derivation |
|---|---|
| project.linear_key | Extract [A-Z]+-[0-9]+ pattern from branch name |
| project.github_pr | gh pr view --json number or from branch metadata |
| project.repo_name | Basename of repo root or from remote URL |
Implementation sketch
This follows the exact same pattern Claude Code already uses for per-event attributes:
class SessionContextLogProcessor implements LogRecordProcessor {
onEmit(logRecord: LogRecord): void {
// These are cheap and reflect current state at emit time
logRecord.setAttribute('process.working_directory', process.cwd());
// Cache git info with a short TTL (e.g., 30s) to avoid repeated exec
const gitContext = this.getCachedGitContext();
if (gitContext.branch) {
logRecord.setAttribute('vcs.ref.head.name', gitContext.branch);
}
if (gitContext.repoUrl) {
logRecord.setAttribute('vcs.repository.url.full', gitContext.repoUrl);
}
}
}
Why log record attributes, not resource attributes?
Per the OTel spec, resources are "an immutable representation of the entity producing telemetry." Session context (branch, directory) can change mid-session and belongs on individual log records. The OTel TC explicitly recommended this approach in opentelemetry-specification#1298.
Current Workaround
I built a shell wrapper that sets OTEL_RESOURCE_ATTRIBUTES dynamically before each claude invocation:
claude() {
local attrs="environment=dev,user=$(whoami)"
attrs="${attrs},working.directory=$(basename "$PWD")"
local branch=$(git branch --show-current 2>/dev/null)
[[ -n "$branch" ]] && attrs="${attrs},git.branch=${branch}"
OTEL_RESOURCE_ATTRIBUTES="$attrs" command claude "$@"
}
This works for direct CLI usage but:
- Doesn't work with Conductor, Zed (ACP), JetBrains, or any launcher that spawns Claude Code as a subprocess
- Context is frozen at session start — doesn't update if I switch branches
- Requires a transform processor in the OTel Collector to copy resource attributes to log record attributes for Loki visibility
Impact
This would enable powerful analytics out of the box:
- Cost attribution by project, branch, ticket, and PR
- Productivity analysis by repo and feature branch
- Resource planning based on which types of work consume the most tokens
- Project management integration — correlate Claude Code usage with Linear/GitHub work items
Environment
- Claude Code v2.1.64
- OTel Collector contrib v0.145.0
- Loki + Grafana for log analysis
- Launchers: CLI, Conductor, Zed (ACP)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗