Skip to content

Commit f760eb2

Browse files
authored
Option to output L3AFd logs as a JSON object (#601)
* Adding an option to disable pretty log print and format logs as an JSON object Signed-off-by: Jay Sheth <[email protected]>
1 parent 6f74cb5 commit f760eb2

File tree

4 files changed

+67
-53
lines changed

4 files changed

+67
-53
lines changed

config/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type Config struct {
3737
FileLogMaxSize int
3838
FileLogMaxBackups int
3939
FileLogMaxAge int
40+
JSONFormatLogs bool
4041

4142
// stats
4243
// Prometheus endpoint for pull/scrape the metrics.
@@ -120,6 +121,7 @@ func ReadConfig(configPath string) (*Config, error) {
120121
FileLogMaxSize: LoadOptionalConfigInt(confReader, "l3afd", "file-log-max-size", 100),
121122
FileLogMaxBackups: LoadOptionalConfigInt(confReader, "l3afd", "file-log-max-backups", 20),
122123
FileLogMaxAge: LoadOptionalConfigInt(confReader, "l3afd", "file-log-max-age", 60),
124+
JSONFormatLogs: LoadOptionalConfigBool(confReader, "l3afd", "json-format-logs", false),
123125
EBPFRepoURL: LoadConfigString(confReader, "ebpf-repo", "url"),
124126
HttpClientTimeout: LoadOptionalConfigDuration(confReader, "l3afd", "http-client-timeout", 30*time.Second),
125127
MaxEBPFReStartCount: LoadOptionalConfigInt(confReader, "l3afd", "max-ebpf-restart-count", 3),

config/l3afd.cfg

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ bpf-chaining-enabled: true
1414
swagger-api-enabled: true
1515
environment: DEV
1616
BpfMapDefaultPath: /sys/fs/bpf
17-
#FileLogLocation:
18-
#FileLogMaxSize: 100
19-
#FileLogMaxBackups: 20
20-
#FileLogMaxAge: 60
17+
#file-log-location: /var/log/l3afd.log
18+
#file-log-max-size: 100
19+
#file-log-max-backups: 20
20+
#file-log-max-age: 60
21+
#json-format-logs: true
2122

2223
[ebpf-repo]
2324
url: file:///srv/l3afd

docs/configdoc.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,26 @@ environment: PROD
2626

2727
## [l3afd]
2828

29-
| FieldName | Default | Description | Required |
30-
| ------------- |------------------------| --------------- | --------------- |
31-
|pid-file| `"/var/l3afd/l3afd.pid"` | The path to the l3afd.pid file which contains process id of L3afd | Yes |
32-
|datacenter| `"dc"` | Name of Datacenter| Yes |
33-
|bpf-dir| `"/dev/shm"` | Absolute Path where eBPF packages are to be extracted | Yes |
34-
|bpf-log-dir| `""` | Absolute Path for log files, which is passed to applications on the command line. L3afd does not store any logs itself.| No |
35-
|kernel-major-version| `"5"` |Major version of the kernel required to run eBPF programs (Linux Only) | No |
36-
|kernel-minor-version| `"1"` |Minor version of the kernel required to run eBPF programs (Linux Only)| No |
37-
|shutdown-timeout| `"1s"` |Maximum amount of time allowed for l3afd to gracefully stop. After shutdown-timeout, l3afd will exit even if it could not stop applications.| No |
38-
|http-client-timeout| `"10s"` |Maximum amount of time allowed to get HTTP response headers when fetching a package from a repository| No |
39-
|max-nf-restart-count| `"3"` |Maximum number of tries to restart eBPF applications if they are not running| No |
40-
|bpf-chaining-enabled| `"true"` |Boolean to set bpf-chaining. For more info about bpf chaining check [L3AF_KFaaS.pdf](https://github.com/l3af-project/l3af-arch/blob/main/L3AF_KFaaS.pdf)| Yes |
41-
|swagger-api-enabled| `"false"` |Whether the swagger API is enabled or not. For more info see [swagger.md](https://github.com/l3af-project/l3afd/blob/main/docs/swagger.md)| No |
42-
|environment| `"PROD"` |If set to anything other than "PROD", mTLS security will not be checked| Yes |
43-
|BpfMapDefaultPath| `"/sys/fs/bpf"` |The base pin path for eBPF maps| Yes |
44-
| file-log-location | `"/var/log/l3afd.log"` | Location of the log file | No |
45-
| file-log-max-size | `"100"` | Max size in megabytes for Log file rotation | No |
46-
| file-log-max-backups | `"20"` | Max size in megabytes for Log file rotation | No |
47-
| file-log-max-age | `"60"` | Max number of days to keep Log files | No |
29+
| FieldName | Default | Description | Required |
30+
| ------------- |--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| --------------- |
31+
|pid-file| `"/var/l3afd/l3afd.pid"` | The path to the l3afd.pid file which contains process id of L3afd | Yes |
32+
|datacenter| `"dc"` | Name of Datacenter | Yes |
33+
|bpf-dir| `"/dev/shm"` | Absolute Path where eBPF packages are to be extracted | Yes |
34+
|bpf-log-dir| `""` | Absolute Path for log files, which is passed to applications on the command line. L3afd does not store any logs itself. | No |
35+
|kernel-major-version| `"5"` | Major version of the kernel required to run eBPF programs (Linux Only) | No |
36+
|kernel-minor-version| `"1"` | Minor version of the kernel required to run eBPF programs (Linux Only) | No |
37+
|shutdown-timeout| `"1s"` | Maximum amount of time allowed for l3afd to gracefully stop. After shutdown-timeout, l3afd will exit even if it could not stop applications. | No |
38+
|http-client-timeout| `"10s"` | Maximum amount of time allowed to get HTTP response headers when fetching a package from a repository | No |
39+
|max-nf-restart-count| `"3"` | Maximum number of tries to restart eBPF applications if they are not running | No |
40+
|bpf-chaining-enabled| `"true"` | Boolean to set bpf-chaining. For more info about bpf chaining check [L3AF_KFaaS.pdf](https://github.com/l3af-project/l3af-arch/blob/main/L3AF_KFaaS.pdf) | Yes |
41+
|swagger-api-enabled| `"false"` | Whether the swagger API is enabled or not. For more info see [swagger.md](https://github.com/l3af-project/l3afd/blob/main/docs/swagger.md) | No |
42+
|environment| `"PROD"` | If set to anything other than "PROD", mTLS security will not be checked | Yes |
43+
|BpfMapDefaultPath| `"/sys/fs/bpf"` | The base pin path for eBPF maps | Yes |
44+
| file-log-location | `"/var/log/l3afd.log"` | Location of the log file | No |
45+
| file-log-max-size | `"100"` | Max size in megabytes for Log file rotation | No |
46+
| file-log-max-backups | `"20"` | Max size in megabytes for Log file rotation | No |
47+
| file-log-max-age | `"60"` | Max number of days to keep Log files | No |
48+
| json-format-logs | `"false"` | Logs to be printed as a JSON object | No |
4849

4950
## [ebpf-repo]
5051
| FieldName | Default | Description | Required |

main.go

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import (
1919
"sync"
2020
"time"
2121

22+
"gopkg.in/natefinch/lumberjack.v2"
23+
2224
"github.com/l3af-project/l3afd/v2/apis"
2325
"github.com/l3af-project/l3afd/v2/apis/handlers"
2426
"github.com/l3af-project/l3afd/v2/bpfprogs"
@@ -27,7 +29,6 @@ import (
2729
"github.com/l3af-project/l3afd/v2/pidfile"
2830
"github.com/l3af-project/l3afd/v2/restart"
2931
"github.com/l3af-project/l3afd/v2/stats"
30-
"gopkg.in/natefinch/lumberjack.v2"
3132

3233
"github.com/rs/zerolog"
3334
"github.com/rs/zerolog/log"
@@ -37,55 +38,65 @@ const daemonName = "l3afd"
3738

3839
var stateSockPath string
3940

40-
func setupLogging() {
41-
const logLevelEnvName = "L3AF_LOG_LEVEL"
42-
43-
// If this is removed, zerolog will do structured logging. For now,
44-
// we set zerolog to do human-readable logging just to keep the same
45-
// behavior as the closed-source logging package that we replaced with
46-
// zerolog.
47-
log.Logger = log.Output(zerolog.ConsoleWriter{
48-
Out: os.Stderr, TimeFormat: time.RFC3339Nano})
49-
50-
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
41+
func setupLogging(conf *config.Config) {
42+
// ConsoleWriter formats the logs for user-readability
43+
if conf.JSONFormatLogs {
44+
log.Logger = zerolog.New(os.Stderr).With().Timestamp().Logger()
45+
}
5146

52-
// Set the default
47+
// Set the default Log level
5348
zerolog.SetGlobalLevel(zerolog.InfoLevel)
49+
log.Info().Msgf("Log level set to %q", zerolog.InfoLevel)
5450

55-
logLevelStr := os.Getenv(logLevelEnvName)
56-
if logLevelStr == "" {
57-
return
51+
if logLevelStr := os.Getenv("L3AF_LOG_LEVEL"); logLevelStr != "" {
52+
if logLevel, err := zerolog.ParseLevel(logLevelStr); err != nil {
53+
log.Error().Err(err).Msg("Invalid environment-specified log level. Defaulting to INFO.")
54+
} else {
55+
zerolog.SetGlobalLevel(logLevel)
56+
log.Info().Msgf("Log level set to %q via environment variable", logLevel)
57+
}
5858
}
59-
logLevel, err := zerolog.ParseLevel(logLevelStr)
60-
if err != nil {
61-
log.Error().Err(err).Msg("Invalid L3AF_LOG_LEVEL")
59+
60+
if conf.FileLogLocation != "" {
61+
log.Info().Msgf("Saving logs to file: %s", conf.FileLogLocation)
62+
saveLogsToFile(conf)
6263
return
6364
}
64-
zerolog.SetGlobalLevel(logLevel)
65-
log.Debug().Msgf("Log level set to %q", logLevel)
65+
6666
}
6767

6868
func saveLogsToFile(conf *config.Config) {
69-
7069
logFileWithRotation := &lumberjack.Logger{
7170
Filename: conf.FileLogLocation,
7271
MaxSize: conf.FileLogMaxSize, // Max size in megabytes
7372
MaxBackups: conf.FileLogMaxBackups, // Max number of old log files to keep
7473
MaxAge: conf.FileLogMaxAge, // Max number of days to keep log files
7574
}
76-
multi := zerolog.MultiLevelWriter(os.Stdout, logFileWithRotation)
77-
log.Logger = log.Output(zerolog.ConsoleWriter{
78-
Out: multi, TimeFormat: time.RFC3339Nano})
75+
// Create a multi-writer for stdout and the file
76+
multiWriter := zerolog.MultiLevelWriter(os.Stdout, logFileWithRotation)
77+
78+
if conf.JSONFormatLogs {
79+
log.Logger = log.Output(zerolog.ConsoleWriter{
80+
Out: multiWriter})
81+
82+
} else {
83+
log.Logger = zerolog.New(multiWriter).With().Timestamp().Logger()
84+
}
7985
}
8086

8187
func main() {
8288
models.CloseForRestart = make(chan struct{})
8389
models.IsReadOnly = false
8490
models.CurrentWriteReq = 0
8591
models.StateLock = sync.Mutex{}
86-
setupLogging()
8792
ctx, cancel := context.WithCancel(context.Background())
8893
defer cancel()
94+
95+
//Default Logger (uses user-friendly colored log statements in RFC3339Nano (e.g., 2006-01-02T15:04:05.999999999Z07:00) format)
96+
zerolog.TimeFieldFormat = time.RFC3339Nano
97+
log.Logger = log.Output(zerolog.ConsoleWriter{
98+
Out: os.Stderr})
99+
89100
log.Info().Msgf("%s started.", daemonName)
90101

91102
var confPath string
@@ -97,10 +108,9 @@ func main() {
97108
if err != nil {
98109
log.Fatal().Err(err).Msgf("Unable to parse config %q", confPath)
99110
}
100-
if conf.FileLogLocation != "" {
101-
log.Info().Msgf("Saving logs to file: %s", conf.FileLogLocation)
102-
saveLogsToFile(conf)
103-
}
111+
112+
// Setup logging according to the configuration provided
113+
setupLogging(conf)
104114
populateVersions(conf)
105115
if err = pidfile.CheckPIDConflict(conf.PIDFilename); err != nil {
106116
if err = setupForRestartOuter(ctx, conf); err != nil {

0 commit comments

Comments
 (0)