Skip to content

Commit 50cabe7

Browse files
authored
Make the log level of Go services configurable (#2413)
Summary: Make the log level of Go services configurable Every Go service in Pixie Cloud and Vizier calls `services.SetupServiceLogging()`, which hard coded the logrus level to `info`. As discussed in the issue, there was no way to reduce log volume or turn on debug logging without rebuilding. Following the approach suggested in the issue, this PR adds a common `--log_level` flag to `service_flags.go` and uses it in `SetupServiceLogging()`. Like the other service flags, it can also be set with the `PL_LOG_LEVEL` environment variable. It accepts any logrus level (`panic`, `fatal`, `error`, `warn`, `info`, `debug`, `trace`, case insensitive) and defaults to `info`, so current deployments behave exactly as before. An invalid value is a fatal configuration error, the same way `CheckServiceFlags()` handles other invalid flags. The level is applied after flags are parsed, so the `Starting service` line that `SetupService()` logs before parsing is still printed at info level. This only affects the Go logrus logger. The C++ (glog) logging in PEM, Kelvin and the query broker already has its own runtime flags. Relevant Issues: Fixes #2280 Type of change: /kind feature Test Plan: Added `//src/shared/services:services_test`, which checks the default level, explicit levels, case insensitivity, and that an invalid level is fatal. The explicit level cases fail on `main`. I also built `scriptmgr` and ran it locally. With no flag it logs at info. With `--log_level=error`, only error logs are printed after startup. With `PL_LOG_LEVEL=debug`, debug logs are printed. With `--log_level=bogus`, it exits with `Flag --log_level or ENV PL_LOG_LEVEL is invalid`. `go vet` and golangci-lint v2.3.1 with the repo's `.golangci.yaml` are clean. Changelog Message: ```release-note Go services in Pixie Cloud and Vizier now accept a `--log_level` flag (or `PL_LOG_LEVEL` environment variable) to configure their log level. The default remains `info`. ``` Signed-off-by: NopeCharon <115794254+NopeCharon@users.noreply.github.com>
1 parent 3e3350f commit 50cabe7

4 files changed

Lines changed: 118 additions & 1 deletion

File tree

‎src/shared/services/BUILD.bazel‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# SPDX-License-Identifier: Apache-2.0
1616

1717
load("@io_bazel_rules_go//go:def.bzl", "go_library")
18+
load("//bazel:pl_build_system.bzl", "pl_go_test")
1819

1920
go_library(
2021
name = "services",
@@ -50,3 +51,16 @@ go_library(
5051
"@org_golang_google_grpc//status",
5152
],
5253
)
54+
55+
pl_go_test(
56+
name = "services_test",
57+
srcs = ["logging_test.go"],
58+
embed = [":services"],
59+
deps = [
60+
"@com_github_sirupsen_logrus//:logrus",
61+
"@com_github_spf13_pflag//:pflag",
62+
"@com_github_spf13_viper//:viper",
63+
"@com_github_stretchr_testify//assert",
64+
"@com_github_stretchr_testify//require",
65+
],
66+
)

‎src/shared/services/logging.go‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"time"
2525

2626
log "github.com/sirupsen/logrus"
27+
"github.com/spf13/viper"
2728
"github.com/zenazn/goji/web/mutil"
2829

2930
version "px.dev/pixie/src/shared/goversion"
@@ -39,7 +40,11 @@ func init() {
3940
func SetupServiceLogging() {
4041
// Setup logging.
4142
log.SetOutput(os.Stdout)
42-
log.SetLevel(log.InfoLevel)
43+
level, err := log.ParseLevel(viper.GetString("log_level"))
44+
if err != nil {
45+
log.WithError(err).Fatal("Flag --log_level or ENV PL_LOG_LEVEL is invalid")
46+
}
47+
log.SetLevel(level)
4348
}
4449

4550
// HTTPLoggingMiddleware is a middleware function used for logging HTTP requests.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2018- The Pixie Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
*/
18+
19+
package services
20+
21+
import (
22+
"testing"
23+
24+
log "github.com/sirupsen/logrus"
25+
"github.com/spf13/pflag"
26+
"github.com/spf13/viper"
27+
"github.com/stretchr/testify/assert"
28+
"github.com/stretchr/testify/require"
29+
)
30+
31+
func TestSetupServiceLogging(t *testing.T) {
32+
SetupCommonFlags()
33+
34+
tests := []struct {
35+
name string
36+
logLevel string
37+
expectedLevel log.Level
38+
}{
39+
{
40+
name: "default",
41+
logLevel: "",
42+
expectedLevel: log.InfoLevel,
43+
},
44+
{
45+
name: "debug",
46+
logLevel: "debug",
47+
expectedLevel: log.DebugLevel,
48+
},
49+
{
50+
name: "error",
51+
logLevel: "error",
52+
expectedLevel: log.ErrorLevel,
53+
},
54+
{
55+
name: "case insensitive",
56+
logLevel: "WARN",
57+
expectedLevel: log.WarnLevel,
58+
},
59+
}
60+
61+
for _, test := range tests {
62+
t.Run(test.name, func(t *testing.T) {
63+
origLevel := log.GetLevel()
64+
t.Cleanup(func() {
65+
viper.Reset()
66+
log.SetLevel(origLevel)
67+
})
68+
69+
require.NoError(t, viper.BindPFlag("log_level", pflag.Lookup("log_level")))
70+
if test.logLevel != "" {
71+
viper.Set("log_level", test.logLevel)
72+
}
73+
74+
SetupServiceLogging()
75+
assert.Equal(t, test.expectedLevel, log.GetLevel())
76+
})
77+
}
78+
}
79+
80+
func TestSetupServiceLogging_InvalidLevel(t *testing.T) {
81+
origLevel := log.GetLevel()
82+
origExitFunc := log.StandardLogger().ExitFunc
83+
t.Cleanup(func() {
84+
viper.Reset()
85+
log.SetLevel(origLevel)
86+
log.StandardLogger().ExitFunc = origExitFunc
87+
})
88+
89+
exitCode := 0
90+
log.StandardLogger().ExitFunc = func(code int) {
91+
exitCode = code
92+
}
93+
94+
viper.Set("log_level", "verbose")
95+
SetupServiceLogging()
96+
assert.Equal(t, 1, exitCode)
97+
}

‎src/shared/services/service_flags.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func setupCommonFlags() {
5151
pflag.String("jwt_signing_key", "", "The signing key used for JWTs")
5252
pflag.String("pod_name", "<unknown>", "The pod name")
5353
pflag.Bool("version", false, "Print the version and quit.")
54+
pflag.String("log_level", log.InfoLevel.String(), "The log level. One of: panic, fatal, error, warn, info, debug, trace.")
5455
}
5556

5657
// SetupCommonFlags sets flags that are used by every service, even non GRPC servers.

0 commit comments

Comments
 (0)