Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

server: log last executed prepared stmt when panic (#12905) #14322

Merged
merged 1 commit into from
Jan 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions server/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ type clientConn struct {
dbname string // default database name.
salt []byte // random bytes used for authentication.
alloc arena.Allocator // an memory allocator for reducing memory allocation.
lastCmd string // latest sql query string, currently used for logging error.
lastPacket []byte // latest sql query string, currently used for logging error.
ctx QueryCtx // an interface to execute sql statements.
attrs map[string]string // attributes parsed from client handshake response, not used for now.
status int32 // dispatching/reading/shutdown/waitshutdown
Expand Down Expand Up @@ -612,7 +612,7 @@ func (cc *clientConn) Run(ctx context.Context) {
stackSize := runtime.Stack(buf, false)
buf = buf[:stackSize]
logutil.Logger(ctx).Error("connection running loop panic",
zap.String("lastCmd", cc.lastCmd),
zap.Stringer("lastSQL", getLastStmtInConn{cc}),
zap.Reflect("err", r),
zap.String("stack", string(buf)),
)
Expand Down Expand Up @@ -683,7 +683,7 @@ func (cc *clientConn) Run(ctx context.Context) {
zap.String("connInfo", cc.String()),
zap.String("command", mysql.Command2Str[data[0]]),
zap.String("status", cc.SessionStatusToString()),
zap.String("sql", queryStrForLog(string(data[1:]))),
zap.Stringer("sql", getLastStmtInConn{cc}),
zap.String("err", errStrForLog(err)),
)
err1 := cc.writeError(err)
Expand Down Expand Up @@ -864,9 +864,9 @@ func (cc *clientConn) dispatch(ctx context.Context, data []byte) error {
span := opentracing.StartSpan("server.dispatch")

t := time.Now()
cc.lastPacket = data
cmd := data[0]
data = data[1:]
cc.lastCmd = string(hack.String(data))
token := cc.server.getToken()
defer func() {
// if handleChangeUser failed, cc.ctx may be nil
Expand Down Expand Up @@ -1285,7 +1285,7 @@ func (cc *clientConn) writeResultset(ctx context.Context, rs ResultSet, binary b
buf := make([]byte, 4096)
stackSize := runtime.Stack(buf, false)
buf = buf[:stackSize]
logutil.Logger(ctx).Error("write query result panic", zap.String("lastCmd", cc.lastCmd), zap.String("stack", string(buf)))
logutil.Logger(ctx).Error("write query result panic", zap.Stringer("lastSQL", getLastStmtInConn{cc}), zap.String("stack", string(buf)))
}()
var err error
if mysql.HasCursorExistsFlag(serverStatus) {
Expand Down Expand Up @@ -1515,3 +1515,35 @@ func (cc *clientConn) handleChangeUser(ctx context.Context, data []byte) error {

return cc.writeOK()
}

var _ fmt.Stringer = getLastStmtInConn{}

type getLastStmtInConn struct {
*clientConn
}

func (cc getLastStmtInConn) String() string {
if len(cc.lastPacket) == 0 {
return ""
}
cmd, data := cc.lastPacket[0], cc.lastPacket[1:]
switch cmd {
case mysql.ComInitDB:
return "Use " + string(data)
case mysql.ComFieldList:
return "ListFields " + string(data)
case mysql.ComQuery, mysql.ComStmtPrepare:
return queryStrForLog(string(hack.String(data)))
case mysql.ComStmtExecute, mysql.ComStmtFetch:
stmtID := binary.LittleEndian.Uint32(data[0:4])
return queryStrForLog(cc.preparedStmt2String(stmtID))
case mysql.ComStmtClose, mysql.ComStmtReset:
stmtID := binary.LittleEndian.Uint32(data[0:4])
return mysql.Command2Str[cmd] + " " + strconv.Itoa(int(stmtID))
default:
if cmdStr, ok := mysql.Command2Str[cmd]; ok {
return cmdStr
}
return string(hack.String(data))
}
}
3 changes: 3 additions & 0 deletions server/conn_stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,9 @@ func (cc *clientConn) handleSetOption(data []byte) (err error) {

func (cc *clientConn) preparedStmt2String(stmtID uint32) string {
sv := cc.ctx.GetSessionVars()
if sv == nil {
return ""
}
if prepared, ok := sv.PreparedStmts[stmtID]; ok {
return prepared.Stmt.Text() + sv.PreparedParams.String()
}
Expand Down