...

Source file src/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go

Documentation: go.etcd.io/etcd/client/pkg/v3/logutil

     1  // Copyright 2019 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package logutil
    16  
    17  import (
    18  	"sort"
    19  	"time"
    20  
    21  	"go.uber.org/zap"
    22  	"go.uber.org/zap/zapcore"
    23  )
    24  
    25  // CreateDefaultZapLogger creates a logger with default zap configuration
    26  func CreateDefaultZapLogger(level zapcore.Level) (*zap.Logger, error) {
    27  	lcfg := DefaultZapLoggerConfig
    28  	lcfg.Level = zap.NewAtomicLevelAt(level)
    29  	c, err := lcfg.Build()
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	return c, nil
    34  }
    35  
    36  // DefaultZapLoggerConfig defines default zap logger configuration.
    37  var DefaultZapLoggerConfig = zap.Config{
    38  	Level: zap.NewAtomicLevelAt(ConvertToZapLevel(DefaultLogLevel)),
    39  
    40  	Development: false,
    41  	Sampling: &zap.SamplingConfig{
    42  		Initial:    100,
    43  		Thereafter: 100,
    44  	},
    45  
    46  	Encoding: "json",
    47  
    48  	// copied from "zap.NewProductionEncoderConfig" with some updates
    49  	EncoderConfig: zapcore.EncoderConfig{
    50  		TimeKey:       "ts",
    51  		LevelKey:      "level",
    52  		NameKey:       "logger",
    53  		CallerKey:     "caller",
    54  		MessageKey:    "msg",
    55  		StacktraceKey: "stacktrace",
    56  		LineEnding:    zapcore.DefaultLineEnding,
    57  		EncodeLevel:   zapcore.LowercaseLevelEncoder,
    58  
    59  		// Custom EncodeTime function to ensure we match format and precision of historic capnslog timestamps
    60  		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
    61  			enc.AppendString(t.Format("2006-01-02T15:04:05.999999Z0700"))
    62  		},
    63  
    64  		EncodeDuration: zapcore.StringDurationEncoder,
    65  		EncodeCaller:   zapcore.ShortCallerEncoder,
    66  	},
    67  
    68  	// Use "/dev/null" to discard all
    69  	OutputPaths:      []string{"stderr"},
    70  	ErrorOutputPaths: []string{"stderr"},
    71  }
    72  
    73  // MergeOutputPaths merges logging output paths, resolving conflicts.
    74  func MergeOutputPaths(cfg zap.Config) zap.Config {
    75  	outputs := make(map[string]struct{})
    76  	for _, v := range cfg.OutputPaths {
    77  		outputs[v] = struct{}{}
    78  	}
    79  	outputSlice := make([]string, 0)
    80  	if _, ok := outputs["/dev/null"]; ok {
    81  		// "/dev/null" to discard all
    82  		outputSlice = []string{"/dev/null"}
    83  	} else {
    84  		for k := range outputs {
    85  			outputSlice = append(outputSlice, k)
    86  		}
    87  	}
    88  	cfg.OutputPaths = outputSlice
    89  	sort.Strings(cfg.OutputPaths)
    90  
    91  	errOutputs := make(map[string]struct{})
    92  	for _, v := range cfg.ErrorOutputPaths {
    93  		errOutputs[v] = struct{}{}
    94  	}
    95  	errOutputSlice := make([]string, 0)
    96  	if _, ok := errOutputs["/dev/null"]; ok {
    97  		// "/dev/null" to discard all
    98  		errOutputSlice = []string{"/dev/null"}
    99  	} else {
   100  		for k := range errOutputs {
   101  			errOutputSlice = append(errOutputSlice, k)
   102  		}
   103  	}
   104  	cfg.ErrorOutputPaths = errOutputSlice
   105  	sort.Strings(cfg.ErrorOutputPaths)
   106  
   107  	return cfg
   108  }
   109  

View as plain text