blob: 084e3d1b84c1ebcd53ecf2d8003d2984e99f74c9 [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,
52 Contents: []byte{},
53 }
54 p = p[pos+len([]byte("\n")):]
55 cnt += pos + len([]byte("\n"))
56 } else {
57 if l.curr.TimestampMilli == 0 {
58 l.curr.TimestampMilli = time.Now().UnixMilli()
59 }
60 l.curr.Contents = append(l.curr.Contents, p...)
61 cnt += len(p)
62 p = []byte{}
63 }
64 }
65 return cnt, nil
gio183e8342024-08-20 06:01:24 +040066}
67
gioaa6e27a2025-06-29 23:17:54 +040068func (l *Logger) Items() []LogItem {
gio183e8342024-08-20 06:01:24 +040069 l.l.Lock()
70 defer l.l.Unlock()
gioaa6e27a2025-06-29 23:17:54 +040071 ret := []LogItem{}
72 for _, i := range l.items {
73 ret = append(ret, i)
74 }
75 return ret
76}
77
78func (l *Logger) Trim(n int) {
79 l.l.Lock()
80 defer l.l.Unlock()
81 l.items = l.items[n:]
82}
83
84func (l *Logger) Contents() (string, error) {
85 l.l.Lock()
86 defer l.l.Unlock()
87 var ret strings.Builder
88 for _, i := range l.items {
89 if _, err := ret.Write(i.Contents); err != nil {
90 return "", err
91 }
92 if _, err := ret.WriteString("\n"); err != nil {
93 return "", err
94 }
95 }
96 return ret.String(), nil
gio183e8342024-08-20 06:01:24 +040097}