writer.go

 1package logging
 2
 3import (
 4	"bytes"
 5	"fmt"
 6	"time"
 7
 8	"github.com/go-logfmt/logfmt"
 9	"github.com/kujtimiihoxha/termai/internal/pubsub"
10)
11
12type writer struct {
13	messages []LogMessage
14	*pubsub.Broker[LogMessage]
15}
16
17func (w *writer) Write(p []byte) (int, error) {
18	d := logfmt.NewDecoder(bytes.NewReader(p))
19	for d.ScanRecord() {
20		msg := LogMessage{
21			ID:   fmt.Sprintf("%d", time.Now().UnixNano()),
22			Time: time.Now(),
23		}
24		for d.ScanKeyval() {
25			switch string(d.Key()) {
26			case "time":
27				parsed, err := time.Parse(time.RFC3339, string(d.Value()))
28				if err != nil {
29					return 0, fmt.Errorf("parsing time: %w", err)
30				}
31				msg.Time = parsed
32			case "level":
33				msg.Level = string(d.Value())
34			case "msg":
35				msg.Message = string(d.Value())
36			default:
37				if string(d.Key()) == persistKeyArg {
38					msg.Persist = true
39				} else if string(d.Key()) == PersistTimeArg {
40					parsed, err := time.ParseDuration(string(d.Value()))
41					if err != nil {
42						continue
43					}
44					msg.PersistTime = parsed
45				} else {
46					msg.Attributes = append(msg.Attributes, Attr{
47						Key:   string(d.Key()),
48						Value: string(d.Value()),
49					})
50				}
51			}
52		}
53		w.messages = append(w.messages, msg)
54		w.Publish(pubsub.CreatedEvent, msg)
55	}
56	if d.Err() != nil {
57		return 0, d.Err()
58	}
59	return len(p), nil
60}