source

package
v1.131.2 Latest Latest
Warning

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

Go to latest
Published: May 26, 2026 License: MPL-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package source defines the Source abstraction for the v1.80 pipeline.

A Source represents one parser input (exim, dovecot, directadmin, etc.) and provides a stable identity, a descriptor (where its log file lives, who said so), and Open/Close lifecycle methods. The descriptor reuses the v1.79.2 distroconf truth surface — Source does NOT duplicate path discovery logic.

MIGRATION READINESS

To migrate a parser from the legacy detector layer to the pipeline:

  1. Construct a Source via NewFileSource(loader, key, name) — the source resolves its path through distroconf and records the resolution origin.
  2. Pass it to runtime.Pipeline.Register along with a watcher and parser.
  3. Leave the legacy parser in detector/ untouched until parity is proven.

Index

Constants

View Source
const DefaultFreshnessMax = 24 * time.Hour

DefaultFreshnessMax is the default StateActive→StateStale threshold.

Variables

View Source
var ErrNotImplemented = errors.New("source: not implemented")

ErrNotImplemented is returned by stub source methods that have not been wired up yet.

Functions

This section is empty.

Types

type Descriptor

type Descriptor struct {
	Name       string                // source identifier ("exim", "directadmin", ...)
	Service    string                // free-form service label
	DistroKey  string                // the distroconf [paths] key consulted
	Resolution distroconf.Resolution // raw resolution result from distroconf
	Path       string                // chosen path (may differ from Resolution.Path
	// when authority/fallback layers win)
	ResolvedBy string // "distroconf" | "authority" | "fallback" | ""
	State      State
	Reason     string    // human-readable explanation for State
	Mtime      time.Time // freshness check result; zero value if unknown
	Discovered time.Time // when the descriptor was built
}

Descriptor describes one Source after path resolution.

It wraps a distroconf.Resolution (the canonical truth-surface result) and adds runtime fields the pipeline needs: state, freshness, and whether the file exists at the resolved path.

Descriptor is the unit of truth that the CLI, validator, and doctor will consume in later phases. The pipeline emits one of these per registered source at startup, and one updated copy per rotation event.

type FileSource

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

FileSource is a Source backed by a regular file on disk, resolved through distroconf. It is the canonical Source implementation for v1.80 Phase A.

FileSource does NOT tail the file itself — that is the watcher's job. FileSource only owns the descriptor and resolves the path at construction time. If the operator wants to re-resolve (e.g. after a config reload), they construct a new FileSource.

func NewFileSource

func NewFileSource(opts FileSourceOptions) *FileSource

NewFileSource constructs a FileSource by running the layered resolution against distroconf, then the authoritative tool, then the fallback list.

The returned source's Descriptor reflects the resolution outcome. If no layer resolves a path, the descriptor's State is StateMissing and the caller should NOT register a watcher for it (the runtime will skip it).

func (*FileSource) Close

func (s *FileSource) Close() error

Close is a no-op for FileSource. Idempotent.

func (*FileSource) Descriptor

func (s *FileSource) Descriptor() Descriptor

Descriptor returns a snapshot of the current source descriptor.

func (*FileSource) Name

func (s *FileSource) Name() string

Name returns the source identifier.

func (*FileSource) Open

func (s *FileSource) Open() error

Open is a no-op for FileSource. The watcher opens the file.

func (*FileSource) Refresh

func (s *FileSource) Refresh(maxAge time.Duration)

Refresh re-stats the bound path and updates the freshness state.

This is called by the runtime on a periodic tick (e.g. every 60 seconds) so that StateActive can transition to StateStale (or back) as the file is written to or goes idle. Refresh does NOT re-run the layered resolver — once a source has bound a path, that path is stable until restart.

type FileSourceOptions

type FileSourceOptions struct {
	Name          string
	Service       string
	DistroKey     string
	Loader        *distroconf.Loader
	AuthorityFn   func() (string, error)
	AuthorityName string
	Fallback      []string
	FreshnessMax  time.Duration
}

FileSourceOptions configures NewFileSource.

Loader is REQUIRED. If nil, the resolver always returns LoaderUnavailable and the source falls through to the AuthorityFn / Fallback layers.

AuthorityFn is OPTIONAL. When set, it is called if distroconf does not resolve the key (Absent or LoaderUnavailable). It should return the authoritative path discovered via a service-specific tool (e.g. `exim -bP log_file_path`). Empty string + nil error means "tool not installed; not an error" — caller falls through to Fallback.

Fallback is OPTIONAL. When set, it is the ordered list of hard-coded candidate paths tried in order if both distroconf and AuthorityFn fail.

FreshnessMax controls when StateActive degrades to StateStale. Default is 24 hours.

type MemorySource

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

MemorySource is a Source implementation for unit tests. It holds a fixed Descriptor in memory and never touches the filesystem.

func NewMemorySource

func NewMemorySource(name string, state State) *MemorySource

NewMemorySource constructs a MemorySource with a synthetic descriptor. Used by tests to register sources without needing real distro confs or real files on disk.

func (*MemorySource) Close

func (s *MemorySource) Close() error

Close returns the configured close error (default nil).

func (*MemorySource) Descriptor

func (s *MemorySource) Descriptor() Descriptor

Descriptor returns the in-memory descriptor.

func (*MemorySource) Name

func (s *MemorySource) Name() string

Name returns the source identifier.

func (*MemorySource) Open

func (s *MemorySource) Open() error

Open returns the configured open error (default nil).

func (*MemorySource) SetState

func (s *MemorySource) SetState(st State)

SetState updates the source state. Test helper.

type Source

type Source interface {
	// Name returns the canonical identifier of this source.
	Name() string

	// Descriptor returns the current truth-surface descriptor for this
	// source. Callers MUST treat the returned value as immutable.
	Descriptor() Descriptor

	// Open prepares the source for use. For file sources this is typically
	// a no-op (the watcher opens the file). It exists so future sources
	// (e.g. journald, IPC) can do setup.
	Open() error

	// Close releases any resources held by the source. Idempotent.
	Close() error
}

Source is the abstraction the pipeline registers.

A Source has stable identity (Name) and produces a current Descriptor. Open/Close are lifecycle hooks for sources that need setup/teardown (most file-based sources do not, but the interface keeps the door open).

type State

type State int

State is the lifecycle state of a Source.

These mirror the v1.79.2 truth foundation plan Section C states. UNKNOWN is intentionally NOT a valid value: any code path that would emit it is a bug. UNKNOWN was eliminated from the validator in v1.79.1 and the pipeline must not reintroduce it.

const (
	// StateActive: descriptor resolved, file exists, watcher can attach.
	StateActive State = iota

	// StateStale: descriptor resolved, file exists, but mtime is older than
	// the freshness threshold. The parser may still tail it, but the doctor
	// surfaces an advisory.
	StateStale

	// StateMissing: descriptor required (service detected) but no candidate
	// path resolved through distroconf, authority probe, or fallback.
	StateMissing

	// StateDisabled: operator opt-out, OR distroconf returned NotApplicable
	// (n/a literal). Parser intentionally does not start.
	StateDisabled
)

func (State) String

func (s State) String() string

String satisfies fmt.Stringer.

Jump to

Keyboard shortcuts

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