logger.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. var levels = map[string]slog.Level{
  12. "debug": slog.LevelDebug,
  13. DefaultLevel: slog.LevelInfo,
  14. "warn": slog.LevelWarn,
  15. "error": slog.LevelError,
  16. }
  17. func ValidLevels() []string {
  18. keys := maps.Keys(levels)
  19. slices.SortFunc(keys, func(a, b string) int {
  20. if a == DefaultLevel {
  21. return -1
  22. }
  23. if b == DefaultLevel {
  24. return 1
  25. }
  26. if a < b {
  27. return -1
  28. }
  29. return 1
  30. })
  31. return keys
  32. }
  33. func NewLogger(opts Options) *Logger {
  34. logger := &Logger{}
  35. broker := pubsub.NewBroker[Message]()
  36. writer := &writer{
  37. messages: []Message{},
  38. Broker: broker,
  39. }
  40. handler := slog.NewTextHandler(
  41. io.MultiWriter(append(opts.AdditionalWriters, writer)...),
  42. &slog.HandlerOptions{
  43. Level: slog.Level(levels[opts.Level]),
  44. },
  45. )
  46. logger.logger = slog.New(handler)
  47. logger.writer = writer
  48. return logger
  49. }
  50. type Options struct {
  51. Level string
  52. AdditionalWriters []io.Writer
  53. }
  54. type Logger struct {
  55. logger *slog.Logger
  56. writer *writer
  57. }
  58. func (l *Logger) Debug(msg string, args ...any) {
  59. l.logger.Debug(msg, args...)
  60. }
  61. func (l *Logger) Info(msg string, args ...any) {
  62. l.logger.Info(msg, args...)
  63. }
  64. func (l *Logger) Warn(msg string, args ...any) {
  65. l.logger.Warn(msg, args...)
  66. }
  67. func (l *Logger) Error(msg string, args ...any) {
  68. l.logger.Error(msg, args...)
  69. }
  70. func (l *Logger) List() []Message {
  71. return l.writer.messages
  72. }
  73. func (l *Logger) Get(id string) (Message, error) {
  74. for _, msg := range l.writer.messages {
  75. if msg.ID == id {
  76. return msg, nil
  77. }
  78. }
  79. return Message{}, io.EOF
  80. }
  81. func (l *Logger) Subscribe(ctx context.Context) <-chan pubsub.Event[Message] {
  82. return l.writer.Subscribe(ctx)
  83. }