mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-11 09:52:14 +01:00
feat(logging): add a new flag for preprending a prefix to each field in the logs (close #659)
This commit is contained in:
@@ -32,8 +32,9 @@ const (
|
||||
|
||||
// Logging is a module which implements the gotenberg.LoggerProvider interface.
|
||||
type Logging struct {
|
||||
level string
|
||||
format string
|
||||
level string
|
||||
format string
|
||||
fieldsPrefix string
|
||||
}
|
||||
|
||||
// Descriptor returns a Logging's module descriptor.
|
||||
@@ -42,8 +43,9 @@ func (Logging) Descriptor() gotenberg.ModuleDescriptor {
|
||||
ID: "logging",
|
||||
FlagSet: func() *flag.FlagSet {
|
||||
fs := flag.NewFlagSet("logging", flag.ExitOnError)
|
||||
fs.String("log-level", infoLoggingLevel, fmt.Sprintf("Set the log level - %s, %s, %s, or %s", errorLoggingLevel, warnLoggingLevel, infoLoggingLevel, debugLoggingLevel))
|
||||
fs.String("log-format", autoLoggingFormat, fmt.Sprintf("Set log format - %s, %s, or %s", autoLoggingFormat, jsonLoggingFormat, textLoggingFormat))
|
||||
fs.String("log-level", infoLoggingLevel, fmt.Sprintf("Choose the level of logging detail. Options include %s, %s, %s, or %s", errorLoggingLevel, warnLoggingLevel, infoLoggingLevel, debugLoggingLevel))
|
||||
fs.String("log-format", autoLoggingFormat, fmt.Sprintf("Specify the format of logging. Options include %s, %s, or %s", autoLoggingFormat, jsonLoggingFormat, textLoggingFormat))
|
||||
fs.String("log-fields-prefix", "", "Prepend a specified prefix to each field in the logs")
|
||||
|
||||
return fs
|
||||
}(),
|
||||
@@ -57,6 +59,7 @@ func (log *Logging) Provision(ctx *gotenberg.Context) error {
|
||||
|
||||
log.level = flags.MustString("log-level")
|
||||
log.format = flags.MustString("log-format")
|
||||
log.fieldsPrefix = flags.MustString("log-fields-prefix")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -101,29 +104,64 @@ func (log Logging) Logger(mod gotenberg.Module) (*zap.Logger, error) {
|
||||
return nil, fmt.Errorf("get log encoder: %w", err)
|
||||
}
|
||||
|
||||
core := zapcore.NewCore(encoder, os.Stderr, lvl)
|
||||
logger = zap.New(core)
|
||||
|
||||
// nolint
|
||||
defer logger.Sync()
|
||||
logger = zap.New(customCore{
|
||||
Core: zapcore.NewCore(encoder, os.Stderr, lvl),
|
||||
fieldsPrefix: log.fieldsPrefix,
|
||||
})
|
||||
}
|
||||
|
||||
return logger.Named(mod.Descriptor().ID), nil
|
||||
}
|
||||
|
||||
func newLogLevel(level string) (zapcore.Level, error) {
|
||||
switch level {
|
||||
case errorLoggingLevel:
|
||||
return zap.ErrorLevel, nil
|
||||
case warnLoggingLevel:
|
||||
return zap.WarnLevel, nil
|
||||
case infoLoggingLevel:
|
||||
return zap.InfoLevel, nil
|
||||
case debugLoggingLevel:
|
||||
return zap.DebugLevel, nil
|
||||
default:
|
||||
return -2, fmt.Errorf("%s is not a recognized log level", level)
|
||||
// See https://github.com/gotenberg/gotenberg/issues/659.
|
||||
type customCore struct {
|
||||
zapcore.Core
|
||||
fieldsPrefix string
|
||||
}
|
||||
|
||||
func (c customCore) With(fields []zapcore.Field) zapcore.Core {
|
||||
if c.fieldsPrefix != "" {
|
||||
for i := range fields {
|
||||
fields[i].Key = c.fieldsPrefix + "_" + fields[i].Key
|
||||
}
|
||||
}
|
||||
|
||||
return customCore{
|
||||
Core: c.Core.With(fields),
|
||||
fieldsPrefix: c.fieldsPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
func (c customCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
|
||||
// This is a copy from the zapcore.ioCore implementation. Indeed, by doing
|
||||
// so, we are able to prefix the fields given to the logger methods like
|
||||
// Debug, Info, Warn, Error, etc.
|
||||
if c.Enabled(ent.Level) {
|
||||
return ce.AddCore(ent, c)
|
||||
}
|
||||
|
||||
return ce
|
||||
}
|
||||
|
||||
func (c customCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
|
||||
if c.fieldsPrefix != "" {
|
||||
for i := range fields {
|
||||
fields[i].Key = c.fieldsPrefix + "_" + fields[i].Key
|
||||
}
|
||||
}
|
||||
|
||||
return c.Core.Write(entry, fields)
|
||||
}
|
||||
|
||||
func newLogLevel(level string) (zapcore.Level, error) {
|
||||
lvl := zapcore.InvalidLevel
|
||||
|
||||
err := lvl.UnmarshalText([]byte(level))
|
||||
if err != nil {
|
||||
return lvl, fmt.Errorf("%q is not a recognized log level: %w", level, err)
|
||||
}
|
||||
|
||||
return lvl, nil
|
||||
}
|
||||
|
||||
func newLogEncoder(format string) (zapcore.Encoder, error) {
|
||||
@@ -158,6 +196,7 @@ func newLogEncoder(format string) (zapcore.Encoder, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton so that we instantiate our logger only once.
|
||||
var logger *zap.Logger = nil
|
||||
|
||||
// Interface guards.
|
||||
@@ -166,4 +205,5 @@ var (
|
||||
_ gotenberg.Provisioner = (*Logging)(nil)
|
||||
_ gotenberg.Validator = (*Logging)(nil)
|
||||
_ gotenberg.LoggerProvider = (*Logging)(nil)
|
||||
_ zapcore.Core = (*customCore)(nil)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user