logger.go 3.0 KB

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