Skip to content

chore(logger): unify structured-log identifier keys and gate against drift - #3739

Closed
AdaAibaby wants to merge 1 commit into
e2b-dev:mainfrom
AdaAibaby:chore/unify-log-field-keys
Closed

AdaAibaby wants to merge 1 commit into
e2b-dev:mainfrom
AdaAibaby:chore/unify-log-field-keys

Conversation

@AdaAibaby

@AdaAibaby AdaAibaby commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3738.

Problem

Identifier fields are logged three ways across services — dotted via the logger.With* helpers (sandbox.id, team.id), snake_case (team_id, build_id), and camelCase (teamID, buildID). A build ID alone appears under 8+ spellings. The result: log queries/alerts must match each concept under several names, and cross-service correlation (client-proxy instance_id ↔ api sandbox.id ↔ orchestrator instanceID) is manual.

Why a grep gate, not forbidigo

.golangci.yml already runs forbidigo, but it matches the called function name, not a string-literal argument. Verified in an isolated module: a rule on zapString("team_id" does not fire; a rule on zapString fires on every call. So it cannot forbid zap.String("team_id", …). Hence a grep gate.

Changes

  • fields.go: canonical key constants (KeySandboxID, KeyTeamID, …) as the single source of truth; every With* helper returns one of them. Standard is the dotted "<noun>.id" the Vector pipeline already normalises on (packages/local-dev/vector.toml).
  • 24 raw call sites across api, orchestrator, client-proxy, clickhouse, dashboard-api converted to the matching logger.With* helper (incl. two cluster_id/clusterID sites the gate itself surfaced that a first manual pass missed).
  • scripts/check-log-field-keys.sh: grep gate; fails if a raw identifier key reappears. Wired into Makefile (make check-log-field-keys) and the lint CI workflow. Self-tested: injecting a raw key → exit 1, removing it → exit 0.
  • logger/sandbox/metadata.go: the deliberate instanceID/envID aliases kept for the Vector migration window are marked log-key-exempt: and documented, instead of silently tripping the gate.
  • fields_keys_test.go: locks each helper to its canonical key, forbids duplicate keys, and enforces lowercase-dotted (no snake_case/camelCase).

Verification

  • go build ./... clean for all 6 affected modules; go vet on logger clean.
  • go test ./pkg/logger/... green incl. the new TestCanonicalFieldKeys.
  • gate passes on the branch (0 hits) and fails on an injected violation.

Migration window (not in this PR)

vector.toml already reads both the dotted keys (."team.id", ."sandbox.id", …) and the legacy instanceID/envID, so nothing downstream breaks now. The metadata.go double-write can be removed once logs predating this change age out of retention; the matching vector.toml remap lines go with it.

/cc @jakubno @dobrac @ValentaTomas @arkamar @tvi @ryan-sana @ben-fornefeld Looking forward to your code review.

…drift

Identifier fields were logged three ways across services — dotted
(sandbox.id, team.id, via the logger.With* helpers), snake_case
(team_id, build_id), and camelCase (teamID, buildID). A single concept
like a build ID appeared under 8+ spellings, so log queries and alerts had
to match each concept under several names, and cross-service correlation
(client-proxy instance_id <-> api sandbox.id <-> orchestrator instanceID)
needed manual mapping.

This standardises on the dotted "<noun>.id" convention the Vector pipeline
already normalises on (packages/local-dev/vector.toml), and prevents
regressions:

- fields.go: add canonical key constants (KeySandboxID, KeyTeamID, ...) as
  the single source of truth; every With* helper now returns one of them.
- Convert all 24 raw zap.String("team_id"/"buildID"/...) identifier call
  sites across api, orchestrator, client-proxy, clickhouse and dashboard-api
  to the matching logger.With* helper.
- scripts/check-log-field-keys.sh: a grep gate that fails if a raw identifier
  key reappears. golangci-lint's forbidigo cannot express this — it matches
  the called function name, not a string-literal argument (verified), so a
  script gate is the only option. Wired into Makefile (check-log-field-keys)
  and the lint CI workflow.
- logger/sandbox/metadata.go: the deliberate instanceID/envID aliases kept
  for the Vector migration window are marked "log-key-exempt:" and documented,
  rather than silently tripping the gate.
- fields_keys_test.go: locks each helper to its canonical key, forbids
  duplicates, and enforces lowercase-dotted (no snake_case/camelCase).

Vector migration window: vector.toml already reads the dotted keys
(."team.id", ."sandbox.id", ...) as well as the legacy instanceID/envID, so
nothing downstream breaks now. The legacy double-write in metadata.go can be
dropped once logs predating this change age out of retention.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logging: unify structured-log identifier keys (sandbox/team/template/build/node/cluster) across services

3 participants