blob: f04760ee859af1cebd4a70eb85ecf8947c592c6e [file] [log] [blame]
gio183e8342024-08-20 06:01:24 +04001package main
2
3import (
gioaa6e27a2025-06-29 23:17:54 +04004 "bytes"
gio183e8342024-08-20 06:01:24 +04005 "strings"
6 "sync"
gioaa6e27a2025-06-29 23:17:54 +04007 "time"
gio183e8342024-08-20 06:01:24 +04008)
9
gioaa6e27a2025-06-29 23:17:54 +040010type LogItem struct {
11 RunId string `json:"runId"`
12 TimestampMilli int64 `json:"timestampMilli"`
13 Commit string `json:"commit,omitempty"`
14 Contents []byte `json:"contents"`
gio183e8342024-08-20 06:01:24 +040015}
16
gioaa6e27a2025-06-29 23:17:54 +040017type Logger struct {
18 l sync.Mutex
19 runId string
20 commitHash string
21 items []LogItem
22 curr LogItem
23}
24
25func NewLogger(runId string) *Logger {
26 return &Logger{
27 l: sync.Mutex{},
28 runId: runId,
29 items: []LogItem{},
30 curr: LogItem{
31 RunId: runId,
32 Contents: []byte{},
33 },
34 }
35}
36
37func (l *Logger) Write(p []byte) (n int, err error) {
gio183e8342024-08-20 06:01:24 +040038 l.l.Lock()
39 defer l.l.Unlock()
gioaa6e27a2025-06-29 23:17:54 +040040 cnt := 0
gio183e8342024-08-20 06:01:24 +040041 // TODO(gio): Reset s.logs periodically
gioaa6e27a2025-06-29 23:17:54 +040042 for len(p) > 0 {
43 pos := bytes.Index(p, []byte("\n"))
44 if pos != -1 {
45 if l.curr.TimestampMilli == 0 {
46 l.curr.TimestampMilli = time.Now().UnixMilli()
47 }
48 l.curr.Contents = append(l.curr.Contents, p[:pos]...)
49 l.items = append(l.items, l.curr)
50 l.curr = LogItem{
51 RunId: l.runId,
gio89c5b5e2025-07-02 12:15:04 +040052 Commit: l.commitHash,
gioaa6e27a2025-06-29 23:17:54 +040053 Contents: []byte{},
54 }
55 p = p[pos+len([]byte("\n")):]
56 cnt += pos + len([]byte("\n"))
57 } else {
58 if l.curr.TimestampMilli == 0 {
59 l.curr.TimestampMilli = time.Now().UnixMilli()
60 }
61 l.curr.Contents = append(l.curr.Contents, p...)
62 cnt += len(p)
63 p = []byte{}
64 }
65 }
66 return cnt, nil
gio183e8342024-08-20 06:01:24 +040067}
68
gioaa6e27a2025-06-29 23:17:54 +040069func (l *Logger) Items() []LogItem {
gio183e8342024-08-20 06:01:24 +040070 l.l.Lock()
71 defer l.l.Unlock()
gioaa6e27a2025-06-29 23:17:54 +040072 ret := []LogItem{}
73 for _, i := range l.items {
74 ret = append(ret, i)
75 }
76 return ret
77}
78
79func (l *Logger) Trim(n int) {
80 l.l.Lock()
81 defer l.l.Unlock()
82 l.items = l.items[n:]
83}
84
85func (l *Logger) Contents() (string, error) {
86 l.l.Lock()
87 defer l.l.Unlock()
88 var ret strings.Builder
89 for _, i := range l.items {
90 if _, err := ret.Write(i.Contents); err != nil {
91 return "", err
92 }
93 if _, err := ret.WriteString("\n"); err != nil {
94 return "", err
95 }
96 }
97 return ret.String(), nil
gio183e8342024-08-20 06:01:24 +040098}