TUN-3767: Tolerate logging errors

This addresses a bug where logging would not be output when
cloudflared was run as a Windows Service.

That was happening because Windows Services have no stderr/out,
and the ConsoleWriter log was failing inside zerolog, which would
then not proceed to the next logger (the file logger).

We now overcome that by using our own multi writer that is resilient
to errors.
This commit is contained in:
Nuno Diegues
2021-01-16 15:56:44 +00:00
parent 8da61274b8
commit de27361ffa
2 changed files with 105 additions and 1 deletions

89
logger/create_test.go Normal file
View File

@@ -0,0 +1,89 @@
package logger
import (
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
"io"
"testing"
)
var writeCalls int
type mockedWriter struct {
wantErr bool
}
func (c mockedWriter) Write(p []byte) (int, error) {
writeCalls++
if c.wantErr {
return -1, errors.New("Expected error")
}
return len(p), nil
}
// Tests that a new writer is only used if it actually works.
func TestResilientMultiWriter(t *testing.T) {
tests := []struct {
name string
writers []io.Writer
}{
{
name: "All valid writers",
writers: []io.Writer{
mockedWriter {
wantErr: false,
},
mockedWriter {
wantErr: false,
},
},
},
{
name: "All invalid writers",
writers: []io.Writer{
mockedWriter {
wantErr: true,
},
mockedWriter {
wantErr: true,
},
},
},
{
name: "First invalid writer",
writers: []io.Writer{
mockedWriter {
wantErr: true,
},
mockedWriter {
wantErr: false,
},
},
},
{
name: "First valid writer",
writers: []io.Writer{
mockedWriter {
wantErr: false,
},
mockedWriter {
wantErr: true,
},
},
},
}
for _, tt := range tests {
writers := tt.writers
multiWriter := resilientMultiWriter{writers}
logger := zerolog.New(multiWriter).With().Timestamp().Logger().Level(zerolog.InfoLevel)
logger.Info().Msg("Test msg")
assert.Equal(t, len(writers), writeCalls)
writeCalls = 0
}
}