diff --git a/cmd/windows_exporter/0_service.go b/cmd/windows_exporter/0_service.go index d19756b22..37ac74087 100644 --- a/cmd/windows_exporter/0_service.go +++ b/cmd/windows_exporter/0_service.go @@ -126,7 +126,7 @@ func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, // logToEventToLog logs a message to the Windows event log. func logToEventToLog(eType uint16, msg string) error { - eventLog, err := eventlog.Open("windows_exporter") + eventLog, err := eventlog.Open(serviceName) if err != nil { return fmt.Errorf("failed to open event log: %w", err) } @@ -134,15 +134,15 @@ func logToEventToLog(eType uint16, msg string) error { _ = eventLog.Close() }(eventLog) - p, err := windows.UTF16PtrFromString(msg) - if err != nil { - return fmt.Errorf("error convert string to UTF-16: %w", err) + switch eType { + case windows.EVENTLOG_ERROR_TYPE: + err = eventLog.Error(102, msg) + case windows.EVENTLOG_WARNING_TYPE: + err = eventLog.Warning(101, msg) + case windows.EVENTLOG_INFORMATION_TYPE: + err = eventLog.Info(100, msg) } - zero := uint16(0) - ss := []*uint16{p, &zero, &zero, &zero, &zero, &zero, &zero, &zero, &zero} - - err = windows.ReportEvent(eventLog.Handle, eType, 0, 3299, 0, 9, 0, &ss[0], nil) if err != nil { return fmt.Errorf("error report event: %w", err) } diff --git a/installer/files.wxs b/installer/files.wxs index 1b4c019de..e011b6c66 100644 --- a/installer/files.wxs +++ b/installer/files.wxs @@ -44,6 +44,12 @@ + + diff --git a/internal/log/eventlog/eventlog.go b/internal/log/eventlog/eventlog.go index 73e68864a..ba1c89f2a 100644 --- a/internal/log/eventlog/eventlog.go +++ b/internal/log/eventlog/eventlog.go @@ -17,53 +17,41 @@ package eventlog import ( - "bytes" - "fmt" "io" + "regexp" + "strings" - "golang.org/x/sys/windows" -) - -const ( - // NeLogOemCode is a generic error log entry for OEMs to use to - // elog errors from OEM value added services. - // See: https://github.com/microsoft/win32metadata/blob/2f3c5282ce1024a712aeccd90d3aa50bf7a49e27/generation/WinSDK/RecompiledIdlHeaders/um/LMErrlog.h#L824-L845 - NeLogOemCode = uint32(3299) + "golang.org/x/sys/windows/svc/eventlog" ) // Interface guard. var _ io.Writer = (*Writer)(nil) -//nolint:gochecknoglobals -var EmptyStringUTF16 uint16 +var reStripTimeAndLevel = regexp.MustCompile(`^time=\S+ level=\S+ `) type Writer struct { - handle windows.Handle + handle *eventlog.Log } -// NewEventLogWriter returns a new Writer which writes to Windows EventLog. -func NewEventLogWriter(handle windows.Handle) *Writer { +// NewEventLogWriter returns a new Writer, which writes to Windows EventLog. +func NewEventLogWriter(handle *eventlog.Log) *Writer { return &Writer{handle: handle} } func (w *Writer) Write(p []byte) (int, error) { - var eType uint16 + var err error + + msg := strings.TrimSpace(string(p)) + eventLogMsg := reStripTimeAndLevel.ReplaceAllString(msg, "") switch { - case bytes.Contains(p, []byte(" level=error")) || bytes.Contains(p, []byte(`"level":"error"`)): - eType = windows.EVENTLOG_ERROR_TYPE - case bytes.Contains(p, []byte(" level=warn")) || bytes.Contains(p, []byte(`"level":"warn"`)): - eType = windows.EVENTLOG_WARNING_TYPE + case strings.Contains(msg, " level=ERROR") || strings.Contains(msg, `"level":"error"`): + err = w.handle.Error(102, eventLogMsg) + case strings.Contains(msg, " level=WARN") || strings.Contains(msg, `"level":"warn"`): + err = w.handle.Warning(101, eventLogMsg) default: - eType = windows.EVENTLOG_INFORMATION_TYPE + err = w.handle.Info(100, eventLogMsg) } - msg, err := windows.UTF16PtrFromString(string(p)) - if err != nil { - return 0, fmt.Errorf("error convert string to UTF-16: %w", err) - } - - ss := []*uint16{msg, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16} - - return len(p), windows.ReportEvent(w.handle, eType, 0, NeLogOemCode, 0, 9, 0, &ss[0], nil) + return len(p), err } diff --git a/internal/log/logger.go b/internal/log/logger.go index c245783e2..23006aae9 100644 --- a/internal/log/logger.go +++ b/internal/log/logger.go @@ -24,7 +24,7 @@ import ( "github.com/prometheus-community/windows_exporter/internal/log/eventlog" "github.com/prometheus/common/promslog" - "golang.org/x/sys/windows" + wineventlog "golang.org/x/sys/windows/svc/eventlog" ) // AllowedFile is a settable identifier for the output file that the logger can have. @@ -51,12 +51,12 @@ func (f *AllowedFile) Set(s string) error { case "stderr": f.w = os.Stderr case "eventlog": - handle, err := windows.RegisterEventSource(nil, windows.StringToUTF16Ptr("windows_exporter")) + eventLog, err := wineventlog.Open("windows_exporter") if err != nil { return fmt.Errorf("failed to open event log: %w", err) } - f.w = eventlog.NewEventLogWriter(handle) + f.w = eventlog.NewEventLogWriter(eventLog) default: file, err := os.OpenFile(s, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o200) if err != nil { diff --git a/internal/pdh/collector.go b/internal/pdh/collector.go index 1aa689395..db8ab1490 100644 --- a/internal/pdh/collector.go +++ b/internal/pdh/collector.go @@ -172,6 +172,12 @@ func NewCollectorWithReflection(resultType CounterType, object string, instances continue } + if bufLen == 0 { + errs = append(errs, errors.New("GetCounterInfo: buffer length is zero")) + + continue + } + buf := make([]byte, bufLen) if ret := GetCounterInfo(counterHandle, 0, &bufLen, &buf[0]); ret != ErrorSuccess { errs = append(errs, fmt.Errorf("GetCounterInfo: %w", NewPdhError(ret)))