Skip to content

Commit 698d22e

Browse files
committed
feat(cli): support fine-grained server log filtering
1 parent 6b92abe commit 698d22e

File tree

15 files changed

+139
-52
lines changed

15 files changed

+139
-52
lines changed

agent/agent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ func (a *agent) createTailnet(ctx context.Context, agentID uuid.UUID, derpMap *t
755755
network, err := tailnet.NewConn(&tailnet.Options{
756756
Addresses: a.wireguardAddresses(agentID),
757757
DERPMap: derpMap,
758-
Logger: a.logger.Named("tailnet"),
758+
Logger: a.logger.Named("net.tailnet"),
759759
ListenPort: a.tailnetListenPort,
760760
BlockEndpoints: disableDirectConnections,
761761
})

cli/server.go

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
334334
)
335335
if cfg.AccessURL.String() == "" {
336336
cliui.Infof(inv.Stderr, "Opening tunnel so workspaces can connect to your deployment. For production scenarios, specify an external access URL")
337-
tunnel, err = devtunnel.New(ctx, logger.Named("devtunnel"), cfg.WgtunnelHost.String())
337+
tunnel, err = devtunnel.New(ctx, logger.Named("net.devtunnel"), cfg.WgtunnelHost.String())
338338
if err != nil {
339339
return xerrors.Errorf("create tunnel: %w", err)
340340
}
@@ -1751,6 +1751,50 @@ func IsLocalhost(host string) bool {
17511751
return host == "localhost" || host == "127.0.0.1" || host == "::1"
17521752
}
17531753

1754+
var _ slog.Sink = &filterSink{}
1755+
1756+
type filterSink struct {
1757+
next []slog.Sink
1758+
re *regexp.Regexp
1759+
}
1760+
1761+
func (f *filterSink) compile(res []string) error {
1762+
if len(res) == 0 {
1763+
return nil
1764+
}
1765+
1766+
var reb strings.Builder
1767+
for i, re := range res {
1768+
_, _ = fmt.Fprintf(&reb, "(%s)", re)
1769+
if i != len(res)-1 {
1770+
_, _ = reb.WriteRune('|')
1771+
}
1772+
}
1773+
1774+
re, err := regexp.Compile(reb.String())
1775+
if err != nil {
1776+
return xerrors.Errorf("compile regex: %w", err)
1777+
}
1778+
f.re = re
1779+
return nil
1780+
}
1781+
1782+
func (f *filterSink) LogEntry(ctx context.Context, ent slog.SinkEntry) {
1783+
logName := strings.Join(ent.LoggerNames, ".")
1784+
if f.re != nil && !f.re.MatchString(logName) {
1785+
return
1786+
}
1787+
for _, sink := range f.next {
1788+
sink.LogEntry(ctx, ent)
1789+
}
1790+
}
1791+
1792+
func (f *filterSink) Sync() {
1793+
for _, sink := range f.next {
1794+
sink.Sync()
1795+
}
1796+
}
1797+
17541798
func BuildLogger(inv *clibase.Invocation, cfg *codersdk.DeploymentValues) (slog.Logger, func(), error) {
17551799
var (
17561800
sinks = []slog.Sink{}
@@ -1795,16 +1839,25 @@ func BuildLogger(inv *clibase.Invocation, cfg *codersdk.DeploymentValues) (slog.
17951839
sinks = append(sinks, tracing.SlogSink{})
17961840
}
17971841

1798-
level := slog.LevelInfo
1799-
if cfg.Verbose {
1800-
level = slog.LevelDebug
1801-
}
1802-
1842+
// User should log to null device if they don't want logs.
18031843
if len(sinks) == 0 {
18041844
return slog.Logger{}, nil, xerrors.New("no loggers provided")
18051845
}
18061846

1807-
return slog.Make(sinks...).Leveled(level), func() {
1847+
filter := &filterSink{next: sinks}
1848+
1849+
err = filter.compile(cfg.Logging.Filter.Value())
1850+
if err != nil {
1851+
return slog.Logger{}, nil, xerrors.Errorf("compile filters: %w", err)
1852+
}
1853+
1854+
level := slog.LevelInfo
1855+
// Debug logging is always enabled if a filter is present.
1856+
if cfg.Verbose || filter.re != nil {
1857+
level = slog.LevelDebug
1858+
}
1859+
1860+
return slog.Make(filter).Leveled(level), func() {
18081861
for _, closer := range closers {
18091862
_ = closer()
18101863
}

cli/server_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,7 +1305,7 @@ func TestServer(t *testing.T) {
13051305

13061306
root, _ := clitest.New(t,
13071307
"server",
1308-
"--verbose",
1308+
"--log-filter=.*",
13091309
"--in-memory",
13101310
"--http-address", ":0",
13111311
"--access-url", "http://example.com",
@@ -1322,7 +1322,7 @@ func TestServer(t *testing.T) {
13221322

13231323
root, _ := clitest.New(t,
13241324
"server",
1325-
"--verbose",
1325+
"--log-filter=.*",
13261326
"--in-memory",
13271327
"--http-address", ":0",
13281328
"--access-url", "http://example.com",
@@ -1339,7 +1339,7 @@ func TestServer(t *testing.T) {
13391339

13401340
root, _ := clitest.New(t,
13411341
"server",
1342-
"--verbose",
1342+
"--log-filter=.*",
13431343
"--in-memory",
13441344
"--http-address", ":0",
13451345
"--access-url", "http://example.com",
@@ -1359,7 +1359,7 @@ func TestServer(t *testing.T) {
13591359

13601360
inv, _ := clitest.New(t,
13611361
"server",
1362-
"--verbose",
1362+
"--log-filter=.*",
13631363
"--in-memory",
13641364
"--http-address", ":0",
13651365
"--access-url", "http://example.com",
@@ -1393,7 +1393,7 @@ func TestServer(t *testing.T) {
13931393
// HTTP.
13941394
inv, _ := clitest.New(t,
13951395
"server",
1396-
"--verbose",
1396+
"--log-filter=.*",
13971397
"--in-memory",
13981398
"--http-address", ":0",
13991399
"--access-url", "http://example.com",

cli/testdata/coder_server_--help.golden

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,13 @@ Use a YAML configuration file when your server launch become unwieldy.
8383
--log-json string, $CODER_LOGGING_JSON
8484
Output JSON logs to a given file.
8585

86+
-l, --log-filter string-array, $CODER_LOG_FILTER
87+
Filter debug logs by matching against a given regex. Use .* to match
88+
all debug logs.
89+
8690
--log-stackdriver string, $CODER_LOGGING_STACKDRIVER
8791
Output Stackdriver compatible logs to a given file.
8892

89-
-v, --verbose bool, $CODER_VERBOSE
90-
Output debug-level logs.
91-
9293
Introspection / Prometheus Options
9394
--prometheus-address host:port, $CODER_PROMETHEUS_ADDRESS (default: 127.0.0.1:2112)
9495
The bind address to serve prometheus metrics.

coderd/apidoc/docs.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/workspaceagents.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ func (api *API) _dialWorkspaceAgentTailnet(agentID uuid.UUID) (*codersdk.Workspa
691691
conn, err := tailnet.NewConn(&tailnet.Options{
692692
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)},
693693
DERPMap: api.DERPMap(),
694-
Logger: api.Logger.Named("tailnet"),
694+
Logger: api.Logger.Named("net.tailnet"),
695695
BlockEndpoints: api.DeploymentValues.DERP.Config.BlockDirect.Value(),
696696
})
697697
if err != nil {

codersdk/deployment.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -340,9 +340,10 @@ type SwaggerConfig struct {
340340
}
341341

342342
type LoggingConfig struct {
343-
Human clibase.String `json:"human" typescript:",notnull"`
344-
JSON clibase.String `json:"json" typescript:",notnull"`
345-
Stackdriver clibase.String `json:"stackdriver" typescript:",notnull"`
343+
Filter clibase.StringArray `json:"log_filter" typescript:",notnull"`
344+
Human clibase.String `json:"human" typescript:",notnull"`
345+
JSON clibase.String `json:"json" typescript:",notnull"`
346+
Stackdriver clibase.String `json:"stackdriver" typescript:",notnull"`
346347
}
347348

348349
type DangerousConfig struct {
@@ -533,6 +534,16 @@ when required by your organization's security policy.`,
533534
Group: &deploymentGroupNetworking,
534535
YAML: "redirectToAccessURL",
535536
}
537+
logFilter := clibase.Option{
538+
Name: "Log Filter",
539+
Description: "Filter debug logs by matching against a given regex. Use .* to match all debug logs.",
540+
Flag: "log-filter",
541+
FlagShorthand: "l",
542+
Env: "CODER_LOG_FILTER",
543+
Value: &c.Logging.Filter,
544+
Group: &deploymentGroupIntrospectionLogging,
545+
YAML: "filter",
546+
}
536547
opts := clibase.OptionSet{
537548
{
538549
Name: "Access URL",
@@ -1249,12 +1260,14 @@ when required by your organization's security policy.`,
12491260
Flag: "verbose",
12501261
Env: "CODER_VERBOSE",
12511262
FlagShorthand: "v",
1252-
1253-
Value: &c.Verbose,
1254-
Group: &deploymentGroupIntrospectionLogging,
1255-
YAML: "verbose",
1256-
Annotations: clibase.Annotations{}.Mark(annotationExternalProxies, "true"),
1263+
Hidden: true,
1264+
UseInstead: []clibase.Option{logFilter},
1265+
Value: &c.Verbose,
1266+
Group: &deploymentGroupIntrospectionLogging,
1267+
YAML: "verbose",
1268+
Annotations: clibase.Annotations{}.Mark(annotationExternalProxies, "true"),
12571269
},
1270+
logFilter,
12581271
{
12591272
Name: "Human Log Location",
12601273
Description: "Output human-readable logs to a given file.",

docs/api/general.md

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/api/schemas.md

Lines changed: 9 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy