logger.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package logging
  2. import (
  3. "context"
  4. "io"
  5. "log/slog"
  6. "slices"
  7. "github.com/kujtimiihoxha/termai/internal/pubsub"
  8. "golang.org/x/exp/maps"
  9. )
  10. const DefaultLevel = "info"
  11. const (
  12. persistKeyArg = "$persist"
  13. PersistTimeArg = "$persist_time"
  14. )
  15. var levels = map[string]slog.Level{
  16. "debug": slog.LevelDebug,
  17. DefaultLevel: slog.LevelInfo,
  18. "warn": slog.LevelWarn,
  19. "error": slog.LevelError,
  20. }
  21. func ValidLevels() []string {
  22. keys := maps.Keys(levels)
  23. slices.SortFunc(keys, func(a, b string) int {
  24. if a == DefaultLevel {
  25. return -1
  26. }
  27. if b == DefaultLevel {
  28. return 1
  29. }
  30. if a < b {
  31. return -1
  32. }
  33. return 1
  34. })
  35. return keys
  36. }
  37. func NewLogger(opts Options) Interface {
  38. logger := &Logger{}
  39. broker := pubsub.NewBroker[LogMessage]()
  40. writer := &writer{
  41. messages: []LogMessage{},
  42. Broker: broker,
  43. }
  44. handler := slog.NewTextHandler(
  45. io.MultiWriter(writer),
  46. &slog.HandlerOptions{
  47. Level: slog.Level(levels[opts.Level]),
  48. },
  49. )
  50. logger.logger = slog.New(handler)
  51. logger.writer = writer
  52. return logger
  53. }
  54. type Options struct {
  55. Level string
  56. }
  57. type Logger struct {
  58. logger *slog.Logger
  59. writer *writer
  60. }
  61. func (l *Logger) SetLevel(level string) {
  62. if _, ok := levels[level]; !ok {
  63. level = DefaultLevel
  64. }
  65. handler := slog.NewTextHandler(
  66. io.MultiWriter(l.writer),
  67. &slog.HandlerOptions{
  68. Level: levels[level],
  69. },
  70. )
  71. l.logger = slog.New(handler)
  72. }
  73. // PersistDebug implements Interface.
  74. func (l *Logger) PersistDebug(msg string, args ...any) {
  75. args = append(args, persistKeyArg, true)
  76. l.Debug(msg, args...)
  77. }
  78. // PersistError implements Interface.
  79. func (l *Logger) PersistError(msg string, args ...any) {
  80. args = append(args, persistKeyArg, true)
  81. l.Error(msg, args...)
  82. }
  83. // PersistInfo implements Interface.
  84. func (l *Logger) PersistInfo(msg string, args ...any) {
  85. args = append(args, persistKeyArg, true)
  86. l.Info(msg, args...)
  87. }
  88. // PersistWarn implements Interface.
  89. func (l *Logger) PersistWarn(msg string, args ...any) {
  90. args = append(args, persistKeyArg, true)
  91. l.Warn(msg, args...)
  92. }
  93. func (l *Logger) Debug(msg string, args ...any) {
  94. l.logger.Debug(msg, args...)
  95. }
  96. func (l *Logger) Info(msg string, args ...any) {
  97. l.logger.Info(msg, args...)
  98. }
  99. func (l *Logger) Warn(msg string, args ...any) {
  100. l.logger.Warn(msg, args...)
  101. }
  102. func (l *Logger) Error(msg string, args ...any) {
  103. l.logger.Error(msg, args...)
  104. }
  105. func (l *Logger) List() []LogMessage {
  106. return l.writer.messages
  107. }
  108. func (l *Logger) Get(id string) (LogMessage, error) {
  109. for _, msg := range l.writer.messages {
  110. if msg.ID == id {
  111. return msg, nil
  112. }
  113. }
  114. return LogMessage{}, io.EOF
  115. }
  116. func (l *Logger) Subscribe(ctx context.Context) <-chan pubsub.Event[LogMessage] {
  117. return l.writer.Subscribe(ctx)
  118. }