tracesampler

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package tracesampler is the shared post-trace sampler engine behind the first-party sw-trace-sampler and zipkin-trace-sampler plugins. Both plugins implement the same keep logic from docs/design/post-trace-pipeline.md (Scenario 6.1 for SkyWalking segments, 6.2 for Zipkin) — a duration threshold, sure-keep error and tag rules, and a deterministic healthy sample — and differ only in how each schema physically stores the columns those rules read. That per-schema knowledge is a Schema value passed to New; everything else lives here so the two plugins stay a few lines each and cannot drift apart.

Tag matching accounts for the real BanyanDB trace layout SkyWalking writes: searchable tags are not first-class columns but "key=value" entries flattened into one string-array column ("tags" for segments, "query" for Zipkin), so every keepTagRules entry is matched against that array.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(configJSON []byte, schema Schema) (sdk.Sampler, error)

New parses and validates the operator config against the given Schema, compiles any regex matchers, and computes the projection. A returned error rejects the plugin at admission.

Types

type Sampler

type Sampler struct {
	// contains filtered or unexported fields
}

Sampler keeps a trace when any sure-keep rule matches, and otherwise admits a deterministic fraction of the healthy remainder. It implements sdk.Sampler.

func (*Sampler) Close

func (s *Sampler) Close() error

Close releases resources; this sampler holds none.

func (*Sampler) Decide

func (s *Sampler) Decide(batch *sdk.TraceBatch) (sdk.Verdict, error)

Decide returns a keep-mask aligned to batch.Traces. The batch is read-only. It never returns an error: a per-row decode failure fails open for that trace (kept), so one malformed value can never make the sampler drop data.

func (*Sampler) Kind

func (s *Sampler) Kind() sdk.Kind

Kind reports the sampler kind, satisfying the generic sdk.Plugin interface that sdk.Sampler embeds.

func (*Sampler) Project

func (s *Sampler) Project() sdk.Projection

Project declares the columns the verdict reads: the duration and start-time columns (when a duration threshold is set), the error column (when keepErrors is set), the flattened array column (when any tag rule is configured, or the error signal lives there), plus the span-id column only when a span-count rule is configured.

Spans stays false, so the verdict never reads span bodies. The merge can copy a unique raw block unchanged while decoding only these projected columns for evaluation. A trace split across physical blocks still takes the ordinary decoded path because compaction must consolidate its output blocks.

func (*Sampler) UseHost

func (s *Sampler) UseHost(host sdk.Host)

UseHost binds the sampler's decision counter to its group-scoped host.

type Schema

type Schema struct {
	// ArrayTagColumn is the flattened searchable-tag column: a string array of
	// "key=value" entries — "tags" for the SkyWalking segment schema, "query"
	// for the Zipkin schema. Every keepTagRules entry resolves here: a rule whose
	// tagKey is this column's own name matches raw entries, and any other tagKey
	// matches the value of the "tagKey=" entries.
	ArrayTagColumn string
	// ErrorTag is what keepErrors reads. An empty ErrorTag means the schema has no
	// error signal at all and keepErrors is rejected at construction.
	ErrorTag string
	// DurationTag and StartTimeTag drive the durationThresholdMs rule, which
	// keeps a trace whose end-to-end envelope reaches the threshold. The envelope
	// is max(start + duration) - min(start) over the trace's rows, computed from
	// these two per-row tags. This is the true trace duration: it catches traces
	// that are slow only through sequential segments.
	//
	// DO NOT replace this with the intrinsic MaxTS - MinTS, however tempting the
	// saving. sdk.TraceBlock documents MaxTS as "the latest span end ... trace
	// duration is MaxTS - MinTS" and _example/segment-tail-sampler computes it that
	// way, but both are WRONG: banyand/trace/block.go fills MinTS and MaxTS from the
	// same per-row timestamp column, so they are the spread of span/segment START
	// times. That understates any trace whose last span outlives the last span to
	// begin, and is exactly 0 for a single-row trace — which would silently drop
	// every single-segment slow trace. Reading the two tags costs a decode; being
	// correct is worth it.
	//
	// DurationTag is the per-row duration column: "latency" (segment duration, ms)
	// for the segment schema, "duration" (span duration, µs) for Zipkin.
	DurationTag string
	// StartTimeTag is the per-row start timestamp column: "start_time" for the
	// segment schema, "timestamp_millis" for Zipkin. Both are stored as timestamp
	// tags (unix nanoseconds), so the plugin reads them as int64 ns.
	StartTimeTag string
	// DurationTagNanosPerUnit converts one DurationTag unit to nanoseconds so the
	// envelope math is ns-consistent with StartTimeTag: 1_000_000 for a millisecond
	// tag (segment latency), 1_000 for a microsecond tag (Zipkin duration).
	// FirstClassColumns is the schema's full column inventory — every tag OAP stores
	// as a real column rather than as an entry of ArrayTagColumn. It exists purely to
	// reject rules that could never match: "keep everything from the payment service",
	// written as {tagKey: service_id, equals: ...}, is admitted by a schema that does
	// not list its columns and then drops exactly those traces.
	//
	// List every column INCLUDING the duration, start-time and error tags named above
	// (the dedicated checks simply produce a better message for those), but NOT
	// ArrayTagColumn itself — a rule on that is the documented escape hatch for a
	// searchable tag whose key collides with a column name.
	FirstClassColumns       []string
	DurationTagNanosPerUnit int64
	// ErrorTagInArray says the error signal is a KEY INSIDE ArrayTagColumn rather
	// than a column of its own. The segment schema has a real is_error column
	// (false); Zipkin has none, but OAP flattens every span tag into "query" as both
	// a bare key and "key=value", so a span carrying Zipkin's conventional "error"
	// tag is detectable there (true).
	//
	// Note this is a tag CONVENTION, not an authoritative field: instrumentations
	// that signal failure only through http.status_code 5xx or otel.status_code are
	// not covered, and need an explicit keepTagRules entry.
	//
	// It is also subject to an OAP-side truncation. SpanForward.java skips BOTH the
	// bare key and "key=value" when either the value or the joined string exceeds
	// Tag.TAG_LENGTH (256 chars), so a Zipkin "error" tag carrying a long exception
	// message writes nothing into the array and keepErrors cannot see it — precisely
	// the loudest errors go missing. Catching those needs a keepTagRules entry on a
	// short-valued tag (an http.status_code regex, say) until OAP records the bare key
	// before the length check.
	ErrorTagInArray bool
}

Schema captures the per-plugin storage facts the shared engine needs: where a trace's searchable tags live, which columns carry the duration envelope, and how (or whether) "error" is expressed. The two first-party plugins differ only in the Schema they pass to New.

Only the columns named below are ever read as columns. Every keepTagRules entry resolves to ArrayTagColumn, so a rule can only match a searchable tag — never a first-class column such as local_endpoint_service_name. New rejects a tagKey naming one of the columns it does know to be first-class, rather than letting the rule silently never fire.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL