internal/sampler/threshold/threshold.go

// Package threshold gates records by minimum severity. It acts as a
// pre-filter before the probabilistic samplers; anything below MinLevel
// never makes it to them.
//
// See mercemay.top/src/lambdalog/internal/sampler/threshold/.
package threshold

import (
	"mercemay.top/src/lambdalog/internal/encoder"
	"mercemay.top/src/lambdalog/internal/sampler"
)

// Sampler drops any record whose level is below MinLevel. Everything at or
// above MinLevel is emitted. The zero value allows everything through.
type Sampler struct {
	// MinLevel is matched case-insensitively via encoder.FormatLevel.
	MinLevel string
	// Escalate, if set, forces Emit for the listed levels even if MinLevel
	// would ordinarily let them be dropped by a downstream sampler.
	Escalate []string
}

// Name returns a stable identifier.
func (s *Sampler) Name() string { return "threshold" }

// Sample applies the threshold rule.
func (s *Sampler) Sample(in sampler.Input) sampler.Decision {
	inPrio := encoder.LevelPriority(in.Level)
	if s.MinLevel != "" {
		if inPrio < encoder.LevelPriority(s.MinLevel) {
			return sampler.Drop
		}
	}
	for _, e := range s.Escalate {
		if encoder.LevelPriority(e) == inPrio {
			return sampler.Emit
		}
	}
	return sampler.Emit
}

// New returns a Sampler initialised with min.
func New(min string) *Sampler {
	return &Sampler{MinLevel: min}
}

// WithEscalation adds levels that must always emit regardless of downstream
// sampler decisions. Returns s for chaining.
func (s *Sampler) WithEscalation(levels ...string) *Sampler {
	s.Escalate = append(s.Escalate, levels...)
	return s
}

// Reject reports whether in would be dropped by Sample. It is useful for
// building unit tests around the threshold without going through the
// Decision enum.
func (s *Sampler) Reject(in sampler.Input) bool {
	return s.Sample(in) == sampler.Drop
}

// MustEmit reports whether in matches an Escalate entry, meaning downstream
// samplers should not be consulted.
func (s *Sampler) MustEmit(in sampler.Input) bool {
	inPrio := encoder.LevelPriority(in.Level)
	for _, e := range s.Escalate {
		if encoder.LevelPriority(e) == inPrio {
			return true
		}
	}
	return false
}