Skip to content

Commit d394ee5

Browse files
authored
backend, net: log client versions (#395)
1 parent 37c4701 commit d394ee5

File tree

6 files changed

+68
-5
lines changed

6 files changed

+68
-5
lines changed

pkg/proxy/backend/authenticator.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,12 @@ func (auth *Authenticator) updateCurrentDB(db string) {
411411
auth.dbname = db
412412
}
413413

414+
func (auth *Authenticator) ConnInfo() []zap.Field {
415+
fields := pnet.Attr2ZapFields(auth.attrs)
416+
fields = append(fields, zap.Stringer("capability", auth.capability), zap.Bool("proxy-protocol", auth.proxyProtocol))
417+
return fields
418+
}
419+
414420
func setCompress(packetIO *pnet.PacketIO, capability pnet.Capability, zstdLevel int) error {
415421
algorithm := pnet.CompressionNone
416422
if capability&pnet.ClientCompress > 0 {

pkg/proxy/backend/backend_conn_mgr.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ func (mgr *BackendConnManager) getBackendIO(cctx ConnContext, auth *Authenticato
216216
return nil, errors.Wrapf(err, "dial backend %s error", addr)
217217
}
218218

219-
mgr.logger.Info("connected to backend", zap.String("backend_addr", addr))
220219
// NOTE: should use DNS name as much as possible
221220
// Usually certs are signed with domain instead of IP addrs
222221
// And `RemoteAddr()` will return IP addr
@@ -640,7 +639,7 @@ func (mgr *BackendConnManager) Close() error {
640639
// Just notify it with the current address.
641640
if len(addr) > 0 {
642641
if err := eventReceiver.OnConnClosed(addr, mgr); err != nil {
643-
mgr.logger.Error("close connection error", zap.String("client_addr", addr), zap.NamedError("notify_err", err))
642+
mgr.logger.Error("close connection error", zap.String("backend_addr", addr), zap.NamedError("notify_err", err))
644643
}
645644
}
646645
}
@@ -695,3 +694,13 @@ func (mgr *BackendConnManager) resetQuitSource() {
695694
func (mgr *BackendConnManager) UpdateLogger(fields ...zap.Field) {
696695
mgr.logger = mgr.logger.With(fields...)
697696
}
697+
698+
// ConnInfo returns detailed info of the connection, which should not be logged too many times.
699+
func (mgr *BackendConnManager) ConnInfo() []zap.Field {
700+
var fields []zap.Field
701+
if mgr.authenticator != nil {
702+
fields = mgr.authenticator.ConnInfo()
703+
}
704+
fields = append(fields, zap.String("backend_addr", mgr.ServerAddr()))
705+
return fields
706+
}

pkg/proxy/client/client_conn.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func (cc *ClientConnection) Run(ctx context.Context) {
4949
msg = "new connection failed"
5050
goto clean
5151
}
52+
cc.logger.Info("connected to backend", cc.connMgr.ConnInfo()...)
5253
if err = cc.processMsg(ctx); err != nil {
5354
msg = "fails to relay the connection"
5455
goto clean
@@ -59,7 +60,9 @@ clean:
5960
switch src {
6061
case backend.SrcClientQuit, backend.SrcClientErr, backend.SrcProxyQuit:
6162
default:
62-
cc.logger.Warn(msg, zap.String("backend_addr", cc.connMgr.ServerAddr()), zap.Stringer("quit source", src), zap.Error(err))
63+
fields := cc.connMgr.ConnInfo()
64+
fields = append(fields, zap.Stringer("quit source", src), zap.Error(err))
65+
cc.logger.Warn(msg, fields...)
6366
}
6467
}
6568

pkg/proxy/net/mysql.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/pingcap/tidb/parser/mysql"
1414
"github.com/pingcap/tiproxy/lib/util/errors"
1515
"github.com/siddontang/go/hack"
16+
"go.uber.org/zap"
1617
)
1718

1819
const (
@@ -431,3 +432,32 @@ func IsResultSetOKPacket(firstByte byte, length int) bool {
431432
func IsErrorPacket(firstByte byte) bool {
432433
return firstByte == ErrHeader.Byte()
433434
}
435+
436+
// The connection attribute names that are logged.
437+
// https://dev.mysql.com/doc/mysql-perfschema-excerpt/8.2/en/performance-schema-connection-attribute-tables.html
438+
const (
439+
AttrNameClientVersion = "_client_version" // libmysqlclient & Connector/C++ & Connector/J & Connector/Net & Connector/Python
440+
AttrNameClientName1 = "_client_name" // libmysqlclient & Connector/C++ & Connector/J & Connector/Python & mysqlnd
441+
AttrNameClientName2 = "_program_name" // Connector/Net
442+
AttrNameProgramName = "program_name" // MySQL Client & MySQL Shell
443+
)
444+
445+
// Attr2ZapFields converts connection attributes to log fields.
446+
// We only pick some of them because others may be too sensitive to be logged.
447+
func Attr2ZapFields(attrs map[string]string) []zap.Field {
448+
fields := make([]zap.Field, 0, 3)
449+
if attrs != nil {
450+
if version, ok := attrs[AttrNameClientVersion]; ok {
451+
fields = append(fields, zap.String("client_version", version))
452+
}
453+
if name, ok := attrs[AttrNameClientName1]; ok {
454+
fields = append(fields, zap.String("client_name", name))
455+
} else if name, ok := attrs[AttrNameClientName2]; ok {
456+
fields = append(fields, zap.String("client_name", name))
457+
}
458+
if name, ok := attrs[AttrNameProgramName]; ok {
459+
fields = append(fields, zap.String("program_name", name))
460+
}
461+
}
462+
return fields
463+
}

pkg/proxy/net/mysql_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package net
66
import (
77
"testing"
88

9+
"github.com/pingcap/tiproxy/lib/util/logger"
910
"github.com/stretchr/testify/require"
1011
)
1112

@@ -46,3 +47,17 @@ func TestChangeUserReq(t *testing.T) {
4647
_, err = ParseChangeUser(b, capability)
4748
require.NoError(t, err)
4849
}
50+
51+
func TestLogAttrs(t *testing.T) {
52+
attrs := map[string]string{
53+
AttrNameClientVersion: "8.1.0",
54+
AttrNameClientName1: "libmysql",
55+
AttrNameProgramName: "mysql",
56+
}
57+
lg, text := logger.CreateLoggerForTest(t)
58+
lg.Info("connection info", Attr2ZapFields(attrs)...)
59+
str := text.String()
60+
require.Contains(t, str, `"client_version": "8.1.0"`)
61+
require.Contains(t, str, `"client_name": "libmysql"`)
62+
require.Contains(t, str, `"program_name": "mysql"`)
63+
}

pkg/proxy/proxy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func (s *SQLServer) onConn(ctx context.Context, conn net.Conn, addr string) {
158158
connID := s.mu.connID
159159
s.mu.connID++
160160
logger := s.logger.With(zap.Uint64("connID", connID), zap.String("client_addr", conn.RemoteAddr().String()),
161-
zap.Bool("proxy-protocol", s.mu.proxyProtocol), zap.String("addr", addr))
161+
zap.String("addr", addr))
162162
clientConn := client.NewClientConnection(logger.Named("conn"), conn, s.certMgr.ServerTLS(), s.certMgr.SQLTLS(),
163163
s.hsHandler, connID, addr, &backend.BCConfig{
164164
ProxyProtocol: s.mu.proxyProtocol,
@@ -168,9 +168,9 @@ func (s *SQLServer) onConn(ctx context.Context, conn net.Conn, addr string) {
168168
ConnBufferSize: s.mu.connBufferSize,
169169
})
170170
s.mu.clients[connID] = clientConn
171+
logger.Info("new connection", zap.Bool("proxy-protocol", s.mu.proxyProtocol))
171172
s.mu.Unlock()
172173

173-
logger.Info("new connection")
174174
metrics.ConnGauge.Inc()
175175

176176
defer func() {

0 commit comments

Comments
 (0)