Path: blob/main/cmd/grafana-agent-service/logger_windows.go
4096 views
package main12import (3"io"4"runtime"5"strings"67"github.com/go-kit/log"8"golang.org/x/sys/windows/svc/eventlog"9)1011// logger sends logs to the Windows Event Log.12type logger struct {13el *eventlog.Log14}1516var (17_ log.Logger = (*logger)(nil)18_ io.Writer = (*logger)(nil)19)2021// newLogger creates a new logger which writes logs to the Windows Event22// Logger.23func newLogger() (*logger, error) {24eventTypes := uint32(eventlog.Info | eventlog.Warning | eventlog.Error)2526// Install the event source. This will fail with an error string saying "already27// exists" if it has been installed before.28err := eventlog.InstallAsEventCreate(serviceName, eventTypes)29if err != nil && !strings.Contains(err.Error(), "already exists") {30return nil, err31}3233el, err := eventlog.Open(serviceName)34if err != nil {35return nil, err36}3738// Ensure the logger gets closed when GC runs.39runtime.SetFinalizer(el, func(li *eventlog.Log) {40_ = li.Close()41})4243return &logger{el: el}, nil44}4546// Log implements [log.Logger], logging the key-value pairs to the Windows47// event logger as logfmt.48//49// If kvps contains a logging level, then50func (l *logger) Log(kvps ...interface{}) error {51// log.NewLogfmtLogger shouldn't escape to the heap since it's never used52// beyond the scope of this initial call.53return log.NewLogfmtLogger(l).Log(kvps...)54}5556var (57warnText = "warn"58errorText = "error"59)6061// Write implements [io.Writer], writing the provided data to the event logger.62// If the data contains the phrase "warn," then the text is logged as a63// warn-level event. If the data contains the phrase "error," then the text is64// logged as an error-level event.65func (l *logger) Write(data []byte) (n int, err error) {66var (67leveledLogger = l.el.Info68msg = string(data)69)7071// TODO(rfratto): Find a way to reduce the amount of false positives where72// log lines get incorrectly flagged as warning/error log lines.73//74// A longer-term solution would need to consider that logs may be emitted as75// either logfmt or JSON.76switch {77case strings.Contains(msg, warnText):78leveledLogger = l.el.Warning79case strings.Contains(msg, errorText):80leveledLogger = l.el.Error81}8283if err := leveledLogger(1, msg); err != nil {84return 0, err85}86return len(data), nil87}888990