deploy.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package zap
  2. import (
  3. "github.com/ydb-platform/ydb/library/go/core/log"
  4. "go.uber.org/zap"
  5. "go.uber.org/zap/zapcore"
  6. )
  7. // NewDeployEncoderConfig returns an opinionated EncoderConfig for
  8. // deploy environment.
  9. func NewDeployEncoderConfig() zapcore.EncoderConfig {
  10. return zapcore.EncoderConfig{
  11. MessageKey: "msg",
  12. LevelKey: "levelStr",
  13. StacktraceKey: "stackTrace",
  14. TimeKey: "@timestamp",
  15. CallerKey: "",
  16. NameKey: "loggerName",
  17. EncodeLevel: zapcore.CapitalLevelEncoder,
  18. EncodeTime: zapcore.ISO8601TimeEncoder,
  19. EncodeDuration: zapcore.StringDurationEncoder,
  20. EncodeCaller: zapcore.ShortCallerEncoder,
  21. }
  22. }
  23. type cfgOption func(cfg *zap.Config)
  24. // WithSampling sets sampling settings initial and thereafter
  25. func WithSampling(initial int, thereafter int) cfgOption {
  26. return cfgOption(func(cfg *zap.Config) {
  27. cfg.Sampling = &zap.SamplingConfig{
  28. Initial: initial,
  29. Thereafter: thereafter,
  30. }
  31. })
  32. }
  33. // SetOutputPaths sets OutputPaths (stdout by default)
  34. func SetOutputPaths(paths []string) cfgOption {
  35. return cfgOption(func(cfg *zap.Config) {
  36. cfg.OutputPaths = paths
  37. })
  38. }
  39. // WithDevelopment sets Development option of zap.Config
  40. func WithDevelopment(enabled bool) cfgOption {
  41. return cfgOption(func(cfg *zap.Config) {
  42. cfg.Development = enabled
  43. })
  44. }
  45. // WithLevel sets level of logging
  46. func WithLevel(level log.Level) cfgOption {
  47. return cfgOption(func(cfg *zap.Config) {
  48. cfg.Level = zap.NewAtomicLevelAt(ZapifyLevel(level))
  49. })
  50. }
  51. // NewDeployConfig returns default configuration (with no sampling).
  52. // Not recommended for production use.
  53. func NewDeployConfig(opts ...cfgOption) zap.Config {
  54. cfg := zap.Config{
  55. Level: zap.NewAtomicLevelAt(zap.DebugLevel),
  56. Encoding: "json",
  57. OutputPaths: []string{"stdout"},
  58. ErrorOutputPaths: []string{"stderr"},
  59. EncoderConfig: NewDeployEncoderConfig(),
  60. }
  61. for _, opt := range opts {
  62. opt(&cfg)
  63. }
  64. return cfg
  65. }
  66. // NewCustomDeployLogger constructs new logger by config cfg
  67. func NewCustomDeployLogger(cfg zap.Config, opts ...zap.Option) (*Logger, error) {
  68. zl, err := cfg.Build(opts...)
  69. if err != nil {
  70. return nil, err
  71. }
  72. return &Logger{
  73. L: addDeployContext(zl).(*zap.Logger),
  74. }, nil
  75. }
  76. // NewDeployLogger constructs fully-fledged Deploy compatible logger
  77. // based on predefined config. See https://deploy.yandex-team.ru/docs/concepts/pod/sidecars/logs/logs#format
  78. // for more information
  79. func NewDeployLogger(level log.Level, opts ...zap.Option) (*Logger, error) {
  80. return NewCustomDeployLogger(
  81. NewDeployConfig(
  82. WithLevel(level),
  83. ),
  84. opts...,
  85. )
  86. }
  87. // NewProductionDeployConfig returns configuration, suitable for production use.
  88. //
  89. // It uses a JSON encoder, writes to standard error, and enables sampling.
  90. // Stacktraces are automatically included on logs of ErrorLevel and above.
  91. func NewProductionDeployConfig() zap.Config {
  92. return NewDeployConfig(
  93. WithDevelopment(false),
  94. WithSampling(100, 100),
  95. )
  96. }
  97. // Same as NewDeployLogger, but with sampling
  98. func NewProductionDeployLogger(level log.Level, opts ...zap.Option) (*Logger, error) {
  99. return NewCustomDeployLogger(
  100. NewDeployConfig(
  101. WithLevel(level),
  102. WithDevelopment(false),
  103. WithSampling(100, 100),
  104. ),
  105. opts...,
  106. )
  107. }
  108. func addDeployContext(i interface{}) interface{} {
  109. switch c := i.(type) {
  110. case *zap.Logger:
  111. return c.With(zap.Namespace("@fields"))
  112. case zapcore.Core:
  113. return c.With([]zapcore.Field{zap.Namespace("@fields")})
  114. }
  115. return i
  116. }