github.com/m3db/m3@v1.5.0/src/x/log/config.go (about)

     1  // Copyright (c) 2021 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package log
    22  
    23  import (
    24  	"fmt"
    25  
    26  	"go.uber.org/zap"
    27  	"go.uber.org/zap/zapcore"
    28  )
    29  
    30  // Configuration defines configuration for logging.
    31  type Configuration struct {
    32  	File          string                 `json:"file" yaml:"file"`
    33  	Level         string                 `json:"level" yaml:"level"`
    34  	Fields        map[string]interface{} `json:"fields" yaml:"fields"`
    35  	EncoderConfig encoderConfig          `json:"encoderConfig,omitempty" yaml:"encoderConfig,omitempty"`
    36  }
    37  
    38  type encoderConfig struct {
    39  	MessageKey     string `json:"messageKey" yaml:"messageKey"`
    40  	LevelKey       string `json:"levelKey" yaml:"levelKey"`
    41  	TimeKey        string `json:"timeKey" yaml:"timeKey"`
    42  	NameKey        string `json:"nameKey" yaml:"nameKey"`
    43  	CallerKey      string `json:"callerKey" yaml:"callerKey"`
    44  	FunctionKey    string `json:"functionKey" yaml:"functionKey"`
    45  	StacktraceKey  string `json:"stacktraceKey" yaml:"stacktraceKey"`
    46  	LineEnding     string `json:"lineEnding" yaml:"lineEnding"`
    47  	EncodeLevel    string `json:"levelEncoder" yaml:"levelEncoder"`
    48  	EncodeTime     string `json:"timeEncoder" yaml:"timeEncoder"`
    49  	EncodeDuration string `json:"durationEncoder" yaml:"durationEncoder"`
    50  	EncodeCaller   string `json:"callerEncoder" yaml:"callerEncoder"`
    51  	EncodeName     string `json:"nameEncoder" yaml:"nameEncoder,omitempty"`
    52  }
    53  
    54  // BuildLogger builds a new Logger based on the configuration.
    55  func (cfg Configuration) BuildLogger() (*zap.Logger, error) {
    56  	zc := zap.Config{
    57  		Level:             zap.NewAtomicLevelAt(zap.InfoLevel),
    58  		Development:       false,
    59  		DisableCaller:     true,
    60  		DisableStacktrace: true,
    61  		Sampling: &zap.SamplingConfig{
    62  			Initial:    100,
    63  			Thereafter: 100,
    64  		},
    65  		Encoding:         "json",
    66  		EncoderConfig:    cfg.newEncoderConfig(),
    67  		OutputPaths:      []string{"stdout"},
    68  		ErrorOutputPaths: []string{"stdout"},
    69  		InitialFields:    cfg.Fields,
    70  	}
    71  
    72  	if cfg.File != "" {
    73  		zc.OutputPaths = append(zc.OutputPaths, cfg.File)
    74  		zc.ErrorOutputPaths = append(zc.ErrorOutputPaths, cfg.File)
    75  	}
    76  
    77  	if len(cfg.Level) != 0 {
    78  		var parsedLevel zap.AtomicLevel
    79  		if err := parsedLevel.UnmarshalText([]byte(cfg.Level)); err != nil {
    80  			return nil, fmt.Errorf("unable to parse log level %s: %v", cfg.Level, err)
    81  		}
    82  		zc.Level = parsedLevel
    83  	}
    84  
    85  	return zc.Build()
    86  }
    87  
    88  func (cfg Configuration) newEncoderConfig() zapcore.EncoderConfig {
    89  	ec := zap.NewProductionEncoderConfig()
    90  
    91  	if cfg.EncoderConfig.MessageKey != "" {
    92  		ec.MessageKey = cfg.EncoderConfig.MessageKey
    93  	}
    94  
    95  	if cfg.EncoderConfig.LevelKey != "" {
    96  		ec.LevelKey = cfg.EncoderConfig.LevelKey
    97  	}
    98  
    99  	if cfg.EncoderConfig.TimeKey != "" {
   100  		ec.TimeKey = cfg.EncoderConfig.TimeKey
   101  	}
   102  
   103  	if cfg.EncoderConfig.NameKey != "" {
   104  		ec.NameKey = cfg.EncoderConfig.NameKey
   105  	}
   106  
   107  	if cfg.EncoderConfig.CallerKey != "" {
   108  		ec.CallerKey = cfg.EncoderConfig.CallerKey
   109  	}
   110  
   111  	if cfg.EncoderConfig.FunctionKey != "" {
   112  		ec.FunctionKey = cfg.EncoderConfig.FunctionKey
   113  	}
   114  
   115  	if cfg.EncoderConfig.StacktraceKey != "" {
   116  		ec.StacktraceKey = cfg.EncoderConfig.StacktraceKey
   117  	}
   118  
   119  	if cfg.EncoderConfig.LineEnding != "" {
   120  		ec.LineEnding = cfg.EncoderConfig.LineEnding
   121  	}
   122  
   123  	if cfg.EncoderConfig.EncodeLevel != "" {
   124  		var levelEncoder zapcore.LevelEncoder
   125  		_ = levelEncoder.UnmarshalText([]byte(cfg.EncoderConfig.EncodeLevel))
   126  		ec.EncodeLevel = levelEncoder
   127  	}
   128  
   129  	if cfg.EncoderConfig.EncodeTime != "" {
   130  		var timeEncoder zapcore.TimeEncoder
   131  		_ = timeEncoder.UnmarshalText([]byte(cfg.EncoderConfig.EncodeTime))
   132  		ec.EncodeTime = timeEncoder
   133  	}
   134  
   135  	if cfg.EncoderConfig.EncodeDuration != "" {
   136  		var durationEncoder zapcore.DurationEncoder
   137  		_ = durationEncoder.UnmarshalText([]byte(cfg.EncoderConfig.EncodeDuration))
   138  		ec.EncodeDuration = durationEncoder
   139  	}
   140  
   141  	if cfg.EncoderConfig.EncodeCaller != "" {
   142  		var callerEncoder zapcore.CallerEncoder
   143  		_ = callerEncoder.UnmarshalText([]byte(cfg.EncoderConfig.EncodeCaller))
   144  		ec.EncodeCaller = callerEncoder
   145  	}
   146  
   147  	if cfg.EncoderConfig.EncodeName != "" {
   148  		var nameEncoder zapcore.NameEncoder
   149  		_ = nameEncoder.UnmarshalText([]byte(cfg.EncoderConfig.EncodeName))
   150  		ec.EncodeName = nameEncoder
   151  	}
   152  
   153  	return ec
   154  }