Add Event Log support for Windows (#8616)

* Add event log support for windows when not running as a windows service.

* Add error message for initializing event logger.

* Add build windows flag.

* Only register event logger when running telegraf under windows.

* Update logger/event_logger.go

Co-authored-by: Steven Soroka <ssoroka@influxdata.com>

* Remove unnecessary 'fmt' import

* Remove unnecessary 'fmt' import

* Remove unnecessary error check

* use constants for eid levels.

Co-authored-by: Steven Soroka <ssoroka@influxdata.com>
This commit is contained in:
David Bennett 2021-01-19 11:03:19 -05:00 committed by GitHub
parent 6ed1431348
commit 1bf5a19582
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 23 deletions

View File

@ -12,6 +12,9 @@ import (
) )
func run(inputFilters, outputFilters, aggregatorFilters, processorFilters []string) { func run(inputFilters, outputFilters, aggregatorFilters, processorFilters []string) {
// Register the eventlog logging target for windows.
logger.RegisterEventLogger(*fServiceName)
if runtime.GOOS == "windows" && windowsRunAsService() { if runtime.GOOS == "windows" && windowsRunAsService() {
runAsWindowsService( runAsWindowsService(
inputFilters, inputFilters,
@ -96,12 +99,7 @@ func runAsWindowsService(inputFilters, outputFilters, aggregatorFilters, process
} }
os.Exit(0) os.Exit(0)
} else { } else {
winlogger, err := s.Logger(nil) logger.SetupLogging(logger.LogConfig{LogTarget: logger.LogTargetEventlog})
if err == nil {
//When in service mode, register eventlog target andd setup default logging to eventlog
logger.RegisterEventLogger(winlogger)
logger.SetupLogging(logger.LogConfig{LogTarget: logger.LogTargetEventlog})
}
err = s.Run() err = s.Run()
if err != nil { if err != nil {

View File

@ -1,35 +1,41 @@
//+build windows
package logger package logger
import ( import (
"io" "io"
"log"
"strings" "strings"
"github.com/influxdata/wlog" "github.com/influxdata/wlog"
"github.com/kardianos/service" "golang.org/x/sys/windows/svc/eventlog"
) )
const ( const (
LogTargetEventlog = "eventlog" LogTargetEventlog = "eventlog"
eidInfo = 1
eidWarning = 2
eidError = 3
) )
type eventLogger struct { type eventLogger struct {
logger service.Logger logger *eventlog.Log
} }
func (t *eventLogger) Write(b []byte) (n int, err error) { func (t *eventLogger) Write(b []byte) (n int, err error) {
loc := prefixRegex.FindIndex(b) loc := prefixRegex.FindIndex(b)
n = len(b) n = len(b)
if loc == nil { if loc == nil {
err = t.logger.Info(b) err = t.logger.Info(1, string(b))
} else if n > 2 { //skip empty log messages } else if n > 2 { //skip empty log messages
line := strings.Trim(string(b[loc[1]:]), " \t\r\n") line := strings.Trim(string(b[loc[1]:]), " \t\r\n")
switch rune(b[loc[0]]) { switch rune(b[loc[0]]) {
case 'I': case 'I':
err = t.logger.Info(line) err = t.logger.Info(eidInfo, line)
case 'W': case 'W':
err = t.logger.Warning(line) err = t.logger.Warning(eidWarning, line)
case 'E': case 'E':
err = t.logger.Error(line) err = t.logger.Error(eidError, line)
} }
} }
@ -37,13 +43,20 @@ func (t *eventLogger) Write(b []byte) (n int, err error) {
} }
type eventLoggerCreator struct { type eventLoggerCreator struct {
serviceLogger service.Logger logger *eventlog.Log
} }
func (e *eventLoggerCreator) CreateLogger(config LogConfig) (io.Writer, error) { func (e *eventLoggerCreator) CreateLogger(config LogConfig) (io.Writer, error) {
return wlog.NewWriter(&eventLogger{logger: e.serviceLogger}), nil return wlog.NewWriter(&eventLogger{logger: e.logger}), nil
} }
func RegisterEventLogger(serviceLogger service.Logger) { func RegisterEventLogger(name string) error {
registerLogger(LogTargetEventlog, &eventLoggerCreator{serviceLogger: serviceLogger}) eventLog, err := eventlog.Open(name)
if err != nil {
log.Printf("E! An error occurred while initializing an event logger. %s", err)
return err
}
registerLogger(LogTargetEventlog, &eventLoggerCreator{logger: eventLog})
return nil
} }

View File

@ -10,9 +10,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/kardianos/service"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"golang.org/x/sys/windows/svc/eventlog"
) )
type Levels int type Levels int
@ -30,7 +30,8 @@ type Event struct {
func getEventLog(t *testing.T, since time.Time) []Event { func getEventLog(t *testing.T, since time.Time) []Event {
timeStr := since.UTC().Format(time.RFC3339) timeStr := since.UTC().Format(time.RFC3339)
cmd := exec.Command("wevtutil", "qe", "Application", "/rd:true", "/q:Event[System[TimeCreated[@SystemTime >= '"+timeStr+"'] and Provider[@Name='Telegraf']]]") timeStr = timeStr[:19]
cmd := exec.Command("wevtutil", "qe", "Application", "/rd:true", "/q:Event[System[TimeCreated[@SystemTime >= '"+timeStr+"'] and Provider[@Name='telegraf']]]")
var out bytes.Buffer var out bytes.Buffer
cmd.Stdout = &out cmd.Stdout = &out
err := cmd.Run() err := cmd.Run()
@ -91,10 +92,8 @@ func TestRestrictedEventLog(t *testing.T) {
} }
func prepareLogger(t *testing.T) { func prepareLogger(t *testing.T) {
svc, err := service.New(nil, &service.Config{Name: "Telegraf"}) eventLog, err := eventlog.Open("telegraf")
require.NoError(t, err) require.NoError(t, err)
svcLogger, err := svc.SystemLogger(nil) require.NotNil(t, eventLog)
require.NoError(t, err) registerLogger(LogTargetEventlog, &eventLoggerCreator{logger: eventLog})
require.NotNil(t, svcLogger)
registerLogger(LogTargetEventlog, &eventLoggerCreator{serviceLogger: svcLogger})
} }