feat: Add logging options for coder agent (#7474)

Similar to logging options in the coderd server, but for the agent
running in workspaces. Meant to make hollistic log collection and
querying simpler.
This commit is contained in:
goodspark
2023-05-24 07:32:40 -07:00
committed by GitHub
parent b6c8e5be48
commit 71c52ea93c
2 changed files with 86 additions and 9 deletions

View File

@ -22,6 +22,8 @@ import (
"cdr.dev/slog" "cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman" "cdr.dev/slog/sloggers/sloghuman"
"cdr.dev/slog/sloggers/slogjson"
"cdr.dev/slog/sloggers/slogstackdriver"
"github.com/coder/coder/agent" "github.com/coder/coder/agent"
"github.com/coder/coder/agent/reaper" "github.com/coder/coder/agent/reaper"
"github.com/coder/coder/buildinfo" "github.com/coder/coder/buildinfo"
@ -40,6 +42,9 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
tailnetListenPort int64 tailnetListenPort int64
prometheusAddress string prometheusAddress string
debugAddress string debugAddress string
slogHumanPath string
slogJSONPath string
slogStackdriverPath string
) )
cmd := &clibase.Cmd{ cmd := &clibase.Cmd{
Use: "agent", Use: "agent",
@ -62,7 +67,46 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
MaxSize: 5, // MB MaxSize: 5, // MB
} }
defer logWriter.Close() defer logWriter.Close()
logger := slog.Make(sloghuman.Sink(inv.Stderr), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug)
sinks := []slog.Sink{sloghuman.Sink(logWriter)}
closers := []func() error{}
addSinkIfProvided := func(sinkFn func(io.Writer) slog.Sink, loc string) error {
switch loc {
case "":
case "/dev/stdout":
sinks = append(sinks, sinkFn(inv.Stdout))
case "/dev/stderr":
sinks = append(sinks, sinkFn(inv.Stderr))
default:
fi, err := os.OpenFile(loc, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644)
if err != nil {
return xerrors.Errorf("open log file %q: %w", loc, err)
}
closers = append(closers, fi.Close)
sinks = append(sinks, sinkFn(fi))
}
return nil
}
if err := addSinkIfProvided(sloghuman.Sink, slogHumanPath); err != nil {
return xerrors.Errorf("add human sink: %w", err)
}
if err := addSinkIfProvided(slogjson.Sink, slogJSONPath); err != nil {
return xerrors.Errorf("add json sink: %w", err)
}
if err := addSinkIfProvided(slogstackdriver.Sink, slogStackdriverPath); err != nil {
return xerrors.Errorf("add stackdriver sink: %w", err)
}
logger := slog.Make(sinks...).Leveled(slog.LevelDebug)
defer func() {
for _, closer := range closers {
_ = closer()
}
}()
logger.Info(ctx, "spawning reaper process") logger.Info(ctx, "spawning reaper process")
// Do not start a reaper on the child process. It's important // Do not start a reaper on the child process. It's important
@ -290,6 +334,30 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
Value: clibase.StringOf(&debugAddress), Value: clibase.StringOf(&debugAddress),
Description: "The bind address to serve a debug HTTP server.", Description: "The bind address to serve a debug HTTP server.",
}, },
{
Name: "Human Log Location",
Description: "Output human-readable logs to a given file.",
Flag: "log-human",
Env: "CODER_AGENT_LOGGING_HUMAN",
Default: "/dev/stderr",
Value: clibase.StringOf(&slogHumanPath),
},
{
Name: "JSON Log Location",
Description: "Output JSON logs to a given file.",
Flag: "log-json",
Env: "CODER_AGENT_LOGGING_JSON",
Default: "",
Value: clibase.StringOf(&slogJSONPath),
},
{
Name: "Stackdriver Log Location",
Description: "Output Stackdriver compatible logs to a given file.",
Flag: "log-stackdriver",
Env: "CODER_AGENT_LOGGING_STACKDRIVER",
Default: "",
Value: clibase.StringOf(&slogStackdriverPath),
},
} }
return cmd return cmd

View File

@ -3,6 +3,15 @@ Usage: coder agent [flags]
Starts the Coder workspace agent. Starts the Coder workspace agent.
Options Options
--log-human string, $CODER_AGENT_LOGGING_HUMAN (default: /dev/stderr)
Output human-readable logs to a given file.
--log-json string, $CODER_AGENT_LOGGING_JSON
Output JSON logs to a given file.
--log-stackdriver string, $CODER_AGENT_LOGGING_STACKDRIVER
Output Stackdriver compatible logs to a given file.
--auth string, $CODER_AGENT_AUTH (default: token) --auth string, $CODER_AGENT_AUTH (default: token)
Specify the authentication type to use for the agent. Specify the authentication type to use for the agent.