You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(serverless-init): attach per-instance tag to MicroVM enhanced usage metric (#53230)
Codex flagged this on PR #53093 ([review
comment](#53093 (comment))):
MicroVM's enhanced usage metric (`aws.lambda.microvm.instance`) is
emitted with the same static tag set for every MicroVM booted from a
given image.
`MicroVM.GetEnhancedMetricTags` computes the `Usage` tag set once at
startup — before the MicroVM's instance ID is known, since the platform
only reveals it via the `/run` lifecycle hook — and nothing ever updates
it afterward. Under normal autoscaling, with multiple concurrent
MicroVMs running from the same image, their periodic usage samples are
indistinguishable from one another: instance-level usage collapses into
a single series.
The obvious fix — mutate the frozen tag set on `ServerlessMetricAgent`
once `/run` reveals the instance ID, mirroring the existing
`LogsTagSetter`/`TraceTagSetter` pattern — turned out to require a
lock/atomic on `ServerlessMetricAgent`. That struct is passed **by
value** into `CloudService.Shutdown` across every cloud service
(`AppService`, `CloudRun`, `CloudRunJobs`, `ContainerApp`,
`LocalService`, `MicroVM`), so adding any lock-bearing field trips `go
vet`'s copylocks check everywhere, not just for MicroVM.
Instead, this attaches the tag at the point of *emission* rather than
mutating shared state:
- `lifecycle.Server` already tracks the instance ID race-free
(`instanceID *atomic.String`, captured in `handleRun`). Added
`InstanceID()`, a nil-safe accessor, so callers outside the `lifecycle`
package can read it.
- `MicroVM.CurrentUsageMetricTags()` turns that into an
`"instance:<id>"` tag, or `nil` before `/run` has fired.
- `enhancedmetrics.Collector` gained an optional `usageMetricTagsFunc`,
invoked on every collection tick and passed straight through the
existing `AddEnhancedUsageMetric(..., extraTags ...string)` parameter —
no new shared mutable state needed.
- `main.go` duck-types `cloudService` against a local
`usageMetricTagProvider` interface to wire this hook. Every other cloud
service doesn't implement it, so `usageMetricTagsFunc` stays `nil` for
them and their usage metrics are unaffected.
This keeps the change scoped to MicroVM plus small, nil-safe, additive
plumbing in the shared collector — no other cloud service,
`ServerlessMetricAgent`, or the `Shutdown` interface needed to change.
- [x] `dda inv test --targets=./cmd/serverless-init/...` — all 281 tests
pass (12 new: `InstanceID()` nil/before/after `/run`,
`CurrentUsageMetricTags()` nil-server/before-run/after-run end-to-end,
collector dynamic-tag forwarding + nil-func regression guard,
`NewCollector` wiring, and the `usageMetricTagProvider` type-assertion
pinning `*MicroVM` in vs. every other cloud service out)
- [x] `gofmt -l` clean on all changed files
- [x] `dda inv linter.go --targets=./cmd/serverless-init/...` — 0 issues
- [ ]
`cmd/serverless-init/enhanced-metrics/collector.go`/`collector_test.go`
carry a pre-existing `//go:build linux` tag; this session ran on macOS
without a Linux cross-toolchain, so those specific new tests are
syntax-checked (`gofmt -e`) and reviewed but not yet executed — first
real run will be in Linux CI
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
0 commit comments