From 39676004def5d3cffcff2323d5af02992a4e97cd Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Thu, 3 Nov 2022 20:50:28 -0500 Subject: [PATCH] Fix logger string truncation with UTF-8 fixes #1365 --- tracelog/tracelog.go | 10 +++++++++- tracelog/tracelog_test.go | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/tracelog/tracelog.go b/tracelog/tracelog.go index d51b9b95..7b19f343 100644 --- a/tracelog/tracelog.go +++ b/tracelog/tracelog.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "time" + "unicode/utf8" "github.com/jackc/pgx/v5" ) @@ -62,6 +63,7 @@ func (f LoggerFunc) Log(ctx context.Context, level LogLevel, msg string, data ma // LogLevelFromString converts log level string to constant // // Valid levels: +// // trace // debug // info @@ -100,7 +102,13 @@ func logQueryArgs(args []any) []any { } case string: if len(v) > 64 { - a = fmt.Sprintf("%s (truncated %d bytes)", v[:64], len(v)-64) + var l int = 0 + for w := 0; l < 64; l += w { + _, w = utf8.DecodeRuneInString(v[l:]) + } + if len(v) > l { + a = fmt.Sprintf("%s (truncated %d bytes)", v[:l], len(v)-l) + } } } logArgs = append(logArgs, a) diff --git a/tracelog/tracelog_test.go b/tracelog/tracelog_test.go index ed0f8eab..ae666066 100644 --- a/tracelog/tracelog_test.go +++ b/tracelog/tracelog_test.go @@ -137,6 +137,48 @@ func TestLogQuery(t *testing.T) { }) } +// https://github.com/jackc/pgx/issues/1365 +func TestLogQueryArgsHandlesUTF8(t *testing.T) { + t.Parallel() + + logger := &testLogger{} + tracer := &tracelog.TraceLog{ + Logger: logger, + LogLevel: tracelog.LogLevelTrace, + } + + ctr := defaultConnTestRunner + ctr.CreateConfig = func(ctx context.Context, t testing.TB) *pgx.ConnConfig { + config := defaultConnTestRunner.CreateConfig(ctx, t) + config.Tracer = tracer + return config + } + + pgxtest.RunWithQueryExecModes(context.Background(), t, ctr, nil, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + logger.logs = logger.logs[0:0] // Clear any logs written when establishing connection + + var s string + for i := 0; i < 63; i++ { + s += "0" + } + s += "😊" + + _, err := conn.Exec(ctx, `select $1::text`, s) + require.NoError(t, err) + require.Len(t, logger.logs, 1) + require.Equal(t, "Query", logger.logs[0].msg) + require.Equal(t, tracelog.LogLevelInfo, logger.logs[0].lvl) + require.Equal(t, s, logger.logs[0].data["args"].([]any)[0]) + + _, err = conn.Exec(ctx, `select $1::text`, s+"000") + require.NoError(t, err) + require.Len(t, logger.logs, 2) + require.Equal(t, "Query", logger.logs[1].msg) + require.Equal(t, tracelog.LogLevelInfo, logger.logs[1].lvl) + require.Equal(t, s+" (truncated 3 bytes)", logger.logs[1].data["args"].([]any)[0]) + }) +} + func TestLogCopyFrom(t *testing.T) { t.Parallel()