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:
- Construct a Source via NewFileSource(loader, key, name) — the source resolves its path through distroconf and records the resolution origin.
- Pass it to runtime.Pipeline.Register along with a watcher and parser.
- Leave the legacy parser in detector/ untouched until parity is proven.
Index ¶
Constants ¶
const DefaultFreshnessMax = 24 * time.Hour
DefaultFreshnessMax is the default StateActive→StateStale threshold.
Variables ¶
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) 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 )