/
logrotate-output.go
68 lines (57 loc) · 1.26 KB
/
logrotate-output.go
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
package fileoutput
import (
"os"
"os/signal"
"sync"
"syscall"
"github.com/usnistgov/ndntdump"
)
// LogrotateOutput wraps a file-based RecordOutput to reopen the file upon SIGHUP.
type LogrotateOutput[T ndntdump.RecordOutput] struct {
filename string
mu sync.Mutex
sighup chan os.Signal
output T
create func(string) (T, error)
}
func (o *LogrotateOutput[T]) reopen(first bool) error {
o.mu.Lock()
defer o.mu.Unlock()
output, e := o.create(o.filename)
if e != nil {
return e
}
if !first {
o.output.Close()
}
o.output = output
return nil
}
func (o *LogrotateOutput[T]) Close() error {
signal.Stop(o.sighup)
close(o.sighup)
return o.output.Close()
}
func (o *LogrotateOutput[T]) Write(rec ndntdump.Record) error {
o.mu.Lock()
defer o.mu.Unlock()
return o.output.Write(rec)
}
// NewLogrotateOutput creates LogrotateOutput.
func NewLogrotateOutput[T ndntdump.RecordOutput](filename string, create func(string) (T, error)) (o *LogrotateOutput[T], e error) {
o = &LogrotateOutput[T]{
filename: filename,
sighup: make(chan os.Signal, 1),
create: create,
}
if e = o.reopen(true); e != nil {
return nil, e
}
signal.Notify(o.sighup, syscall.SIGHUP)
go func() {
for range o.sighup {
o.reopen(false)
}
}()
return o, nil
}