feat_: API logging objects with `zap.Any` (#6125)

* feat_: api logging objects as zap.Any

* test_: fix TestCall
This commit is contained in:
Igor Sirotin 2024-11-29 13:18:59 +00:00 committed by GitHub
parent 5a69c686cf
commit cdc41c3b64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 3 deletions

View File

@ -1,6 +1,7 @@
package callog package callog
import ( import (
"encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"regexp" "regexp"
@ -138,8 +139,17 @@ func Log(logger *zap.Logger, method string, params any, resp any, startTime time
duration := time.Since(startTime) duration := time.Since(startTime)
logger.Debug("call", logger.Debug("call",
zap.String("method", method), zap.String("method", method),
zap.String("params", removeSensitiveInfo(fmt.Sprintf("%+v", params))),
zap.String("resp", removeSensitiveInfo(fmt.Sprintf("%+v", resp))),
zap.Duration("duration", duration), zap.Duration("duration", duration),
dataField("request", params),
dataField("response", resp),
) )
} }
func dataField(name string, data any) zap.Field {
dataString := removeSensitiveInfo(fmt.Sprintf("%+v", data))
var paramsParsed any
if json.Unmarshal([]byte(dataString), &paramsParsed) == nil {
return zap.Any(name, paramsParsed)
}
return zap.String(name, dataString)
}

View File

@ -95,7 +95,7 @@ func TestCall(t *testing.T) {
requestLogOutput := string(logData) requestLogOutput := string(logData)
// Check if the log contains expected information // Check if the log contains expected information
expectedLogParts := []string{getShortFunctionName(testFunc), "params", testParam, "resp", expectedResult} expectedLogParts := []string{getShortFunctionName(testFunc), "request", testParam, "response", expectedResult}
for _, part := range expectedLogParts { for _, part := range expectedLogParts {
if !strings.Contains(requestLogOutput, part) { if !strings.Contains(requestLogOutput, part) {
t.Errorf("Log output doesn't contain expected part: %s", part) t.Errorf("Log output doesn't contain expected part: %s", part)
@ -134,3 +134,48 @@ func TestGetFunctionName(t *testing.T) {
fn := getShortFunctionName(initializeApplication) fn := getShortFunctionName(initializeApplication)
require.Equal(t, "initializeApplication", fn) require.Equal(t, "initializeApplication", fn)
} }
func TestDataField(t *testing.T) {
entry := zapcore.Entry{}
enc := zapcore.NewJSONEncoder(zapcore.EncoderConfig{})
f := dataField("root", "value")
require.NotNil(t, f)
require.Equal(t, "root", f.Key)
require.Equal(t, zapcore.StringType, f.Type)
require.Equal(t, "value", f.String)
// Test JSON object
f = dataField("root", `{"key1": "value1"}`)
require.NotNil(t, f)
require.Equal(t, "root", f.Key)
require.Equal(t, zapcore.ReflectType, f.Type)
buf, err := enc.EncodeEntry(entry, []zapcore.Field{f})
require.NoError(t, err)
require.NotNil(t, buf)
require.Equal(t, `{"root":{"key1":"value1"}}`+"\n", buf.String())
// Test JSON array
f = dataField("root", `["value1", "value2"]`)
require.NotNil(t, f)
require.Equal(t, "root", f.Key)
require.Equal(t, zapcore.ReflectType, f.Type)
buf, err = enc.EncodeEntry(entry, []zapcore.Field{f})
require.NoError(t, err)
require.NotNil(t, buf)
require.Equal(t, `{"root":["value1","value2"]}`+"\n", buf.String())
// Test non-json content
f = dataField("root", `{non-json content}`)
require.NotNil(t, f)
require.Equal(t, "root", f.Key)
require.Equal(t, zapcore.StringType, f.Type)
require.Equal(t, `{non-json content}`, f.String)
buf, err = enc.EncodeEntry(entry, []zapcore.Field{f})
require.NoError(t, err)
require.NotNil(t, buf)
require.Equal(t, `{"root":"{non-json content}"}`+"\n", buf.String())
}