@@ -81,7 +81,7 @@ func (s *WindowsService) Execute(args []string, requests <-chan svc.ChangeReques
8181
8282func (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 = newWithEventViewerWithWindowsCore (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 newWithEventViewerWithWindowsCore (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 \n Stack 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 = (* windowsCore )(nil )
132+
133+ type windowsCore struct {
134+ core zapcore.Core
135+ elog * eventlog.Log
136+ encoder zapcore.Encoder
137+ }
138+
139+ func (w windowsCore ) Enabled (level zapcore.Level ) bool {
140+ return w .core .Enabled (level )
141+ }
142+
143+ func (w windowsCore ) With (fields []zapcore.Field ) zapcore.Core {
144+ return withWindowsCore (w .elog )(w .core .With (fields ))
145+ }
146+
147+ func (w windowsCore ) 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 windowsCore ) 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 windowsCore ) 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 windowsCore {core , elog , zapcore .NewConsoleEncoder (encoderConfig )}
187+ }
188+ }
0 commit comments