logger.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package logger
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "log/slog"
  7. "os"
  8. "sync"
  9. )
  10. type CtxAttrKey struct{}
  11. var (
  12. once sync.Once
  13. ctxAttrMu sync.RWMutex
  14. logger *Logger
  15. )
  16. type Logger struct {
  17. config Config
  18. logFile *os.File
  19. stdoutLogger *slog.Logger
  20. fileLogger *slog.Logger
  21. emailLogger *slog.Logger
  22. }
  23. func Init(c Config) error {
  24. var err error
  25. once.Do(func() {
  26. logger = &Logger{config: c}
  27. if c.stdoutLogEnabled {
  28. logger.stdoutLogger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
  29. AddSource: c.stdoutLogAddSource,
  30. Level: c.stdoutLogLevel,
  31. }))
  32. }
  33. if c.fileLogEnabled {
  34. logger.logFile, err = os.OpenFile(c.filepath, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0644)
  35. if err != nil {
  36. return
  37. }
  38. logger.fileLogger = slog.New(slog.NewJSONHandler(logger.logFile, &slog.HandlerOptions{
  39. AddSource: c.fileLogAddSource,
  40. Level: c.fileLogLevel,
  41. }))
  42. }
  43. if c.emailLogEnabled {
  44. if c.smtpClient == nil {
  45. err = errors.New("empty SMTP client")
  46. return
  47. }
  48. ew, ewErr := NewEmailWriter(c.smtpClient, c.emailRecipient, c.emailSubject)
  49. if ewErr != nil {
  50. err = ewErr
  51. return
  52. }
  53. logger.emailLogger = slog.New(slog.NewJSONHandler(ew, &slog.HandlerOptions{
  54. AddSource: c.emailLogAddSource,
  55. Level: c.emailLogLevel,
  56. }))
  57. }
  58. })
  59. return err
  60. }
  61. func Default() *Logger {
  62. if logger == nil {
  63. logger = &Logger{}
  64. }
  65. return logger
  66. }
  67. func ErrorKV(ctx context.Context, msg string, args ...any) {
  68. log(ctx, slog.LevelError, msg, args...)
  69. }
  70. func WarnKV(ctx context.Context, msg string, args ...any) {
  71. log(ctx, slog.LevelWarn, msg, args...)
  72. }
  73. func InfoKV(ctx context.Context, msg string, args ...any) {
  74. log(ctx, slog.LevelInfo, msg, args...)
  75. }
  76. func DebugKV(ctx context.Context, msg string, args ...any) {
  77. log(ctx, slog.LevelDebug, msg, args...)
  78. }
  79. func Errorf(ctx context.Context, format string, args ...any) {
  80. log(ctx, slog.LevelError, fmt.Sprintf(format, args...))
  81. }
  82. func Warnf(ctx context.Context, format string, args ...any) {
  83. log(ctx, slog.LevelWarn, fmt.Sprintf(format, args...))
  84. }
  85. func Infof(ctx context.Context, format string, args ...any) {
  86. log(ctx, slog.LevelInfo, fmt.Sprintf(format, args...))
  87. }
  88. func Debugf(ctx context.Context, format string, args ...any) {
  89. log(ctx, slog.LevelDebug, fmt.Sprintf(format, args...))
  90. }
  91. func Error(ctx context.Context, msg string) {
  92. log(ctx, slog.LevelError, msg)
  93. }
  94. func Warn(ctx context.Context, msg string) {
  95. log(ctx, slog.LevelWarn, msg)
  96. }
  97. func Info(ctx context.Context, msg string) {
  98. log(ctx, slog.LevelInfo, msg)
  99. }
  100. func Debug(ctx context.Context, msg string) {
  101. log(ctx, slog.LevelDebug, msg)
  102. }
  103. func log(ctx context.Context, level slog.Level, msg string, args ...any) {
  104. if Default().stdoutLogger != nil {
  105. Default().stdoutLogger.Log(ctx, level, msg, append(args, AttrFromCtx(ctx)...)...)
  106. }
  107. if Default().fileLogger != nil {
  108. Default().fileLogger.Log(ctx, level, msg, append(args, AttrFromCtx(ctx)...)...)
  109. }
  110. if Default().emailLogger != nil {
  111. Default().emailLogger.Log(ctx, level, msg, append(args, AttrFromCtx(ctx)...)...)
  112. }
  113. }
  114. func Close() error {
  115. if Default().logFile != nil {
  116. if err := Default().logFile.Close(); err != nil {
  117. return err
  118. }
  119. }
  120. return nil
  121. }