mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-08 05:56:37 +00:00
feat: windows_exporter uses own event log source to correctly format messages. (#1873)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de> Signed-off-by: Jan-Otto Kröpke <github@jkroepke.de>
This commit is contained in:
@@ -126,7 +126,7 @@ func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest,
|
|||||||
|
|
||||||
// logToEventToLog logs a message to the Windows event log.
|
// logToEventToLog logs a message to the Windows event log.
|
||||||
func logToEventToLog(eType uint16, msg string) error {
|
func logToEventToLog(eType uint16, msg string) error {
|
||||||
eventLog, err := eventlog.Open("windows_exporter")
|
eventLog, err := eventlog.Open(serviceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open event log: %w", err)
|
return fmt.Errorf("failed to open event log: %w", err)
|
||||||
}
|
}
|
||||||
@@ -134,15 +134,15 @@ func logToEventToLog(eType uint16, msg string) error {
|
|||||||
_ = eventLog.Close()
|
_ = eventLog.Close()
|
||||||
}(eventLog)
|
}(eventLog)
|
||||||
|
|
||||||
p, err := windows.UTF16PtrFromString(msg)
|
switch eType {
|
||||||
if err != nil {
|
case windows.EVENTLOG_ERROR_TYPE:
|
||||||
return fmt.Errorf("error convert string to UTF-16: %w", err)
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("error report event: %w", err)
|
return fmt.Errorf("error report event: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,12 @@
|
|||||||
<ServiceDependency Id="wmiApSrv" />
|
<ServiceDependency Id="wmiApSrv" />
|
||||||
</ServiceInstall>
|
</ServiceInstall>
|
||||||
<ServiceControl Id="ServiceStateControl" Name="windows_exporter" Remove="uninstall" Start="install" Stop="both"/>
|
<ServiceControl Id="ServiceStateControl" Name="windows_exporter" Remove="uninstall" Start="install" Stop="both"/>
|
||||||
|
<!-- The "Name" field must match the argument to eventlog.Open() -->
|
||||||
|
<util:EventSource Log="Application" Name="windows_exporter"
|
||||||
|
EventMessageFile="%SystemRoot%\System32\EventCreate.exe"
|
||||||
|
SupportsErrors="yes"
|
||||||
|
SupportsInformationals="yes"
|
||||||
|
SupportsWarnings="yes"/>
|
||||||
</Component>
|
</Component>
|
||||||
<Component Id="CreateTextfileDirectory" Directory="textfile_inputs" Guid="d03ef58a-9cbf-4165-ad39-d143e9b27e14">
|
<Component Id="CreateTextfileDirectory" Directory="textfile_inputs" Guid="d03ef58a-9cbf-4165-ad39-d143e9b27e14">
|
||||||
<CreateFolder />
|
<CreateFolder />
|
||||||
|
|||||||
@@ -17,53 +17,41 @@
|
|||||||
package eventlog
|
package eventlog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows/svc/eventlog"
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interface guard.
|
// Interface guard.
|
||||||
var _ io.Writer = (*Writer)(nil)
|
var _ io.Writer = (*Writer)(nil)
|
||||||
|
|
||||||
//nolint:gochecknoglobals
|
var reStripTimeAndLevel = regexp.MustCompile(`^time=\S+ level=\S+ `)
|
||||||
var EmptyStringUTF16 uint16
|
|
||||||
|
|
||||||
type Writer struct {
|
type Writer struct {
|
||||||
handle windows.Handle
|
handle *eventlog.Log
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEventLogWriter returns a new Writer which writes to Windows EventLog.
|
// NewEventLogWriter returns a new Writer, which writes to Windows EventLog.
|
||||||
func NewEventLogWriter(handle windows.Handle) *Writer {
|
func NewEventLogWriter(handle *eventlog.Log) *Writer {
|
||||||
return &Writer{handle: handle}
|
return &Writer{handle: handle}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Write(p []byte) (int, error) {
|
func (w *Writer) Write(p []byte) (int, error) {
|
||||||
var eType uint16
|
var err error
|
||||||
|
|
||||||
|
msg := strings.TrimSpace(string(p))
|
||||||
|
eventLogMsg := reStripTimeAndLevel.ReplaceAllString(msg, "")
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case bytes.Contains(p, []byte(" level=error")) || bytes.Contains(p, []byte(`"level":"error"`)):
|
case strings.Contains(msg, " level=ERROR") || strings.Contains(msg, `"level":"error"`):
|
||||||
eType = windows.EVENTLOG_ERROR_TYPE
|
err = w.handle.Error(102, eventLogMsg)
|
||||||
case bytes.Contains(p, []byte(" level=warn")) || bytes.Contains(p, []byte(`"level":"warn"`)):
|
case strings.Contains(msg, " level=WARN") || strings.Contains(msg, `"level":"warn"`):
|
||||||
eType = windows.EVENTLOG_WARNING_TYPE
|
err = w.handle.Warning(101, eventLogMsg)
|
||||||
default:
|
default:
|
||||||
eType = windows.EVENTLOG_INFORMATION_TYPE
|
err = w.handle.Info(100, eventLogMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := windows.UTF16PtrFromString(string(p))
|
return len(p), err
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
"github.com/prometheus-community/windows_exporter/internal/log/eventlog"
|
"github.com/prometheus-community/windows_exporter/internal/log/eventlog"
|
||||||
"github.com/prometheus/common/promslog"
|
"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.
|
// 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":
|
case "stderr":
|
||||||
f.w = os.Stderr
|
f.w = os.Stderr
|
||||||
case "eventlog":
|
case "eventlog":
|
||||||
handle, err := windows.RegisterEventSource(nil, windows.StringToUTF16Ptr("windows_exporter"))
|
eventLog, err := wineventlog.Open("windows_exporter")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open event log: %w", err)
|
return fmt.Errorf("failed to open event log: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f.w = eventlog.NewEventLogWriter(handle)
|
f.w = eventlog.NewEventLogWriter(eventLog)
|
||||||
default:
|
default:
|
||||||
file, err := os.OpenFile(s, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o200)
|
file, err := os.OpenFile(s, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o200)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -172,6 +172,12 @@ func NewCollectorWithReflection(resultType CounterType, object string, instances
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bufLen == 0 {
|
||||||
|
errs = append(errs, errors.New("GetCounterInfo: buffer length is zero"))
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
buf := make([]byte, bufLen)
|
buf := make([]byte, bufLen)
|
||||||
if ret := GetCounterInfo(counterHandle, 0, &bufLen, &buf[0]); ret != ErrorSuccess {
|
if ret := GetCounterInfo(counterHandle, 0, &bufLen, &buf[0]); ret != ErrorSuccess {
|
||||||
errs = append(errs, fmt.Errorf("GetCounterInfo: %w", NewPdhError(ret)))
|
errs = append(errs, fmt.Errorf("GetCounterInfo: %w", NewPdhError(ret)))
|
||||||
|
|||||||
Reference in New Issue
Block a user