Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/cmd/grafana-agent-service/logger_windows.go
4096 views
1
package main
2
3
import (
4
"io"
5
"runtime"
6
"strings"
7
8
"github.com/go-kit/log"
9
"golang.org/x/sys/windows/svc/eventlog"
10
)
11
12
// logger sends logs to the Windows Event Log.
13
type logger struct {
14
el *eventlog.Log
15
}
16
17
var (
18
_ log.Logger = (*logger)(nil)
19
_ io.Writer = (*logger)(nil)
20
)
21
22
// newLogger creates a new logger which writes logs to the Windows Event
23
// Logger.
24
func newLogger() (*logger, error) {
25
eventTypes := uint32(eventlog.Info | eventlog.Warning | eventlog.Error)
26
27
// Install the event source. This will fail with an error string saying "already
28
// exists" if it has been installed before.
29
err := eventlog.InstallAsEventCreate(serviceName, eventTypes)
30
if err != nil && !strings.Contains(err.Error(), "already exists") {
31
return nil, err
32
}
33
34
el, err := eventlog.Open(serviceName)
35
if err != nil {
36
return nil, err
37
}
38
39
// Ensure the logger gets closed when GC runs.
40
runtime.SetFinalizer(el, func(li *eventlog.Log) {
41
_ = li.Close()
42
})
43
44
return &logger{el: el}, nil
45
}
46
47
// Log implements [log.Logger], logging the key-value pairs to the Windows
48
// event logger as logfmt.
49
//
50
// If kvps contains a logging level, then
51
func (l *logger) Log(kvps ...interface{}) error {
52
// log.NewLogfmtLogger shouldn't escape to the heap since it's never used
53
// beyond the scope of this initial call.
54
return log.NewLogfmtLogger(l).Log(kvps...)
55
}
56
57
var (
58
warnText = "warn"
59
errorText = "error"
60
)
61
62
// Write implements [io.Writer], writing the provided data to the event logger.
63
// If the data contains the phrase "warn," then the text is logged as a
64
// warn-level event. If the data contains the phrase "error," then the text is
65
// logged as an error-level event.
66
func (l *logger) Write(data []byte) (n int, err error) {
67
var (
68
leveledLogger = l.el.Info
69
msg = string(data)
70
)
71
72
// TODO(rfratto): Find a way to reduce the amount of false positives where
73
// log lines get incorrectly flagged as warning/error log lines.
74
//
75
// A longer-term solution would need to consider that logs may be emitted as
76
// either logfmt or JSON.
77
switch {
78
case strings.Contains(msg, warnText):
79
leveledLogger = l.el.Warning
80
case strings.Contains(msg, errorText):
81
leveledLogger = l.el.Error
82
}
83
84
if err := leveledLogger(1, msg); err != nil {
85
return 0, err
86
}
87
return len(data), nil
88
}
89
90