feat: declaration-first usage metering (ms.Meter + Record)#122
Merged
Conversation
213b70c to
9803ba7
Compare
9803ba7 to
41f5173
Compare
…by name) Declare each metric once in setup via ms.Meter(name, kind, ms.Unit/ms.Price) (side-effect registration into the manifest, no handle returned), then emit at runtime BY NAME with package-level ms.Record(ctx, name, value) — mirroring the existing ms.Emits/ms.Emit pair. No *Metric handle, no Gauge() method, no kind on the wire; the manifest-fed catalog is authoritative and the envelope stays v1. Guards: reserved infra.*/platform.* prefix + duplicate-name panic at declaration; undeclared-name + negative/non-finite value return an error from Record. Transport unchanged (MS_METER_LAMBDA_ARN / lambda.Invoke; dispatch-HTTP rewrite is PR #2). Fix defensive-nil bug: Record's dev-mode path (lambdaClient == nil) guards the logger before Printf, so a zero Client{} (or one from NewFromARN, which leaves logger nil) cannot panic. Adds a regression test. Design ref: docs-temp/milestone-d-meter/design.md §4/§5. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41f5173 to
0a025c0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Declaration-first usage metering — BY NAME
A module declares each metric once in setup, then emits by name at runtime — exactly mirroring the existing
ms.Emits(declare) /ms.Emit(emit by name) pair. No stored handle, noGauge()method, nokindon the wire.API
ms.Meter(name string, kind Kind, opts ...MetricOption)— registers the metric into the module manifest as a side effect; returns nothing (no*Metrichandle).Kindisms.Counterorms.Gauge; options arems.Unit(...)andms.Price(microDollars)(price optional). Mirrors howms.Emitsregisters.ms.Record(ctx context.Context, name string, value float64) error— package-level, mirrorsms.Emit. Resolves the declared metric by name from the registry; returns an error if the name was never declared viams.Meter(declaration-first, fail fast). No chaining.Guards
infra.*/platform.*prefix → panic at declaration (platform-measured, not module-declarable).Record→ error.Record→ error (never panics the handler).Wire / transport
kindfield on the wire — the manifest-fed catalog is authoritative; no production emitters to stay compatible with).MS_METER_LAMBDA_ARN/lambda.Invoke; dev = stderr). The dispatch-HTTP rewrite is PR docs: add SDK package structure to README #2.Design ref
docs-temp/milestone-d-meter/design.md§4 (Axis 1) / §5 (app-module-sdk).Review follow-ups (non-blocking)
Recorddev-mode path now guards the nilloggerbeforePrintf, so a zeroClient{}(or one fromNewFromARN, which leavesloggernil) cannot panic. Regression test added.ValidateMetricNamedeliberately restatesregistry.ValidateNamebecausemeteris a public package that cannot importinternal/registry; a sharedinternal/namecheckcould dedup later if it becomes a maintenance burden.NewFromARNleavesloggernil by design (dev sink only); the invariant is now safe via the nil-guard rather than implicit.internal/core (m *Module).MetercallsDeclarethenAddMetricin lockstep from a single call site; manifest/registry stay in sync.TestRecord_DevModeLogsToStderris non-parallel (uses a shared logger sink); not a correctness issue.