-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogbuffer.go
More file actions
80 lines (66 loc) · 1.76 KB
/
logbuffer.go
File metadata and controls
80 lines (66 loc) · 1.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package syro
import (
"archive/zip"
"bytes"
"fmt"
"strings"
"sync"
"time"
)
// LogBuffer is a minimal, thread-safe log buffer. It accumulates lines in
// memory until ToFile is called. Useful for accumumating logs of a
// single prolonged operation, that you don't want to log to
// disk right away or write to db each time
type LogBuffer struct {
sb strings.Builder
mu sync.Mutex
}
func NewLogBuffer() *LogBuffer { return &LogBuffer{} }
// Logf appends a formatted line to the buffer (thread-safe).
// Always ensures a trailing newline.
func (lb *LogBuffer) Logf(format string, args ...any) {
s := fmt.Sprintf(format, args...)
lb.mu.Lock()
lb.sb.WriteString(s)
if !strings.HasSuffix(s, "\n") {
lb.sb.WriteByte('\n')
}
lb.mu.Unlock()
}
// Reset resets the [Builder] to be empty.
func (lb *LogBuffer) Reset() {
lb.mu.Lock()
lb.sb.Reset()
lb.mu.Unlock()
}
// Flush returns the accumulated sb contents as []byte,
// and clears the in-memory buffer (thread-safe).
func (lb *LogBuffer) Flush() []byte {
lb.mu.Lock()
defer lb.mu.Unlock()
data := []byte(lb.sb.String())
lb.sb.Reset() // free memory
return data
}
// FlushToZip empties the sb and converts it to a zip
func (lb *LogBuffer) FlushToZip(filename string) ([]byte, error) {
fileBytes := lb.Flush()
var buf bytes.Buffer
zw := zip.NewWriter(&buf)
h := &zip.FileHeader{
Name: filename,
Method: zip.Deflate,
Modified: time.Now().UTC(),
}
w, err := zw.CreateHeader(h)
if err != nil {
return nil, fmt.Errorf("failed to create zip entry: %v", err)
}
if _, err := w.Write(fileBytes); err != nil {
return nil, fmt.Errorf("failed to write log bytes into zip: %v", err)
}
if err := zw.Close(); err != nil {
return nil, fmt.Errorf("failed to finalize zip: %v", err)
}
return buf.Bytes(), nil
}