github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/x/log/config_test.go (about) 1 // Copyright (c) 2021 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package log 22 23 import ( 24 "io/ioutil" 25 "os" 26 "strings" 27 "testing" 28 "time" 29 30 "github.com/stretchr/testify/assert" 31 "github.com/stretchr/testify/require" 32 "go.uber.org/zap/zapcore" 33 ) 34 35 func TestLoggerConfiguration(t *testing.T) { 36 tmpfile, err := ioutil.TempFile("", "logtest") 37 require.NoError(t, err) 38 39 defer tmpfile.Close() 40 defer os.Remove(tmpfile.Name()) 41 42 cfg := Configuration{ 43 Fields: map[string]interface{}{ 44 "my-field": "my-val", 45 }, 46 Level: "error", 47 File: tmpfile.Name(), 48 } 49 50 log, err := cfg.BuildLogger() 51 require.NoError(t, err) 52 53 log.Info("should not appear") 54 log.Warn("should not appear") 55 log.Error("this should appear") 56 57 b, err := ioutil.ReadAll(tmpfile) 58 require.NoError(t, err) 59 60 data := string(b) 61 require.Equal(t, 1, strings.Count(data, "\n"), data) 62 require.True(t, strings.Contains(data, `"msg":"this should appear"`)) 63 require.True(t, strings.Contains(data, `"my-field":"my-val"`)) 64 require.True(t, strings.Contains(data, `"level":"error"`)) 65 } 66 67 func TestLoggerEncoderConfiguraion(t *testing.T) { 68 logTime := time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC) 69 logEntry := zapcore.Entry{ 70 LoggerName: "main", 71 Level: zapcore.InfoLevel, 72 Message: `hello`, 73 Time: logTime, 74 Stack: "fake-stack", 75 Caller: zapcore.EntryCaller{Defined: true, File: "foo.go", Line: 42, Function: "foo.Foo"}, 76 } 77 78 tests := []struct { 79 name string 80 cfg encoderConfig 81 expected string 82 }{ 83 { 84 name: "empty encoder config", 85 cfg: encoderConfig{}, 86 expected: `{"level":"info","ts":0,"logger":"main","caller":"foo.go:42","msg":"hello",` + 87 `"stacktrace":"fake-stack"}` + zapcore.DefaultLineEnding, 88 }, 89 { 90 name: "encoder custom", 91 cfg: encoderConfig{ 92 MessageKey: "M", 93 LevelKey: "L", 94 TimeKey: "T", 95 NameKey: "N", 96 CallerKey: "C", 97 FunctionKey: "F", 98 StacktraceKey: "S", 99 LineEnding: "\r\n", 100 EncodeLevel: "capital", 101 EncodeTime: "rfc3339nano", 102 EncodeDuration: "string", 103 EncodeCaller: "short", 104 EncodeName: "full", 105 }, 106 expected: `{"L":"INFO","T":"1970-01-01T00:00:00Z","N":"main","C":"foo.go:42","F":"foo.Foo","M":"hello",` + 107 `"S":"fake-stack"}` + "\r\n", 108 }, 109 } 110 for _, tt := range tests { 111 t.Run(tt.name, func(t *testing.T) { 112 logCfg := Configuration{ 113 EncoderConfig: tt.cfg, 114 } 115 ec := logCfg.newEncoderConfig() 116 json := zapcore.NewJSONEncoder(ec) 117 jsonOut, jsonErr := json.EncodeEntry(logEntry, nil) 118 assert.NoError(t, jsonErr, "Unexpected error JSON-encoding entry") 119 assert.Equal(t, tt.expected, jsonOut.String()) 120 }) 121 } 122 } 123 124 func TestGettingLoggerZapConfig(t *testing.T) { 125 tmpfile, err := ioutil.TempFile("", "logtest") 126 require.NoError(t, err) 127 128 defer func() { 129 err = tmpfile.Close() 130 err = os.Remove(tmpfile.Name()) 131 }() 132 133 cfg := Configuration{ 134 Fields: map[string]interface{}{ 135 "my-field": "my-val", 136 }, 137 Level: "error", 138 File: tmpfile.Name(), 139 } 140 141 log, zapConfig, err := cfg.BuildLoggerAndReturnConfig() 142 require.NoError(t, err) 143 144 log.Info("should not appear") 145 log.Warn("should not appear") 146 log.Error("this should appear") 147 148 zapConfig.Level.SetLevel(zapcore.InfoLevel) 149 log.Info("info should now appear") 150 log.Warn("warn should now appear") 151 b, err := ioutil.ReadAll(tmpfile) 152 require.NoError(t, err) 153 154 data := string(b) 155 require.Equal(t, 3, strings.Count(data, "\n"), data) 156 require.True(t, strings.Contains(data, `"msg":"this should appear"`)) 157 require.True(t, strings.Contains(data, `"my-field":"my-val"`)) 158 require.True(t, strings.Contains(data, `"level":"error"`)) 159 require.True(t, strings.Contains(data, `"msg":"info should now appear"`)) 160 require.True(t, strings.Contains(data, `"msg":"warn should now appear"`)) 161 }