diff --git a/logp/config.go b/logp/config.go index 58f2db6..bdc4e83 100644 --- a/logp/config.go +++ b/logp/config.go @@ -71,15 +71,19 @@ const ( // Beat is supposed to be run within. func DefaultConfig(environment Environment) Config { toFiles := true + toStderr := false - // If running in a container environment, don't write to files by default. - if environment == ContainerEnvironment { + // For container and systemd environments, we don't write to files by default. + switch environment { + case ContainerEnvironment, SystemdEnvironment: toFiles = false + toStderr = true } return Config{ - Level: defaultLevel, - ToFiles: toFiles, + Level: defaultLevel, + ToFiles: toFiles, + ToStderr: toStderr, Files: FileConfig{ MaxSize: 10 * 1024 * 1024, MaxBackups: 7, diff --git a/logp/defaults_test.go b/logp/defaults_test.go index 4fa4258..288d386 100644 --- a/logp/defaults_test.go +++ b/logp/defaults_test.go @@ -159,8 +159,7 @@ func TestDefaultConfigContainer(t *testing.T) { return } - // This is running in a separate process. By default the - // container environment should be logging to stderr. + // This is running in a separate process. cfg := logp.DefaultConfig(logp.ContainerEnvironment) assert.NoError(t, logp.Configure(cfg)) logger := logp.L() @@ -168,6 +167,54 @@ func TestDefaultConfigContainer(t *testing.T) { logger.Info("foo") } +func TestDefaultConfigSystemd(t *testing.T) { + switch runtime.GOOS { + case "wasip1", "js", "ios": + t.Skipf("cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH) + } + + if os.Getenv("TEST_DEFAULT_CONFIG_SYSTEMD") != "1" { + cmd := exec.Command(os.Args[0], "-test.run=^TestDefaultConfigSystemd$", "-test.v") //nolint:gosec // This is intentionally running a subprocess + cmd.Env = append(cmd.Env, "TEST_DEFAULT_CONFIG_SYSTEMD=1") + + var stderr bytes.Buffer + cmd.Stderr = &stderr + + err := cmd.Run() + data := stderr.Bytes() + assert.NoError(t, err, "command failed with error: %s\nstderr: %s", err, data) + t.Logf("output:\n%s", data) + + logEntry := struct { + LogLevel string `json:"log.level"` + LogOrigin struct { + FileName string `json:"file.name"` + FileLine int `json:"file.line"` + } `json:"log.origin"` + Message string `json:"message"` + }{} + + assert.NoError(t, json.Unmarshal(data, &logEntry), "cannot unmarshal log entry from stderr") + + assert.Equal(t, "info", logEntry.LogLevel) + assert.Equal(t, "foo", logEntry.Message) + + _, fileName, _, _ := runtime.Caller(0) + expectedFileName := filepath.Base(fileName) + gotFileName := filepath.Base(logEntry.LogOrigin.FileName) + assert.Equal(t, expectedFileName, gotFileName) + + return + } + + // This is running in a separate process. + cfg := logp.DefaultConfig(logp.SystemdEnvironment) + assert.NoError(t, logp.Configure(cfg)) + logger := logp.L() + defer logger.Close() + logger.Info("foo") +} + func TestWith(t *testing.T) { tempDir := t.TempDir()