Skip to content

Commit 2e84285

Browse files
Use dedicated zapcore.Core for Windows service (#3147)
As reported in #2756 Windows service events only contain the zap entry message and none of the fields. These changes create a dedicated `zapcore.Core` to wrap the service logger's Core and use a production console encoder to encode the full entry, including its fields and stack if provided. **Link to tracking Issue:** #2756
1 parent af71182 commit 2e84285

File tree

1 file changed

+62
-21
lines changed

1 file changed

+62
-21
lines changed

service/application_windows.go

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func (s *WindowsService) Execute(args []string, requests <-chan svc.ChangeReques
8181

8282
func (s *WindowsService) start(elog *eventlog.Log, appErrorChannel chan error) error {
8383
var err error
84-
s.app, err = newWithEventViewerLoggingHook(s.params, elog)
84+
s.app, err = newWithWindowsEventLogCore(s.params, elog)
8585
if err != nil {
8686
return err
8787
}
@@ -120,28 +120,69 @@ func openEventLog(serviceName string) (*eventlog.Log, error) {
120120
return elog, nil
121121
}
122122

123-
func newWithEventViewerLoggingHook(params Parameters, elog *eventlog.Log) (*Application, error) {
123+
func newWithWindowsEventLogCore(params Parameters, elog *eventlog.Log) (*Application, error) {
124124
params.LoggingOptions = append(
125125
params.LoggingOptions,
126-
zap.Hooks(func(entry zapcore.Entry) error {
127-
msg := fmt.Sprintf("%v\r\n\r\nStack Trace:\r\n%v", entry.Message, entry.Stack)
128-
129-
switch entry.Level {
130-
case zapcore.FatalLevel, zapcore.PanicLevel, zapcore.DPanicLevel:
131-
// golang.org/x/sys/windows/svc/eventlog does not support Critical level event logs
132-
return elog.Error(3, msg)
133-
case zapcore.ErrorLevel:
134-
return elog.Error(3, msg)
135-
case zapcore.WarnLevel:
136-
return elog.Warning(2, msg)
137-
case zapcore.InfoLevel:
138-
return elog.Info(1, msg)
139-
}
140-
141-
// ignore Debug level logs
142-
return nil
143-
}),
126+
zap.WrapCore(withWindowsCore(elog)),
144127
)
145-
146128
return New(params)
147129
}
130+
131+
var _ zapcore.Core = (*windowsEventLogCore)(nil)
132+
133+
type windowsEventLogCore struct {
134+
core zapcore.Core
135+
elog *eventlog.Log
136+
encoder zapcore.Encoder
137+
}
138+
139+
func (w windowsEventLogCore) Enabled(level zapcore.Level) bool {
140+
return w.core.Enabled(level)
141+
}
142+
143+
func (w windowsEventLogCore) With(fields []zapcore.Field) zapcore.Core {
144+
return withWindowsCore(w.elog)(w.core.With(fields))
145+
}
146+
147+
func (w windowsEventLogCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
148+
if w.Enabled(ent.Level) {
149+
return ce.AddCore(ent, w)
150+
}
151+
return ce
152+
}
153+
154+
func (w windowsEventLogCore) Write(ent zapcore.Entry, fields []zapcore.Field) error {
155+
buf, err := w.encoder.EncodeEntry(ent, fields)
156+
if err != nil {
157+
w.elog.Warning(2, fmt.Sprintf("failed encoding log entry %v\r\n", err))
158+
return err
159+
}
160+
msg := buf.String()
161+
buf.Free()
162+
163+
switch ent.Level {
164+
case zapcore.FatalLevel, zapcore.PanicLevel, zapcore.DPanicLevel:
165+
// golang.org/x/sys/windows/svc/eventlog does not support Critical level event logs
166+
return w.elog.Error(3, msg)
167+
case zapcore.ErrorLevel:
168+
return w.elog.Error(3, msg)
169+
case zapcore.WarnLevel:
170+
return w.elog.Warning(2, msg)
171+
case zapcore.InfoLevel:
172+
return w.elog.Info(1, msg)
173+
}
174+
// We would not be here if debug were disabled so log as info to not drop.
175+
return w.elog.Info(1, msg)
176+
}
177+
178+
func (w windowsEventLogCore) Sync() error {
179+
return w.core.Sync()
180+
}
181+
182+
func withWindowsCore(elog *eventlog.Log) func(zapcore.Core) zapcore.Core {
183+
return func(core zapcore.Core) zapcore.Core {
184+
encoderConfig := zap.NewProductionEncoderConfig()
185+
encoderConfig.LineEnding = "\r\n"
186+
return windowsEventLogCore{core, elog, zapcore.NewConsoleEncoder(encoderConfig)}
187+
}
188+
}

0 commit comments

Comments
 (0)