Documentation
¶
Overview ¶
Package obs bundles the library's injected observability — a zap logger, an OTel tracer, and the metric instruments — built once from the embedder's configuration and handed to each subsystem.
As a library, oteldb/storage never owns a global logger, tracer, or meter: the embedder supplies them through Config (via storage.Options). Every handle is **no-op by default** — an unset logger becomes zap.Nop, an unset provider becomes the OTel noop provider — so an unconfigured store spans, logs, and counts nothing and pays no overhead. The library imports only the OTel API (never an SDK or exporter); the embedder owns the SDK, sampling, and pipelines.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExtractHTTP ¶
ExtractHTTP returns ctx augmented with the trace context read from the request headers, so a receiving handler's spans (and the engine spans below it) join the caller's trace. With the default no-op propagator it returns ctx unchanged.
func InjectHTTP ¶
InjectHTTP writes the trace context from ctx into the request headers, so a node-to-node RPC carries the distributed trace. It uses the globally-configured OTel propagator (set by the embedder, e.g. propagation.TraceContext{}); the default is a no-op that writes nothing, so an unconfigured store propagates nothing at no cost.
Types ¶
type Admission ¶
type Admission struct {
// contains filtered or unexported fields
}
Admission holds the ingest/admission meta-metrics (DESIGN §8a — observability is mandatory for overload control). They are recorded in **bulk** (one Add per write call per reason, never per-point), so they cost nothing on the hot inner loops. With the no-op meter every Add is a no-op.
func (*Admission) Accepted ¶
Accepted records n points accepted for the given signal. A zero n is ignored.
func (*Admission) Overflowed ¶ added in v0.10.0
Overflowed records n points routed to an overflow series past the soft cardinality budget for the given signal. A zero n is ignored.
type Backend ¶
type Backend struct {
// contains filtered or unexported fields
}
Backend instruments the L1 object-store operations.
type Cluster ¶ added in v0.40.0
type Cluster struct {
// contains filtered or unexported fields
}
Cluster instruments this node's standing in the cluster member set — the state that decides whether any peer routes anything here at all. self_absent is the alertable form of a node that is up and serving but missing from etcd: the failure this cannot be inferred from any other signal, because the node itself looks perfectly healthy while it is happening.
type Config ¶
type Config struct {
Logger *zap.Logger
TracerProvider trace.TracerProvider
MeterProvider metric.MeterProvider
}
Config is the embedder-supplied observability configuration. A nil field selects the no-op implementation for that pillar.
type Disk ¶ added in v0.40.0
type Disk struct {
// contains filtered or unexported fields
}
Disk instruments the medium's ability to take what the node accepts. A full disk or an exhausted inode table is not a transient backend fault: the node keeps acking writes it cannot store, so the two states need separate signals — a gauge that stands while the engine refuses writes, and a counter of the writes it refused.
func (*Disk) Record ¶ added in v0.40.0
Record publishes a signal's disk-pressure state: whether its engine is currently refusing writes for want of room, and how many writes it refused since the previous call. Both are published together, from the flush that decides the state — the ingest path that counts a rejection carries no context of its own, and a counter is as useful at flush cadence as per write.
type Fetch ¶
type Fetch struct {
// contains filtered or unexported fields
}
Fetch instruments a fetch over the head ∪ parts.
func (*Fetch) ForcedAdmission ¶ added in v0.37.0
ForcedAdmission accounts one query admitted over the decode-memory ceiling because its wait made no progress. It is a liveness escape, so a non-zero rate means the budget is oversubscribed (or a caller holds several unscoped reads open) and the ceiling is not holding.
type Flush ¶
type Flush struct {
// contains filtered or unexported fields
}
Flush instruments a head→part flush.
type Merge ¶
type Merge struct {
// contains filtered or unexported fields
}
Merge instruments a background merge (compaction/retention/downsample/recompress).
type Obs ¶
type Obs struct {
Log *zap.Logger
Tracer trace.Tracer
Admission *Admission
Flush *Flush
Merge *Merge
Parts *Parts
Fetch *Fetch
Backend *Backend
WAL *WAL
RPC *RPC
Cluster *Cluster
Disk *Disk
}
Obs is the observability handle passed to each subsystem. Log and Tracer are always non-nil (no-op when unconfigured); Admission holds the ingest meta-metrics.
func New ¶
New builds the observability handle, defaulting each unset pillar to its no-op implementation. It returns an error only if the meter rejects an instrument name (it does not for valid names).
func NewNop ¶
func NewNop() *Obs
NewNop returns a fully no-op handle (the default for tests and unconfigured stores). It never errors.
func (*Obs) Base ¶
Base installs the injected logger as the zctx base in ctx, so any layer below can retrieve a trace-correlated logger via zctx.From without holding the obs handle. Seed it at each operation entry, before starting the span; zctx.From then attaches span_id/trace_id from the active span.
type Parts ¶ added in v0.37.0
type Parts struct {
// contains filtered or unexported fields
}
Parts reports the merge selector's view of a signal's flushed parts as gauges: how many parts there are, how many are sealed (no merge will reconsider them), how many a merge may still take, how many the next merge would select, and the seal threshold in effect. Gauges rather than a log line because the question they answer — is compaction ever going to reduce this part count? — is asked of a dashboard over time, not of one cycle.
func (*Parts) Record ¶ added in v0.37.0
func (p *Parts) Record(ctx context.Context, sig string, total, sealed, backlog, candidates, capBytes int64)
Record publishes one signal's part shape, summed over the tenants this node holds. The values are tagged by signal only: tenant ids are unbounded, and [storage.Storage.Inspect] is the per-tenant surface.
type RPC ¶
type RPC struct {
// contains filtered or unexported fields
}
RPC instruments the node-to-node cluster transport's reliability behavior: how often calls are attempted, retried, or hedged (an opportunistic concurrent attempt fired because the in-flight one was slow). Counts are tagged by op ("read"/"write"/"series"/"side"), so a rising retry/hedge rate localizes a degrading link or peer.
func (*RPC) ShardAbsent ¶ added in v0.37.0
ShardAbsent accounts one read of a shard this node is a ring owner of but holds no data for, so the read failed over to another owner instead of answering empty. A sustained rate means the ring and the data disagree — a rebalance whose backfill has not caught up, or a lagging membership view.
func (*RPC) ShardIncomplete ¶ added in v0.38.0
ShardIncomplete accounts one read of a shard this node holds but cannot fully answer for: it came back from a restart (or a rebalance) without the head the shard held unflushed, so the query window overlaps data only another owner has, and the read failed over. It clears once the shard's parts cover that window; a sustained rate means no owner is flushing.