Documentation
¶
Overview ¶
Package engine holds the rules and decision logic that adapters consult on every wrapped operation. It depends only on the standard library and the chaotic fault package.
Index ¶
- Constants
- func Now(ctx context.Context) time.Time
- func Since(ctx context.Context, t time.Time) time.Duration
- func Until(ctx context.Context, t time.Time) time.Duration
- type Action
- type CounterKind
- type CounterSpec
- type Engine
- func (e *Engine) AddRule(r Rule) *Engine
- func (e *Engine) AllHits() map[string]int
- func (e *Engine) Disable()
- func (e *Engine) Enable()
- func (e *Engine) Enabled() bool
- func (e *Engine) Eval(ctx context.Context, op Op) Action
- func (e *Engine) Hits(name string) int
- func (e *Engine) ReplaceRules(rs RuleSet)
- func (e *Engine) Reset()
- type FaultEvent
- type FaultSpec
- type Finding
- type KillSwitch
- type Kind
- type Observer
- type Op
- type Option
- func WithFailureBudget(maxErrorRate float64, window int) Option
- func WithKillSwitch(ks KillSwitch) Option
- func WithMaxConcurrent(n int) Option
- func WithObserver(obs Observer) Option
- func WithProductionGuard(check func() bool) Option
- func WithRateLimit(rps int) Option
- func WithRuleSource(rs RuleSet) Option
- type OutcomeReporter
- type Report
- type RichObserver
- type Rule
- type RuleInfo
- type RuleOption
- func Always() RuleOption
- func MatchAttr(key, value string) RuleOption
- func MatchKind(kinds ...Kind) RuleOption
- func MatchName(pattern string) RuleOption
- func MatchNameRegex(re *regexp.Regexp) RuleOption
- func MatchPredicate(fn func(context.Context, Op) bool) RuleOption
- func MatchTimeWindow(startH, startM, endH, endM int) RuleOption
- func Probability(p float64, seed int64) RuleOption
- func Range(from, to int) RuleOption
- func Sequence(fire []bool) RuleOption
- func StickyAttr(key string, window time.Duration, cap int) RuleOption
- func Times(n int) RuleOption
- func WithFault(f fault.Fault) RuleOption
- func WithFaults(fs ...fault.Fault) RuleOption
- func WithPerRuleRateLimit(rps int) RuleOption
- func WithStages(stages ...Stage) RuleOption
- type RuleSet
- type RuleSpec
- type Severity
- type Stage
- type StageSpec
Examples ¶
Constants ¶
const ( ReasonCounter = "counter" ReasonRateLimit = "rate_limit" ReasonMaxConcurrent = "max_concurrent" ReasonFailureBudget = "failure_budget" // ReasonDisabled and ReasonKillSwitch are reserved for observers that build // their own suppression accounting; the engine's disabled and kill-switch // paths return Pass without calling RuleSkipped, so they are not emitted. ReasonDisabled = "disabled" ReasonKillSwitch = "killswitch" )
Skip reasons passed to Observer.RuleSkipped. Observers may switch on these instead of matching free-form strings.
Variables ¶
This section is empty.
Functions ¶
func Now ¶
Now returns the current wall-clock time skewed by any fault.Clock active on ctx: time.Now().Add(fault.Skew(ctx)). With no skew (no clock cell bound, no Clock fault fired, or a chaos_off build) it is effectively time.Now(). Use Now instead of time.Now() in code whose clock-dependent behavior you want chaos to exercise (deadline math, expiry/token windows, timezone logic).
The skew shifts both the wall and monotonic readings of the returned time, so elapsed-time subtraction between two Now reads is unaffected (a wrong clock must not warp how much time elapsed), while wall-clock field reads (Hour, Year, In) and comparisons against fixed external timestamps reflect the skew. Subtracting a skewed Now from a separately captured time.Now() cancels the skew via the shared monotonic reading.
Types ¶
type Action ¶
Action is what Eval returns; adapters execute it around the wrapped call. Before runs prior to the call. After runs after call.
var Pass Action = passAction{}
Pass is the canonical no-op action.
type CounterKind ¶
type CounterKind int
CounterKind classifies a rule's counter for introspection.
const ( CounterAlways CounterKind = iota CounterTimes CounterRange CounterProbability CounterSequence CounterStaged )
Counter kinds, one per rule counter strategy.
type CounterSpec ¶
type CounterSpec struct {
Type string `yaml:"type" json:"type"`
N int `yaml:"n" json:"n"`
From int `yaml:"from" json:"from"`
To int `yaml:"to" json:"to"`
P float64 `yaml:"p" json:"p"`
Seed int64 `yaml:"seed" json:"seed"`
}
CounterSpec selects a counter. Type is "always", "times", "range", or "probability" (empty defaults to "always").
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine holds the rules and decision logic. Engines are not safe to copy - always pass as *Engine. AddRule is safe for concurrent use, Eval is too.
func (*Engine) AddRule ¶
AddRule appends a rule. Returns the engine for chaining. Append is implemented as a copy-on-write swap of the rule slice so concurrent Evals never see a torn slice.
func (*Engine) AllHits ¶
AllHits returns a snapshot of hit counts for every named rule registered with the engine, including rules that have not yet fired (value 0).
func (*Engine) Disable ¶
func (e *Engine) Disable()
Disable flips an atomic flag so Enabled reports false and adapters take the passthrough path. Faster than Reset for "kill the chaos now". Reversible.
func (*Engine) Enabled ¶
Enabled reports whether the engine has any rules. Adapters call this before constructing an Op so the no-op path stays alloc-free. Nil-safe: a nil engine reports false.
func (*Engine) Eval ¶
Eval evaluates the op against all configured rules and returns the matching Action, or Pass if no rule matches or the engine is disabled.
func (*Engine) Hits ¶
Hits returns the number of times a named rule has fired. Unknown names return 0. Safe for concurrent use.
func (*Engine) ReplaceRules ¶
ReplaceRules atomically swaps the active rule set. Used by rule sources on reload. Concurrent Evals see either the old or the new set, never a torn one. Hit counters are rebuilt for the new set's named rules.
type FaultEvent ¶
type FaultEvent struct {
Rule string
Op Op
FaultKind fault.Kind
// Latency is the fault's configured sleep: the exact duration for a Latency
// fault, or the max bound for a Jittered fault (whose per-call draw is not
// observable). Zero for faults that inject no sleep.
Latency time.Duration
}
FaultEvent describes a single injected fault delivered to RichObserver. It is emitted only for faults whose Apply returns without error (latency, jittered, and any custom no-op fault); faults that short-circuit the call (error, panic, connection drop) never produce a FaultEvent.
type FaultSpec ¶
type FaultSpec struct {
Type string `yaml:"type" json:"type"`
Duration string `yaml:"duration" json:"duration"` // latency
Min string `yaml:"min" json:"min"` // jittered
Max string `yaml:"max" json:"max"` // jittered
Message string `yaml:"message" json:"message"` // error -> errors.New(Message)
Value string `yaml:"value" json:"value"` // panic -> Panic(value)
Rate int `yaml:"rate" json:"rate"` // slow_reader / slow_writer (bytes/sec)
Limit int `yaml:"limit" json:"limit"` // truncate (bytes)
}
FaultSpec selects a fault. Type is "latency", "jittered", "error", "panic", or "conn_drop".
type Finding ¶
Finding is one blast-radius hazard the linter detected. Rule is the offending rule's name (or "<unnamed>" when it has none).
type KillSwitch ¶
KillSwitch lets a caller short-circuit chaos. If it returns true for the current Op, Eval returns Pass without consulting any rule. The default engine has no kill switch (every call is evaluated).
type Kind ¶
type Kind int
Kind identifies which adapter produced an Op. Do not renumber existing values.
const ( OpHTTPClient Kind = iota + 1 OpHTTPServer OpSQL OpGRPCClient OpGRPCServer OpExplicit // chaos.Point call sites OpPGX // pgx adapter OpRedis // go-redis adapter OpRabbitMQ // rabbitmq/amqp091-go adapter OpMongo // mongo-driver v2 adapter OpKafka // segmentio/kafka-go adapter OpAWS // aws-sdk-go-v2 adapter OpNATS // nats.go adapter OpNet // raw net.Conn adapter OpIO // io.Reader / io.Writer adapter )
Op kind constants identify which adapter produced an Op.
type Observer ¶
type Observer interface {
RuleFired(ruleName string, op Op, action Action)
RuleSkipped(ruleName string, op Op, reason string)
}
Observer receives events from the engine each time it evaluates a named rule. v1 ships no concrete implementations. Users supply their own via WithObserver. The always-on per-named-rule hit counter (Engine.Hits) does not require an observer.
Observer methods are called synchronously on the request path. Keep them cheap, do not block.
type Op ¶
Op describes a single intercepted call. Adapters construct an Op only after Engine.Enabled() returns true, so the no-op path allocates nothing.
type Option ¶
type Option func(*Engine)
Option configures an Engine at construction time.
func WithFailureBudget ¶
WithFailureBudget stops injecting faults once the observed error rate over a sliding window of the last window calls reaches maxErrorRate. Requires the adapters to report outcomes (they do, via OutcomeReporter). Panics if maxErrorRate is outside [0, 1] or window < 1.
func WithKillSwitch ¶
func WithKillSwitch(ks KillSwitch) Option
WithKillSwitch attaches a kill switch. Pass nil to clear.
func WithMaxConcurrent ¶
WithMaxConcurrent caps the number of simultaneously in-flight faulted calls to n. Matched calls that would exceed the cap return Pass. The slot is held for the duration of the fault (including latency sleeps) and released when the adapter calls After (or when Before short-circuits).
func WithObserver ¶
WithObserver attaches an Observer to the engine. Pass nil to clear. If obs also implements RichObserver, the engine additionally delivers per-fault FaultEvents to it; the assertion happens once here, not per call.
func WithProductionGuard ¶
WithProductionGuard makes New panic if check returns true. Supply a check that detects an environment chaos must not run in (e.g. reads an env var).
func WithRateLimit ¶
WithRateLimit caps the number of faults that actually fire to rps per second (global across all rules). Matched calls beyond the limit return Pass.
func WithRuleSource ¶
WithRuleSource backs the engine with rs at construction (instead of AddRule).
type OutcomeReporter ¶
OutcomeReporter is an optional interface an Action may implement to receive the result of the wrapped call. Adapters call Outcome (when implemented) after the wrapped boundary returns. callErr is the wrapped call's error (nil or success). It is not invoked when Before short-circuits the call.
type Report ¶
type Report struct {
Findings []Finding
}
Report is the result of a lint pass.
func Lint ¶
Lint inspects programmatic rules via RuleInfo. It is coarse: closures hide globs and probability values, so it flags only structural hazards visible through introspection — chiefly a rule that matches every operation on every call (no matchers, Always counter), which is far riskier when its faults are terminal (panic or connection drop).
func LintSpecs ¶
LintSpecs inspects declarative specs and can see globs, probabilities, and durations the programmatic Lint cannot. It is the richer analog: it flags a wildcard name glob, a probability that always fires, latency above lintLatencyCeiling, a terminal fault on a globally-scoped spec, and two specs that target the same kind+glob (an overlap whose combined effect is easy to underestimate).
type RichObserver ¶
type RichObserver interface {
Observer
FaultInjected(ctx context.Context, ev FaultEvent)
}
RichObserver is an optional richer sink. An Observer may also implement it to receive per-fault detail the base Observer cannot carry. The engine checks for it once, when WithObserver runs, not per call. FaultInjected fires from the adapter's request path, synchronously, after a fault's sleep completes - keep it cheap and non-blocking, like the base Observer methods.
type Rule ¶
type Rule struct {
// contains filtered or unexported fields
}
Rule is a single match-counter-faults triple. Construct with NewRule and pass to Engine.AddRule. Rule values may be copied (e.g., by Named), but they share state via internal pointers - never modify a Rule's selectors or faults after passing it to AddRule.
func BuildRule ¶
BuildRule converts a RuleSpec into a Rule, validating kinds, counter type, fault types, durations, and probability bounds. It is total: it never panics, and it aggregates every invalid field into a single errors.Join result so a caller (and the operator editing config) sees all problems at once.
Example ¶
package main
import (
"context"
"fmt"
"github.com/RomanAgaltsev/chaotic/engine"
)
// fire evaluates op against eng and returns the injected fault error (or nil),
// mimicking what an adapter does around a wrapped call.
func fire(eng *engine.Engine, op engine.Op) error {
ctx := context.Background()
act := eng.Eval(ctx, op)
err := act.Before(ctx)
_ = act.After(ctx)
return err
}
func main() {
// BuildRule turns a declarative RuleSpec (e.g. decoded from YAML) into a
// Rule. It is total: invalid specs return an error instead of panicking.
rule, err := engine.BuildRule(engine.RuleSpec{
Name: "from-config",
Kinds: []string{"http_client"},
Counter: engine.CounterSpec{Type: "times", N: 1},
Faults: []engine.FaultSpec{{Type: "error", Message: "boom"}},
})
if err != nil {
fmt.Println("build error:", err)
return
}
eng := engine.New().AddRule(rule)
fmt.Println("fired:", fire(eng, engine.Op{Kind: engine.OpHTTPClient}) != nil)
}
Output: fired: true
func NewRule ¶
func NewRule(opts ...RuleOption) Rule
NewRule constructs a Rule. The default counter is Always, default action is no faults (Pass).
Example ¶
package main
import (
"context"
"errors"
"fmt"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
// fire evaluates op against eng and returns the injected fault error (or nil),
// mimicking what an adapter does around a wrapped call.
func fire(eng *engine.Engine, op engine.Op) error {
ctx := context.Background()
act := eng.Eval(ctx, op)
err := act.Before(ctx)
_ = act.After(ctx)
return err
}
func main() {
eng := engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpHTTPClient),
engine.Times(1), // fire on the first match only
engine.WithFault(fault.Error(errors.New("transient"))),
).Named("flap"))
op := engine.Op{
Kind: engine.OpHTTPClient,
Name: "/users",
}
fmt.Println("call 1:", fire(eng, op))
fmt.Println("call 2:", fire(eng, op))
fmt.Println("hits:", eng.Hits("flap"))
}
Output: call 1: transient call 2: <nil> hits: 1
type RuleInfo ¶
type RuleInfo struct {
Name string
Unconstrained bool
Counter CounterKind
Faults []fault.Kind
}
RuleInfo is a read-only view of a Rule for linting and tooling. It exposes only what closures permit: whether the rule is unconstrained (no matchers, so it matches every Op), its counter kind, and the kinds of its faults.
type RuleOption ¶
type RuleOption func(*Rule)
RuleOption configures a Rule during construction.
func MatchAttr ¶
func MatchAttr(key, value string) RuleOption
MatchAttr matches Ops whose Attrs[key] equals value.
Example ¶
package main
import (
"context"
"errors"
"fmt"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
// fire evaluates op against eng and returns the injected fault error (or nil),
// mimicking what an adapter does around a wrapped call.
func fire(eng *engine.Engine, op engine.Op) error {
ctx := context.Background()
act := eng.Eval(ctx, op)
err := act.Before(ctx)
_ = act.After(ctx)
return err
}
func main() {
eng := engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpHTTPClient),
engine.MatchAttr("host", "payments.internal"),
engine.WithFault(fault.Error(errors.New("degraded"))),
).Named("payments"))
payments := engine.Op{
Kind: engine.OpHTTPClient,
Attrs: map[string]string{"host": "payments.internal"},
}
search := engine.Op{
Kind: engine.OpHTTPClient,
Attrs: map[string]string{"host": "search.internal"},
}
fmt.Println("payments:", fire(eng, payments))
fmt.Println("search:", fire(eng, search))
}
Output: payments: degraded search: <nil>
func MatchKind ¶
func MatchKind(kinds ...Kind) RuleOption
MatchKind matches Ops whose Kind appears in kinds. With zero arguments, matches nothing.
func MatchName ¶
func MatchName(pattern string) RuleOption
MatchName matches Ops whose Name satisfies path.Match(pattern, Name). Patterns support *, ?, and [...]. * does not cross /.
func MatchNameRegex ¶
func MatchNameRegex(re *regexp.Regexp) RuleOption
MatchNameRegex matches Ops whose Name matches re. Use it when MatchName's path.Match globbing is too constrained — notably, path.Match's * does not cross "/", whereas a regexp can. re must be pre-compiled (regexp.MustCompile or a checked regexp.Compile) so an invalid pattern surfaces at construction, not at fire-time. A nil re matches nothing.
Example ¶
package main
import (
"errors"
"fmt"
"regexp"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
func main() {
// path.Match's * does not cross "/"; a regexp can.
re := regexp.MustCompile(`^/api/v[0-9]+/users/.*$`)
eng := engine.New().AddRule(engine.NewRule(
engine.MatchNameRegex(re),
engine.WithFault(fault.Error(errors.New("boom"))),
).Named("users-api"))
fmt.Println(eng.Enabled())
}
Output: true
func MatchPredicate ¶
func MatchPredicate(fn func(context.Context, Op) bool) RuleOption
MatchPredicate matches Ops for which fn returns true.
func MatchTimeWindow ¶
func MatchTimeWindow(startH, startM, endH, endM int) RuleOption
MatchTimeWindow matches Ops only when the local wall clock falls within the daily window [startH:startM, endH:endM). Hours are 0–23, minutes 0–59, in the process's local time zone. Useful for scheduled chaos, e.g. "only inject between 02:00 and 04:00 during the canary window". A window where start == end matches nothing; a window spanning midnight (start > end) is supported.
Example ¶
package main
import (
"fmt"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
func main() {
// Only inject between 02:00 and 04:00 local time.
eng := engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpHTTPClient),
engine.MatchTimeWindow(2, 0, 4, 0),
engine.WithFault(fault.Latency(0)),
).Named("nightly"))
fmt.Println(eng.Enabled())
}
Output: true
func Probability ¶
func Probability(p float64, seed int64) RuleOption
Probability makes the rule fire on each match independently with probability p. Seed makes the decision deterministic across runs. Panics if p is outside [0,1].
Example ¶
package main
import (
"context"
"errors"
"fmt"
"strings"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
// fire evaluates op against eng and returns the injected fault error (or nil),
// mimicking what an adapter does around a wrapped call.
func fire(eng *engine.Engine, op engine.Op) error {
ctx := context.Background()
act := eng.Eval(ctx, op)
err := act.Before(ctx)
_ = act.After(ctx)
return err
}
func main() {
// A seeded probability rule fires identically every run, so chaos tests are
// reproducible. Two engines built with the same seed produce same
// fire/skip sequence.
build := func() *engine.Engine {
return engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpHTTPClient),
engine.Probability(0.5, 1),
engine.WithFault(fault.Error(errors.New("x"))),
).Named("p"))
}
seq := func(eng *engine.Engine) string {
var b strings.Builder
for range 10 {
if fire(eng, engine.Op{Kind: engine.OpHTTPClient}) != nil {
b.WriteByte('F')
} else {
b.WriteByte('.')
}
}
return b.String()
}
first, second := seq(build()), seq(build())
fmt.Println("reproducible:", first == second)
}
Output: reproducible: true
func Range ¶
func Range(from, to int) RuleOption
Range makes the rule fire on matches[from:to] (1-indexed, inclusive). If from > to or either is < 1, the rule never fires.
func Sequence ¶
func Sequence(fire []bool) RuleOption
Sequence fires on the evaluations whose index is true in fire, in order, and skips the rest. After the slice is exhausted it never fires again. it is the deterministic counter chaostest/golden uses to replay a recorded fire pattern, and is useful generally for "fire on exactly these matches".
func StickyAttr ¶
func StickyAttr(key string, window time.Duration, cap int) RuleOption
StickyAttr makes a rule "sticky" by an Op attribute: once the rule fires for a given Attrs[key] value, every later matching Op carrying that same value keeps firing for window, bypassing the counter. This models a resource that is stuck in a degraded state (e.g. one user wedged after a fault). cap bounds memory: at most cap distinct values are tracked, evicted FIFO. A key absent from an Op's Attrs is never sticky.
Example ¶
package main
import (
"errors"
"fmt"
"time"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
func main() {
// Once a user trips the fault, keep them degraded for a minute.
eng := engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpHTTPClient),
engine.Probability(0.1, 1),
engine.StickyAttr("user", time.Minute, 1024),
engine.WithFault(fault.Error(errors.New("degraded"))),
).Named("sticky-user"))
fmt.Println(eng.Enabled())
}
Output: true
func Times ¶
func Times(n int) RuleOption
Times makes the rule fire on the first n matches. After n, the rule never fires again until Engine.Reset clears the counter.
func WithFault ¶
func WithFault(f fault.Fault) RuleOption
WithFault attaches a single fault. Equivalent to WithFaults(f).
func WithFaults ¶
func WithFaults(fs ...fault.Fault) RuleOption
WithFaults attaches faults that execute in order inside Action.Before. The first fault returning a non-nil error short-circuits the chain.
func WithPerRuleRateLimit ¶
func WithPerRuleRateLimit(rps int) RuleOption
WithPerRuleRateLimit caps how often THIS rule's faults actually fire to rps per second (burst rps), independent of other rules and of the engine-wide WithRateLimit. When the rule is throttled it is skipped and evaluation continues to the next rule, so a lower-priority rule can still match. Panics if rps < 1 (matches WithRateLimit). The cap reuses the engine's token bucket.
Example ¶
package main
import (
"fmt"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
func main() {
// Fail Redis calls, but never more than 10 injected faults per second.
eng := engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpRedis),
engine.WithPerRuleRateLimit(10),
engine.WithFault(fault.ConnDrop()),
).Named("redis-flaky"))
fmt.Println(eng.Enabled())
}
Output: true
func WithStages ¶
func WithStages(stages ...Stage) RuleOption
WithStages makes a rule inject different faults as its cumulative match count grows: stage 1 covers the first Stage.Times matches, stage 2 the next, and so on. A final stage with Times == 0 fires forever; otherwise the rule goes quiet once the last stage is exhausted (it falls through, like a spent Times).
WithStages sets the rule's fire strategy: it is mutually exclusive with Times/Range/Probability/Sequence (last option wins) and takes precedence over StickyAttr. Panics if stages is empty, or if any non-final stage has Times <= 0 — the same fail-fast contract as Probability.
Example ¶
package main
import (
"context"
"errors"
"fmt"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
// fire evaluates op against eng and returns the injected fault error (or nil),
// mimicking what an adapter does around a wrapped call.
func fire(eng *engine.Engine, op engine.Op) error {
ctx := context.Background()
act := eng.Eval(ctx, op)
err := act.Before(ctx)
_ = act.After(ctx)
return err
}
func main() {
eng := engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpHTTPClient),
engine.WithStages(
engine.Stage{Times: 2, Faults: []fault.Fault{fault.Error(errors.New("transient"))}},
engine.Stage{Times: 0, Faults: []fault.Fault{fault.Error(errors.New("permanent"))}},
),
).Named("degrade"))
op := engine.Op{Kind: engine.OpHTTPClient, Name: "/users"}
for i := 1; i <= 4; i++ {
fmt.Printf("call %d: %v\n", i, fire(eng, op))
}
}
Output: call 1: transient call 2: transient call 3: permanent call 4: permanent
type RuleSet ¶
RuleSet is the engine's view of its current rules. The engine never holds a snapshot across Eval calls - it loads a fresh one each time.
func NewRuleSet ¶
NewRuleSet returns an in-memory RuleSet backed by the given rules. Sources (file/http) build their rules then call ReplaceRules(NewRuleSet(rules)).
type RuleSpec ¶
type RuleSpec struct {
Name string `yaml:"name" json:"name"`
Kinds []string `yaml:"kinds" json:"kinds"`
NameGlob string `yaml:"name_glob" json:"name_glob"`
Attrs map[string]string `yaml:"attrs" json:"attrs"`
Counter CounterSpec `yaml:"counter" json:"counter"`
Faults []FaultSpec `yaml:"faults" json:"faults"`
Stages []StageSpec `yaml:"stages" json:"stages"`
}
RuleSpec is the declarative, serializable form of a Rule. Rule sources parse config (YAML/JSON) into RuleSpec and call BuildRule. The struct tags are the on-disk/on-wire field names. MatchPredicate and typed error values cannot be serialized. Config rules support this declarative subset only.
type Severity ¶
type Severity int
Severity ranks a lint Finding. Only SeverityHigh findings fail Report.OK.
Severity levels in ascending order of seriousness.