Skip to content

Commit 71c52ea

Browse files
authored
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.
1 parent b6c8e5b commit 71c52ea

File tree

2 files changed

+86
-9
lines changed

2 files changed

+86
-9
lines changed

cli/agent.go

+77-9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222

2323
"cdr.dev/slog"
2424
"cdr.dev/slog/sloggers/sloghuman"
25+
"cdr.dev/slog/sloggers/slogjson"
26+
"cdr.dev/slog/sloggers/slogstackdriver"
2527
"github.com/coder/coder/agent"
2628
"github.com/coder/coder/agent/reaper"
2729
"github.com/coder/coder/buildinfo"
@@ -32,14 +34,17 @@ import (
3234

3335
func (r *RootCmd) workspaceAgent() *clibase.Cmd {
3436
var (
35-
auth string
36-
logDir string
37-
pprofAddress string
38-
noReap bool
39-
sshMaxTimeout time.Duration
40-
tailnetListenPort int64
41-
prometheusAddress string
42-
debugAddress string
37+
auth string
38+
logDir string
39+
pprofAddress string
40+
noReap bool
41+
sshMaxTimeout time.Duration
42+
tailnetListenPort int64
43+
prometheusAddress string
44+
debugAddress string
45+
slogHumanPath string
46+
slogJSONPath string
47+
slogStackdriverPath string
4348
)
4449
cmd := &clibase.Cmd{
4550
Use: "agent",
@@ -62,7 +67,46 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
6267
MaxSize: 5, // MB
6368
}
6469
defer logWriter.Close()
65-
logger := slog.Make(sloghuman.Sink(inv.Stderr), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug)
70+
71+
sinks := []slog.Sink{sloghuman.Sink(logWriter)}
72+
closers := []func() error{}
73+
addSinkIfProvided := func(sinkFn func(io.Writer) slog.Sink, loc string) error {
74+
switch loc {
75+
case "":
76+
77+
case "/dev/stdout":
78+
sinks = append(sinks, sinkFn(inv.Stdout))
79+
80+
case "/dev/stderr":
81+
sinks = append(sinks, sinkFn(inv.Stderr))
82+
83+
default:
84+
fi, err := os.OpenFile(loc, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644)
85+
if err != nil {
86+
return xerrors.Errorf("open log file %q: %w", loc, err)
87+
}
88+
closers = append(closers, fi.Close)
89+
sinks = append(sinks, sinkFn(fi))
90+
}
91+
return nil
92+
}
93+
94+
if err := addSinkIfProvided(sloghuman.Sink, slogHumanPath); err != nil {
95+
return xerrors.Errorf("add human sink: %w", err)
96+
}
97+
if err := addSinkIfProvided(slogjson.Sink, slogJSONPath); err != nil {
98+
return xerrors.Errorf("add json sink: %w", err)
99+
}
100+
if err := addSinkIfProvided(slogstackdriver.Sink, slogStackdriverPath); err != nil {
101+
return xerrors.Errorf("add stackdriver sink: %w", err)
102+
}
103+
104+
logger := slog.Make(sinks...).Leveled(slog.LevelDebug)
105+
defer func() {
106+
for _, closer := range closers {
107+
_ = closer()
108+
}
109+
}()
66110

67111
logger.Info(ctx, "spawning reaper process")
68112
// Do not start a reaper on the child process. It's important
@@ -290,6 +334,30 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
290334
Value: clibase.StringOf(&debugAddress),
291335
Description: "The bind address to serve a debug HTTP server.",
292336
},
337+
{
338+
Name: "Human Log Location",
339+
Description: "Output human-readable logs to a given file.",
340+
Flag: "log-human",
341+
Env: "CODER_AGENT_LOGGING_HUMAN",
342+
Default: "/dev/stderr",
343+
Value: clibase.StringOf(&slogHumanPath),
344+
},
345+
{
346+
Name: "JSON Log Location",
347+
Description: "Output JSON logs to a given file.",
348+
Flag: "log-json",
349+
Env: "CODER_AGENT_LOGGING_JSON",
350+
Default: "",
351+
Value: clibase.StringOf(&slogJSONPath),
352+
},
353+
{
354+
Name: "Stackdriver Log Location",
355+
Description: "Output Stackdriver compatible logs to a given file.",
356+
Flag: "log-stackdriver",
357+
Env: "CODER_AGENT_LOGGING_STACKDRIVER",
358+
Default: "",
359+
Value: clibase.StringOf(&slogStackdriverPath),
360+
},
293361
}
294362

295363
return cmd

cli/testdata/coder_agent_--help.golden

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ Usage: coder agent [flags]
33
Starts the Coder workspace agent.
44

55
Options
6+
--log-human string, $CODER_AGENT_LOGGING_HUMAN (default: /dev/stderr)
7+
Output human-readable logs to a given file.
8+
9+
--log-json string, $CODER_AGENT_LOGGING_JSON
10+
Output JSON logs to a given file.
11+
12+
--log-stackdriver string, $CODER_AGENT_LOGGING_STACKDRIVER
13+
Output Stackdriver compatible logs to a given file.
14+
615
--auth string, $CODER_AGENT_AUTH (default: token)
716
Specify the authentication type to use for the agent.
817

0 commit comments

Comments
 (0)