config

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Jun 6, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package config loads api-log's runtime configuration from YAML and environment overrides. Layout follows ARCHITECTURE.md § 11.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIConfig

type APIConfig struct {
	Listen string `yaml:"listen"`

	// ExportByteHardCap is the byte ceiling on /api/export before
	// `?bytes_all=1` is required to bypass. Measured in source JSONL
	// bytes (sum of file sizes for matched groups, one os.Stat per
	// group). 0 = unlimited; default 2 GiB.
	//
	// Independent of the row cap. See internal/api/export.go's
	// defaultExportByteHardCap docstring for the rationale; this YAML
	// field overrides that default. Env var:
	// APILOG_API_EXPORT_BYTE_HARDCAP.
	ExportByteHardCap int64 `yaml:"export_byte_hardcap"`
}

type Config

type Config struct {
	Proxy       ProxyConfig       `yaml:"proxy"`
	API         APIConfig         `yaml:"api"`
	Storage     StorageConfig     `yaml:"storage"`
	Timeouts    TimeoutsConfig    `yaml:"timeouts"`
	Shutdown    ShutdownConfig    `yaml:"shutdown"`
	Logging     LoggingConfig     `yaml:"logging"`
	Diagnostics DiagnosticsConfig `yaml:"diagnostics"`
	Plugins     PluginsConfig     `yaml:"plugins"`
	Media       MediaConfig       `yaml:"media"`
	Viewer      ViewerConfig      `yaml:"viewer"`
}

Config is the parsed runtime config.

All durations are stored as time.Duration. YAML uses *_seconds keys so the config file stays readable; we convert on load.

func Defaults

func Defaults() Config

Defaults returns a Config with the documented v0 defaults from ARCHITECTURE.md § 11.

func Load

func Load(path string) (Config, error)

Load reads the YAML file at path (empty path = defaults only), then applies APILOG_* environment overrides on top.

func (Config) Validate

func (c Config) Validate() error

Validate checks that the loaded configuration is internally consistent. Returns a wrapped error naming the offending field.

type DiagnosticsConfig

type DiagnosticsConfig struct {
	// Cadence for the counter-snapshot INFO line. 0 disables.
	// Default 60s; tight enough for prod incident timelines, loose
	// enough not to spam logs.
	SnapshotIntervalSeconds int `yaml:"snapshot_interval_seconds"`
}

Diagnostics knobs — periodic background work that doesn't touch the trace path; safe to leave at defaults.

func (DiagnosticsConfig) SnapshotInterval

func (c DiagnosticsConfig) SnapshotInterval() time.Duration

type LoggingConfig

type LoggingConfig struct {
	Level string `yaml:"level"`
}

type MediaConfig

type MediaConfig struct {
	SaveAttachments bool `yaml:"save_attachments"`
}

MediaConfig governs per-trace media extraction (see phase-k-media-contract.md).

SaveAttachments=true makes the writer-side extractor walk request/response bodies for named base64 fields (image_url.url, source.data, inlineData, b64_json) and persist each as a derived file under <data_dir>/<YYYY-MM-DD>/<keyhash>/media/<trace_id>/<idx>.<ext>. The JSONL remains the source of truth (Backend §6); these files are a fast-read cache + export-bundling target.

Default is true. The runtime-overrides layer can flip this without a restart via PUT /api/config/media, and that override takes precedence over both yaml and env.

type PluginsConfig

type PluginsConfig struct {
	PathFilter    pathfilter.Config    `yaml:"path_filter"`
	CaptureFilter capturefilter.Config `yaml:"capture_filter"`
}

PluginsConfig holds observe-class plugin config. The zero value disables every observe-class plugin, so an empty plugins block preserves default recording behavior.

path_filter (existing): observer-class drop at finalize. Trace IS captured to the data dir; only the SQLite mirror is suppressed. Operators who configured this pre-v0.1.2 keep their semantics.

capture_filter (v0.1.2+): pre-write drop. Matches BEFORE the proxy handler starts a trace; no JSONL line + no SQLite row + no media extraction + no body tee. Use for high-volume polling endpoints that shouldn't consume disk at all. Opt-in; identical pattern syntax so operators can copy a string between the two blocks.

type ProxyConfig

type ProxyConfig struct {
	Listen   string `yaml:"listen"`
	Upstream string `yaml:"upstream"`
}

type ShutdownConfig

type ShutdownConfig struct {
	GraceSeconds int `yaml:"grace_seconds"`
}

func (ShutdownConfig) Grace

func (c ShutdownConfig) Grace() time.Duration

type StorageConfig

type StorageConfig struct {
	DataDir         string `yaml:"data_dir"`
	MaxBodyBytes    int64  `yaml:"max_body_bytes"`
	CaptureChanSize int    `yaml:"capture_chan_size"`
	WriterChanSize  int    `yaml:"writer_chan_size"`
}

type TimeoutsConfig

type TimeoutsConfig struct {
	ReadHeaderSeconds     int `yaml:"read_header_seconds"`
	IdleSeconds           int `yaml:"idle_seconds"`
	StreamIdleSeconds     int `yaml:"stream_idle_seconds"`
	ReqBodyCaptureSeconds int `yaml:"req_body_capture_seconds"`

	// End-to-end traces this slow trigger a WARN log + slow_traces++.
	// 0 disables (no WARN). Default 30s.
	SlowTraceSeconds int `yaml:"slow_trace_seconds"`
}

func (TimeoutsConfig) Idle

func (c TimeoutsConfig) Idle() time.Duration

func (TimeoutsConfig) ReadHeader

func (c TimeoutsConfig) ReadHeader() time.Duration

func (TimeoutsConfig) ReqBodyCapture

func (c TimeoutsConfig) ReqBodyCapture() time.Duration

func (TimeoutsConfig) SlowTrace

func (c TimeoutsConfig) SlowTrace() time.Duration

func (TimeoutsConfig) StreamIdle

func (c TimeoutsConfig) StreamIdle() time.Duration

type ViewerConfig

type ViewerConfig struct {
	Enabled    bool   `yaml:"enabled"`
	Repo       string `yaml:"repo"`
	Version    string `yaml:"version"`
	Sha256     string `yaml:"sha256"`
	LocalPath  string `yaml:"local_path"`
	CacheDir   string `yaml:"cache_dir"`
	PublicPath string `yaml:"public_path"`

	// ReleasesAPIBase overrides the dist.zip fetch endpoint. Empty
	// means "use https://api.github.com" (the default). Internal
	// artifact stores (Gitea, Forgejo) speak the same release-API
	// shape and slot in via this field — e.g. setting it to
	// "http://gitea.homelab.lan/api/v1" with a matching `Repo` =
	// "<gitea-owner>/<repo>" reroutes the fetch.
	ReleasesAPIBase string `yaml:"releases_api_base"`

	// ReleasesAuthToken is sent on the metadata + asset requests as
	// `Authorization: token <value>`. Required for private Gitea
	// repos. Sensitive — source from env (APILOG_VIEWER_RELEASES_AUTH_TOKEN)
	// or a secrets file rather than committing to repo-tracked YAML.
	ReleasesAuthToken string `yaml:"releases_auth_token"`
}

ViewerConfig governs the optional hosted-viewer feature (`/viewer/*`). The backend fetches the viewer's release `dist.zip` once at startup, sha-verifies it against a backend-pinned constant (cmd/api-log/viewer_pins.go), extracts to a local cache, and serves it. Defaults are ON, pinned to the backend's source-baked version + SHA.

Empty Repo / Version / Sha256 fields are filled in from the backend-pinned constants in main.go. An empty CacheDir is resolved to `<DataDir>/viewer-cache`. An empty PublicPath defaults to `/viewer`. LocalPath overrides the fetch entirely (offline mode).

Operator-override safety: if the operator overrides Repo or Version without supplying a matching Sha256 (and not using LocalPath), the viewerhost rejects the override — the binary stays up, but `/viewer/` returns 503 with a logged error. We never serve an unverified asset.

Jump to

Keyboard shortcuts

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