Add log level control for docker agent

Related to #742
This commit is contained in:
rcourtman 2025-11-22 07:43:48 +00:00
parent ee3f1e0cdb
commit 19a2cac355
3 changed files with 55 additions and 16 deletions

View file

@ -50,7 +50,9 @@ func main() {
cfg := loadConfig()
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
zerolog.SetGlobalLevel(cfg.LogLevel)
logger := zerolog.New(os.Stdout).Level(cfg.LogLevel).With().Timestamp().Logger()
cfg.Logger = &logger
agent, err := dockeragent.New(cfg)
@ -87,6 +89,7 @@ func loadConfig() dockeragent.Config {
envSwarmTasks := utils.GetenvTrim("PULSE_SWARM_TASKS")
envIncludeContainers := utils.GetenvTrim("PULSE_INCLUDE_CONTAINERS")
envCollectDisk := utils.GetenvTrim("PULSE_COLLECT_DISK")
envLogLevel := utils.GetenvTrim("LOG_LEVEL")
defaultInterval := 30 * time.Second
if envInterval != "" {
@ -120,6 +123,11 @@ func loadConfig() dockeragent.Config {
collectDiskDefault = utils.ParseBool(envCollectDisk)
}
logLevelDefault := "info"
if envLogLevel != "" {
logLevelDefault = envLogLevel
}
urlFlag := flag.String("url", envURL, "Pulse server URL (e.g. http://pulse:7655)")
tokenFlag := flag.String("token", envToken, "Pulse API token (required)")
intervalFlag := flag.Duration("interval", defaultInterval, "Reporting interval (e.g. 30s)")
@ -128,6 +136,7 @@ func loadConfig() dockeragent.Config {
insecureFlag := flag.Bool("insecure", utils.ParseBool(envInsecure), "Skip TLS certificate verification")
noAutoUpdateFlag := flag.Bool("no-auto-update", utils.ParseBool(envNoAutoUpdate), "Disable automatic agent updates")
runtimeFlag := flag.String("runtime", envRuntime, "Container runtime to expect (auto, docker, podman)")
logLevelFlag := flag.String("log-level", logLevelDefault, "Log level: debug, info, warn, error")
var targetFlags stringFlagList
flag.Var(&targetFlags, "target", "Pulse target in url|token[|insecure] format. Repeat to send to multiple Pulse instances")
var containerStateFlags stringFlagList
@ -211,6 +220,12 @@ func loadConfig() dockeragent.Config {
interval = 30 * time.Second
}
logLevel, err := parseLogLevel(*logLevelFlag)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
containerStates := make([]string, 0)
if len(containerStateFlags) > 0 {
containerStates = append(containerStates, containerStateFlags.Values()...)
@ -235,9 +250,24 @@ func loadConfig() dockeragent.Config {
IncludeTasks: *includeTasksFlag,
IncludeContainers: *includeContainersFlag,
CollectDiskMetrics: *collectDiskFlag,
LogLevel: logLevel,
}
}
func parseLogLevel(value string) (zerolog.Level, error) {
normalized := strings.ToLower(strings.TrimSpace(value))
if normalized == "" {
return zerolog.InfoLevel, nil
}
level, err := zerolog.ParseLevel(normalized)
if err != nil {
return zerolog.InfoLevel, fmt.Errorf("invalid log level %q: must be debug, info, warn, or error", value)
}
return level, nil
}
func parseTargetSpecs(specs []string) ([]dockeragent.TargetConfig, error) {
targets := make([]dockeragent.TargetConfig, 0, len(specs))
for _, spec := range specs {

View file

@ -220,6 +220,8 @@ docker run -d \
ghcr.io/rcourtman/pulse-docker-agent:latest
```
Add `-e LOG_LEVEL=warn` when your container logs feed into journald or another centralized collector and you want quieter steady-state logging.
> **Note**: Official images for `linux/amd64` and `linux/arm64` are published to `ghcr.io/rcourtman/pulse-docker-agent`. To test local changes, run `docker build --target agent_runtime -t pulse-docker-agent:test .` from the repository root.
`--pid=host`, `--uts=host`, and the `/etc/machine-id` bind keep host metadata stable so Pulse doesnt think the container itself is the Docker host. Auto-update is disabled in the image by default; rebuild or override `PULSE_NO_AUTO_UPDATE=false` only if you manage upgrades outside of your orchestrator. Expect to grant the container the same level of Docker socket access as the systemd service—running inside Docker doesnt sandbox the agent from the host.
@ -232,6 +234,7 @@ docker run -d \
| `--token`, `PULSE_TOKEN`| Pulse API token with `docker:report` scope (required). | — |
| `--target`, `PULSE_TARGETS` | One or more `url|token[|insecure]` entries to fan-out reports to multiple Pulse servers. Separate entries with `;` or repeat the flag. | — |
| `--interval`, `PULSE_INTERVAL` | Reporting cadence (supports `30s`, `1m`, etc.). | `30s` |
| `--log-level`, `LOG_LEVEL` | Log verbosity (`debug`, `info`, `warn`, `error`). Use `debug` only while actively troubleshooting to avoid noisy journals. | `info` |
| `--runtime`, `PULSE_RUNTIME` | Container runtime to target (`docker`, `podman`, `auto`). | `docker` |
| `--container-socket`, `PULSE_CONTAINER_SOCKET` / `CONTAINER_HOST` | Explicit runtime socket path or `unix://` URI. | Runtime default |
| `--rootless`, `PULSE_RUNTIME_ROOTLESS` | Install/manage the agent as a user service (Podman). | Auto (rootful) |
@ -260,6 +263,7 @@ Need the alerts but at a different tone? The same Containers tab exposes global
## Testing and troubleshooting
- Run with `--interval 15s --insecure` in a terminal to see log output while testing.
- Adjust verbosity with `--log-level` or `LOG_LEVEL` (`info` by default). Drop to `warn` for quiet steady-state logs; use `debug` only when actively debugging.
- Ensure the Pulse API token has not expired or been regenerated.
- If `pulse-docker-agent` reports `Cannot connect to the Docker daemon`, verify the socket path and permissions.
- Check Pulse (`/containers` tab) for the latest heartbeat time. Hosts are marked offline if they stop reporting for >4× the configured interval.

View file

@ -57,6 +57,7 @@ type Config struct {
IncludeTasks bool
IncludeContainers bool
CollectDiskMetrics bool
LogLevel zerolog.Level
Logger *zerolog.Logger
}
@ -81,20 +82,20 @@ const (
// Agent collects Docker metrics and posts them to Pulse.
type Agent struct {
cfg Config
docker *client.Client
daemonHost string
runtime RuntimeKind
runtimeVer string
supportsSwarm bool
httpClients map[bool]*http.Client
logger zerolog.Logger
machineID string
hostName string
cpuCount int
targets []TargetConfig
allowedStates map[string]struct{}
stateFilters []string
cfg Config
docker *client.Client
daemonHost string
runtime RuntimeKind
runtimeVer string
supportsSwarm bool
httpClients map[bool]*http.Client
logger zerolog.Logger
machineID string
hostName string
cpuCount int
targets []TargetConfig
allowedStates map[string]struct{}
stateFilters []string
hostID string
prevContainerCPU map[string]cpuSample
preCPUStatsFailures int
@ -158,8 +159,12 @@ func New(cfg Config) (*Agent, error) {
}
logger := cfg.Logger
if zerolog.GlobalLevel() == zerolog.DebugLevel && cfg.LogLevel != zerolog.DebugLevel {
zerolog.SetGlobalLevel(cfg.LogLevel)
}
if logger == nil {
defaultLogger := zerolog.New(os.Stdout).With().Timestamp().Str("component", "pulse-docker-agent").Logger()
defaultLogger := zerolog.New(os.Stdout).Level(cfg.LogLevel).With().Timestamp().Str("component", "pulse-docker-agent").Logger()
logger = &defaultLogger
} else {
scoped := logger.With().Str("component", "pulse-docker-agent").Logger()