Documentation
¶
Overview ¶
Package daemon runs the reporter's upload pass on a fixed interval until it is told to stop.
Each cycle runs reporter.RunOnce and then sends a heartbeat, so the dashboard sees the machine online even when there is nothing new. With Reporter.ScanEnded set, each pass also reads the transcripts that changed since the previous pass, so sessions that start and end between passes are not missed. The scan window is held in memory: the first pass looks back Reporter.ScanLookback, and each later pass starts twice the interval before the previous complete pass began. A failed cycle backs off exponentially. Only one daemon runs per home directory, enforced by a lock on ~/.firekeeper/daemon.lock, and it logs to ~/.firekeeper/daemon.log. Logs carry counts and sanitized errors, never transcript text.
Index ¶
- Constants
- Variables
- func DetectProviders(home string, getenv func(string) string, lookPath func(string) (string, error)) []transcript.Provider
- func Follow(ctx context.Context, path string, offset int64, interval time.Duration, ...) error
- func Run(ctx context.Context, cfg Config) error
- func Supported(goos string) bool
- func Tail(path string, n int, w io.Writer) (int64, error)
- type Clock
- type CommandError
- type Config
- type ExecRunner
- type Reporting
- type Runner
- type Service
- func (s *Service) Commands() [][]string
- func (s *Service) DataDir() string
- func (s *Service) File() ([]byte, error)
- func (s *Service) Inspect(ctx context.Context, configServer string, ...) Reporting
- func (s *Service) Install(ctx context.Context) error
- func (s *Service) InstalledArgs() ([]string, error)
- func (s *Service) LogPath() string
- func (s *Service) Path() string
- func (s *Service) StartupLogPath() string
- func (s *Service) Status(ctx context.Context) (Status, error)
- func (s *Service) Uninstall(ctx context.Context, purge bool) error
- type Status
Constants ¶
const ( // DefaultInterval is the time between passes when Config.Interval is // zero. DefaultInterval = 15 * time.Second // MinInterval is the shortest interval Run accepts. MinInterval = 5 * time.Second )
const ( // LaunchdLabel names the macOS LaunchAgent. LaunchdLabel = "dev.firekeeper.daemon" // SystemdUnit names the systemd user unit. SystemdUnit = "firekeeper.service" )
Variables ¶
var ErrLocked = errors.New("another firekeeper daemon is already running")
ErrLocked means another daemon holds the lock for the same home.
var ErrNoProviders = errors.New("no provider enabled; the daemon uploads nothing without one")
ErrNoProviders means the reporter config would upload nothing.
var ErrNotInstalled = errors.New("the firekeeper daemon service is not installed")
ErrNotInstalled means no service definition exists and none is loaded.
Functions ¶
func DetectProviders ¶
func DetectProviders(home string, getenv func(string) string, lookPath func(string) (string, error)) []transcript.Provider
DetectProviders finds supported transcript providers without reading their data or launching their CLIs. An existing provider home or executable on PATH is sufficient; providers without transcript readers are deliberately omitted.
func Follow ¶
func Follow(ctx context.Context, path string, offset int64, interval time.Duration, w io.Writer) error
Follow writes what is appended to the log at path after offset until ctx is cancelled, polling every interval. When the daemon rotates the log it finishes the old file and continues at the start of the new one.
func Run ¶
Run reports every Interval until ctx is cancelled. Cancelling ctx is a graceful stop: the batch in flight finishes and its offset is saved, no new batch starts, and Run returns nil. Run returns an error only when it cannot start.
Types ¶
type Clock ¶
Clock schedules the wait between passes. Tests replace it so backoff can be checked without sleeping.
type CommandError ¶
CommandError is a service-manager command that exited non-zero.
func (*CommandError) Error ¶
func (e *CommandError) Error() string
type Config ¶
type Config struct {
// Reporter configures each pass. Its Providers allowlist is the
// daemon's; Run refuses to start without one. Out and Stop are set by
// Run.
Reporter reporter.Config
// Interval is the time between successful passes. Zero means
// DefaultInterval.
Interval time.Duration
// Dir holds daemon.lock and daemon.log. Empty means
// ~/.firekeeper, using Reporter.Home when set.
Dir string
// Out, when set, also receives every log line.
Out io.Writer
// RunOnce, Heartbeat, Clock, and Rand replace the real implementations
// in tests. Nil means reporter.RunOnce, reporter.Heartbeat, the system
// clock, and math/rand/v2.Float64.
RunOnce func(context.Context, reporter.Config) (reporter.Summary, error)
Heartbeat func(context.Context, reporter.Config, reporter.Summary) error
Clock Clock
Rand func() float64
}
Config configures Run.
type ExecRunner ¶
type ExecRunner struct{}
ExecRunner runs commands with os/exec, bounded by a timeout.
type Reporting ¶
type Reporting struct {
// Installed reports whether the service definition file exists.
Installed bool
// Running reports whether the service is running or a daemon holds
// the lock, such as one started in a terminal.
Running bool
// Foreground reports that the running daemon is not the service: the
// service manager says it is stopped, yet a daemon holds the lock.
Foreground bool
// Server is the dashboard URL the daemon reports to: its --server
// flag when the service has one, else the configured server, else
// reporter.DefaultServer.
Server string
// Providers are the service's --provider flags, or the configured
// providers when it has none.
Providers []transcript.Provider
}
Reporting is what this machine can tell about its own daemon without asking it: whether it is installed and running, where it sends sessions, and which providers it uploads. Every field is best effort.
type Runner ¶
Runner runs a service-manager command and returns its combined output. A command that runs and exits non-zero returns a *CommandError. Tests replace it so no real launchctl or systemctl runs.
type Service ¶
type Service struct {
// GOOS picks the service manager: "darwin" or "linux".
GOOS string
// Home is the user's home directory.
Home string
// UID is the user's numeric id, for the launchd gui/<uid> domain.
UID int
// Executable is the absolute path of the firekeeper binary to run.
Executable string
// Args follow "daemon" on the service's command line.
Args []string
// Env holds the variables written into the service definition.
Env map[string]string
// Runner runs launchctl and systemctl.
Runner Runner
// Out receives progress lines.
Out io.Writer
// Sleep waits between bootstrap retries. Nil means time.Sleep.
Sleep func(time.Duration)
}
Service installs, removes, and inspects the daemon as a per-user login service: a LaunchAgent on macOS and a systemd user unit on Linux. It never needs or calls sudo.
func NewService ¶
NewService returns a Service for the current user and platform, with the running binary as its executable and the current environment's provider homes and PATH captured.
func (*Service) Commands ¶
Commands lists the service-manager commands Install runs after writing the file, for a dry run.
func (*Service) Inspect ¶
func (s *Service) Inspect(ctx context.Context, configServer string, configProviders []transcript.Provider) Reporting
Inspect describes the daemon. configServer and configProviders are the merged configuration, used for whatever the service definition does not set. It reads the service file and asks the service manager, so it may run launchctl or systemctl; it never changes anything.
func (*Service) Install ¶
Install writes the service definition and starts the service. Running it again replaces the definition and restarts the service with the new one.
func (*Service) InstalledArgs ¶
InstalledArgs returns the arguments the installed service passes after "daemon", read back from its definition file. It returns an error wrapping os.ErrNotExist when the service is not installed.
func (*Service) StartupLogPath ¶
StartupLogPath is where launchd writes the daemon's stdout and stderr.
type Status ¶
type Status struct {
// Installed reports whether the service definition file exists.
Installed bool
// Loaded reports whether the service manager knows the service.
Loaded bool
// Running reports whether the daemon process is up.
Running bool
// State is the manager's own word for the service's state.
State string
PID int
// LastExit is the last exit status, or empty when unknown.
LastExit string
}
Status describes the installed service.