zap.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. package logutil
  15. import (
  16. "sort"
  17. "time"
  18. "go.uber.org/zap"
  19. "go.uber.org/zap/zapcore"
  20. )
  21. // CreateDefaultZapLogger creates a logger with default zap configuration
  22. func CreateDefaultZapLogger(level zapcore.Level) (*zap.Logger, error) {
  23. lcfg := DefaultZapLoggerConfig
  24. lcfg.Level = zap.NewAtomicLevelAt(level)
  25. c, err := lcfg.Build()
  26. if err != nil {
  27. return nil, err
  28. }
  29. return c, nil
  30. }
  31. // DefaultZapLoggerConfig defines default zap logger configuration.
  32. var DefaultZapLoggerConfig = zap.Config{
  33. Level: zap.NewAtomicLevelAt(ConvertToZapLevel(DefaultLogLevel)),
  34. Development: false,
  35. Sampling: &zap.SamplingConfig{
  36. Initial: 100,
  37. Thereafter: 100,
  38. },
  39. Encoding: "json",
  40. // copied from "zap.NewProductionEncoderConfig" with some updates
  41. EncoderConfig: zapcore.EncoderConfig{
  42. TimeKey: "ts",
  43. LevelKey: "level",
  44. NameKey: "logger",
  45. CallerKey: "caller",
  46. MessageKey: "msg",
  47. StacktraceKey: "stacktrace",
  48. LineEnding: zapcore.DefaultLineEnding,
  49. EncodeLevel: zapcore.LowercaseLevelEncoder,
  50. // Custom EncodeTime function to ensure we match format and precision of historic capnslog timestamps
  51. EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
  52. enc.AppendString(t.Format("2006-01-02T15:04:05.999999Z0700"))
  53. },
  54. EncodeDuration: zapcore.StringDurationEncoder,
  55. EncodeCaller: zapcore.ShortCallerEncoder,
  56. },
  57. // Use "/dev/null" to discard all
  58. OutputPaths: []string{"stderr"},
  59. ErrorOutputPaths: []string{"stderr"},
  60. }
  61. // MergeOutputPaths merges logging output paths, resolving conflicts.
  62. func MergeOutputPaths(cfg zap.Config) zap.Config {
  63. outputs := make(map[string]struct{})
  64. for _, v := range cfg.OutputPaths {
  65. outputs[v] = struct{}{}
  66. }
  67. outputSlice := make([]string, 0)
  68. if _, ok := outputs["/dev/null"]; ok {
  69. // "/dev/null" to discard all
  70. outputSlice = []string{"/dev/null"}
  71. } else {
  72. for k := range outputs {
  73. outputSlice = append(outputSlice, k)
  74. }
  75. }
  76. cfg.OutputPaths = outputSlice
  77. sort.Strings(cfg.OutputPaths)
  78. errOutputs := make(map[string]struct{})
  79. for _, v := range cfg.ErrorOutputPaths {
  80. errOutputs[v] = struct{}{}
  81. }
  82. errOutputSlice := make([]string, 0)
  83. if _, ok := errOutputs["/dev/null"]; ok {
  84. // "/dev/null" to discard all
  85. errOutputSlice = []string{"/dev/null"}
  86. } else {
  87. for k := range errOutputs {
  88. errOutputSlice = append(errOutputSlice, k)
  89. }
  90. }
  91. cfg.ErrorOutputPaths = errOutputSlice
  92. sort.Strings(cfg.ErrorOutputPaths)
  93. return cfg
  94. }