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 ¶
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) Decide ¶
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 ¶
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.
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.