Documentation
¶
Overview ¶
Package maping is the framework-agnostic Core of the mAPI-ng client: hosted, zero-config API observability for Go services (see docs/context.md). It owns config/env parsing, the in-process Summary aggregation (counters + a latency DDSketch per series), and the background Connect uploader.
The guiding contract is zero-config (CONFIG.md): the only required input is the ingest key. With no key resolved, NewRecorder returns a no-op recorder so adding mAPI-ng to a codebase is always safe — activation is a matter of flipping an env var, decoupled from the code change. The client fails open: setup and upload problems are logged (rate-limited) and surfaced in the dashboard, but never panic or block the host.
A framework adapter (e.g. client/gin) extracts the route template and final status after each request and calls Observe with a neutral Record.
Index ¶
- Constants
- func DownstreamElapsed(ctx context.Context) time.Duration
- func WithDownstreamTracking(ctx context.Context) context.Context
- type Config
- type NoStatusReason
- type Option
- func WithDeployID(id string) Option
- func WithDeployVersion(v string) Option
- func WithEndpoint(endpoint string) Option
- func WithEnvironment(env string) Option
- func WithFlushWindow(d time.Duration) Option
- func WithInstance(instance string) Option
- func WithKey(key string) Option
- func WithRegion(region string) Option
- func WithService(service string) Option
- type Record
- type Recorder
- type RoundTripper
- type Uploader
Constants ¶
const SdkVersion = "0.1.0"
SdkVersion is the client SDK version reported in every Envelope/Handshake for server-side compatibility handling.
Variables ¶
This section is empty.
Functions ¶
func DownstreamElapsed ¶ added in v0.2.0
DownstreamElapsed returns the total downstream time accumulated on ctx since WithDownstreamTracking installed the counter, or 0 when none was installed or no downstream call was recorded.
func WithDownstreamTracking ¶ added in v0.2.0
WithDownstreamTracking installs a fresh downstream-time accumulator on ctx and returns the derived context. An adapter calls it once at request start; every outbound request whose context descends from this one then folds its round-trip time into the same counter (see NewRoundTripper), which DownstreamElapsed reads back at request end. Without this call the RoundTripper is a no-op, so wiring is opt-in and costs nothing when unused.
Types ¶
type Config ¶
type Config struct {
Key string
Endpoint string
Service string
Instance string
FlushWindow time.Duration
// Deploy identity. These are stored, low-cardinality dimensions stamped onto
// every Envelope (not the client-side series key), so the dashboard can ask
// "did release X regress this endpoint?".
DeployVersion string
DeployID string
Environment string
Region string
}
Config is the resolved recorder configuration.
type NoStatusReason ¶ added in v0.2.0
type NoStatusReason uint32
NoStatusReason explains why a request finished without an HTTP status written (see classify → NO_STATUS). An adapter sets it on the Record; the Core records it only for NO_STATUS requests. The values mirror the proto NoStatusReason enum so the flush maps them straight through.
const ( NoStatusUnspecified NoStatusReason = 0 NoStatusContextCanceled NoStatusReason = 1 NoStatusContextDeadline NoStatusReason = 2 NoStatusWriteError NoStatusReason = 3 NoStatusPanic NoStatusReason = 4 NoStatusOther NoStatusReason = 5 )
The NoStatus* values enumerate why a request finished without an HTTP status. They mirror the proto NoStatusReason enum so the flush maps them straight through; NoStatusUnspecified is the zero value.
type Option ¶
type Option func(*Config)
Option configures a Recorder. Options follow the functional-options pattern; a code option always beats the matching env var, which beats the default (CONFIG.md precedence).
func WithDeployID ¶ added in v0.2.0
WithDeployID overrides the build identity (beats MAPING_DEPLOY_ID). When left unset it defaults to the VCS revision from the build info, if available.
func WithDeployVersion ¶ added in v0.2.0
WithDeployVersion overrides the release version (beats MAPING_DEPLOY_VERSION).
func WithEndpoint ¶
WithEndpoint overrides the collector URL (beats MAPING_ENDPOINT).
func WithEnvironment ¶ added in v0.2.0
WithEnvironment overrides the deployment environment (beats MAPING_ENVIRONMENT).
func WithFlushWindow ¶
WithFlushWindow overrides the flush window (beats MAPING_FLUSH_SECONDS).
func WithInstance ¶
WithInstance overrides the instance id (beats MAPING_INSTANCE).
func WithRegion ¶ added in v0.2.0
WithRegion overrides the deployment region (beats MAPING_REGION).
func WithService ¶
WithService overrides the logical service name (beats MAPING_SERVICE).
type Record ¶
type Record struct {
Method string
RouteTemplate string
Status int
Duration time.Duration
ReqBytes int64
RespBytes int64
TraceID string
SpanID string
RequestID string
// ErrorClass is an optional app/framework-supplied error label. The Core
// normalizes it to uppercase [A-Z0-9_] and bounds the distinct set per series;
// empty means the request carried no error label.
ErrorClass string
// NoStatusReason explains a NO_STATUS request (Status <= 0). It is ignored for
// requests that did write a status.
NoStatusReason NoStatusReason
// DownstreamDuration is the time this request spent waiting on downstream calls
// (outbound HTTP), captured by the maping RoundTripper. Zero when the host does
// not wire it or the request made no downstream calls.
DownstreamDuration time.Duration
}
Record is the neutral, framework-agnostic input to Observe. An adapter builds one from a completed request. TraceID/SpanID/RequestID are best-effort exemplar breadcrumbs: empty when the adapter cannot extract them.
type Recorder ¶
type Recorder struct {
// contains filtered or unexported fields
}
Recorder aggregates request Records in process and ships Summaries on a flush cycle. A recorder with no resolved key is a no-op: every method is safe and does nothing, and no goroutine runs.
func NewRecorder ¶
NewRecorder resolves config and returns a Recorder. If the resolved key is empty (zero-config safety), it returns a no-op recorder with no goroutine. On a transport construction failure it logs once at Warn and also returns the no-op recorder — the host is never affected (CONFIG.md fail-open).
func NewRecorderForTest ¶
NewRecorderForTest returns a running Recorder wired to an injected Uploader, with a minimal config. It is the seam adapter tests use to substitute a fake transport and assert what was observed, without a live collector.
func (*Recorder) BeginRequest ¶ added in v0.5.0
func (r *Recorder) BeginRequest() func()
BeginRequest marks a request as in flight and returns a function that marks it done; adapters call `defer rec.BeginRequest()()` at handler entry. It tracks the window peak concurrency for the InstanceWindow in_flight gauge. Safe on a no-op recorder and for concurrent use.
func (*Recorder) Observe ¶
Observe records one completed request. It is safe on a no-op recorder and safe for concurrent use.
The whole body is wrapped in a panic recovery: a bug in aggregation must be invisible to the host request (the core "mAPI-ng failing is invisible to the host" guarantee, docs/context.md). A recovered panic is logged once at Warn (rate-limited) and the observation is dropped.
Steady state (the series already exists) is allocation-free: shard select + lock + in-place counter increments + sketch.Add (itself alloc-free). Only the first sighting of a new series allocates (map insert + sketch.New).
func (*Recorder) Shutdown ¶
Shutdown stops the uploader goroutine, does a final flush (pushing the last window onto the ring), then synchronously drains the ring — attempting to send every pending request, bounded by ctx. A graceful shutdown therefore does not lose buffered summaries: it best-effort ships them before returning (this is what the E2E test relies on). Once ctx expires it stops retrying and returns; any still-pending requests are abandoned. It is synchronous and idempotent. Hosts must call it AFTER their http.Server.Shutdown so no request is still writing a Record.
type RoundTripper ¶ added in v0.2.0
type RoundTripper struct {
// contains filtered or unexported fields
}
RoundTripper wraps an http.RoundTripper and folds each outbound request's round-trip time into the downstream accumulator carried by the request context (installed by WithDownstreamTracking). A host sets it as the Transport of the http.Client it uses for downstream calls, and propagates the inbound request context to those calls, so mAPI-ng can split an endpoint's own time from time spent blocked on a dependency. When the context carries no accumulator it adds nothing and simply delegates, so it is safe to use everywhere.
func NewRoundTripper ¶ added in v0.2.0
func NewRoundTripper(base http.RoundTripper) *RoundTripper
NewRoundTripper wraps base so outbound round-trip time is attributed to the caller's request. A nil base falls back to http.DefaultTransport, matching the convention of the standard library's own transports.
type Uploader ¶
type Uploader interface {
Upload(ctx context.Context, req *mapingv1.UploadRequest) error
Register(ctx context.Context, hs *mapingv1.Handshake) error
}
Uploader is the transport dependency the Recorder needs. The concrete implementation lives in internal/transport; adapters and tests may inject a fake to observe uploads without a live collector (lang-go DI).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package adapterutil holds the framework-agnostic helpers shared by every mAPI-ng web adapter (gin today; echo/chi/beego/net-http next).
|
Package adapterutil holds the framework-agnostic helpers shared by every mAPI-ng web adapter (gin today; echo/chi/beego/net-http next). |
|
gin
module
|
|
|
internal
|
|
|
buffer
Package buffer implements a bounded, drop-oldest ring of pending UploadRequests for the mAPI-ng client's fail-open uploader (docs/context.md).
|
Package buffer implements a bounded, drop-oldest ring of pending UploadRequests for the mAPI-ng client's fail-open uploader (docs/context.md). |
|
transport
Package transport wraps the generated Connect IngestService client with the wire policy mAPI-ng requires: the gRPC protocol (ADR-0002) over a dedicated HTTP client with an explicit timeout, zstd send-compression, and cleartext HTTP/2 (H2C) for local/dev http:// endpoints.
|
Package transport wraps the generated Connect IngestService client with the wire policy mAPI-ng requires: the gRPC protocol (ADR-0002) over a dedicated HTTP client with an explicit timeout, zstd send-compression, and cleartext HTTP/2 (H2C) for local/dev http:// endpoints. |
|
Package sketch implements a hand-rolled DDSketch specialised for request latency aggregation, as decided in ADR-0001.
|
Package sketch implements a hand-rolled DDSketch specialised for request latency aggregation, as decided in ADR-0001. |