添加查询结果信息

This commit is contained in:
xiaobiao 2022-04-27 14:26:44 +08:00
parent b705210cdb
commit 857f74990b
3 changed files with 67 additions and 47 deletions

View File

@ -16,9 +16,13 @@ type MysqlQueryPiece struct {
VisitDB *string `json:"db"` VisitDB *string `json:"db"`
QuerySQL *string `json:"sql"` QuerySQL *string `json:"sql"`
CostTimeInMS int64 `json:"cms"` CostTimeInMS int64 `json:"cms"`
// SQL执行返回状态 1代表成功-1代表失败, 0代表未知
ResponseStatus int `json:"qrs"`
// SQL执行返回信息成功的时候代表影响行数失败的时候代表错误码
ResponseInfo int `json:"qri"`
} }
func (mqp *MysqlQueryPiece) String() (*string) { func (mqp *MysqlQueryPiece) String() *string {
content := mqp.Bytes() content := mqp.Bytes()
contentStr := hack.String(content) contentStr := hack.String(content)
return &contentStr return &contentStr

View File

@ -11,7 +11,7 @@ import (
"github.com/zr-hebo/sniffer-agent/model" "github.com/zr-hebo/sniffer-agent/model"
) )
type MysqlSession struct { type MySQLSession struct {
connectionID *string connectionID *string
visitUser *string visitUser *string
visitDB *string visitDB *string
@ -39,6 +39,11 @@ type MysqlSession struct {
ignoreAckID int64 ignoreAckID int64
sendSize int64 sendSize int64
// SQL执行返回状态 1代表成功-1代表失败, 0代表未知
responseStatus int
// SQL执行返回信息成功的时候代表影响行数失败的时候代表错误码
responseInfo int
} }
type prepareInfo struct { type prepareInfo struct {
@ -47,8 +52,8 @@ type prepareInfo struct {
func NewMysqlSession( func NewMysqlSession(
sessionKey, clientIP *string, clientPort int, serverIP *string, serverPort int, sessionKey, clientIP *string, clientPort int, serverIP *string, serverPort int,
receiver chan model.QueryPiece) (ms *MysqlSession) { receiver chan model.QueryPiece) (ms *MySQLSession) {
ms = &MysqlSession{ ms = &MySQLSession{
connectionID: sessionKey, connectionID: sessionKey,
clientIP: clientIP, clientIP: clientIP,
clientPort: clientPort, clientPort: clientPort,
@ -60,7 +65,6 @@ func NewMysqlSession(
closeConn: make(chan bool, 1), closeConn: make(chan bool, 1),
expectReceiveSize: -1, expectReceiveSize: -1,
coverRanges: NewCoverRanges(), coverRanges: NewCoverRanges(),
ignoreAckID: -1,
sendSize: 0, sendSize: 0,
pkgCacheLock: sync.Mutex{}, pkgCacheLock: sync.Mutex{},
} }
@ -68,20 +72,11 @@ func NewMysqlSession(
return return
} }
func (ms *MysqlSession) ReceiveTCPPacket(newPkt *model.TCPPacket) { func (ms *MySQLSession) ReceiveTCPPacket(newPkt *model.TCPPacket) {
if newPkt == nil { if newPkt == nil {
return return
} }
if !newPkt.ToServer && ms.ignoreAckID == newPkt.Seq {
// ignore to response to client data
ms.ignoreAckID = ms.ignoreAckID + int64(len(newPkt.Payload))
return
} else if !newPkt.ToServer {
ms.ignoreAckID = newPkt.Seq + int64(len(newPkt.Payload))
}
if newPkt.ToServer { if newPkt.ToServer {
ms.resetBeginTime() ms.resetBeginTime()
ms.readFromClient(newPkt.Seq, newPkt.Payload) ms.readFromClient(newPkt.Seq, newPkt.Payload)
@ -95,25 +90,11 @@ func (ms *MysqlSession) ReceiveTCPPacket(newPkt *model.TCPPacket) {
} }
} }
func (ms *MysqlSession) resetBeginTime() { func (ms *MySQLSession) resetBeginTime() {
ms.stmtBeginTimeNano = time.Now().UnixNano() ms.stmtBeginTimeNano = time.Now().UnixNano()
} }
func (ms *MysqlSession) readFromServer(respSeq int64, bytes []byte) { func (ms *MySQLSession) checkFinish() bool {
if ms.expectSendSize < 1 && len(bytes) > 4 {
ms.expectSendSize = extractMysqlPayloadSize(bytes[:4])
contents := bytes[4:]
if ms.prepareInfo != nil && contents[0] == 0 {
ms.prepareInfo.prepareStmtID = bytesToInt(contents[1:5])
}
}
if ms.coverRanges.head.next == nil || ms.coverRanges.head.next.end != respSeq {
ms.clear()
}
}
func (ms *MysqlSession) checkFinish() bool {
if ms.coverRanges.head == nil || ms.coverRanges.head.next == nil { if ms.coverRanges.head == nil || ms.coverRanges.head.next == nil {
return false return false
} }
@ -126,11 +107,11 @@ func (ms *MysqlSession) checkFinish() bool {
return false return false
} }
func (ms *MysqlSession) Close() { func (ms *MySQLSession) Close() {
ms.clear() ms.clear()
} }
func (ms *MysqlSession) clear() { func (ms *MySQLSession) clear() {
localStmtCache.Enqueue(ms.cachedStmtBytes) localStmtCache.Enqueue(ms.cachedStmtBytes)
ms.cachedStmtBytes = nil ms.cachedStmtBytes = nil
ms.expectReceiveSize = -1 ms.expectReceiveSize = -1
@ -138,12 +119,13 @@ func (ms *MysqlSession) clear() {
ms.prepareInfo = nil ms.prepareInfo = nil
ms.beginSeqID = -1 ms.beginSeqID = -1
ms.endSeqID = -1 ms.endSeqID = -1
ms.ignoreAckID = -1
ms.sendSize = 0 ms.sendSize = 0
ms.coverRanges.clear() ms.coverRanges.clear()
ms.responseStatus = 0
ms.responseInfo = 0
} }
func (ms *MysqlSession) readFromClient(seqID int64, bytes []byte) { func (ms *MySQLSession) readFromClient(seqID int64, bytes []byte) {
contentSize := int64(len(bytes)) contentSize := int64(len(bytes))
if ms.expectReceiveSize == -1 { if ms.expectReceiveSize == -1 {
@ -152,7 +134,7 @@ func (ms *MysqlSession) readFromClient(seqID int64, bytes []byte) {
return return
} }
ms.expectReceiveSize = extractMysqlPayloadSize(bytes[:4]) ms.expectReceiveSize = parseInt3(bytes[:4])
// ignore too big mysql packet // ignore too big mysql packet
if ms.expectReceiveSize >= MaxMySQLPacketLen { if ms.expectReceiveSize >= MaxMySQLPacketLen {
log.Infof("expect receive size is bigger than max deal size: %d", MaxMySQLPacketLen) log.Infof("expect receive size is bigger than max deal size: %d", MaxMySQLPacketLen)
@ -213,11 +195,38 @@ func (ms *MysqlSession) readFromClient(seqID int64, bytes []byte) {
// ms.expectReceiveSize = ms.expectReceiveSize - int(contentSize) // ms.expectReceiveSize = ms.expectReceiveSize - int(contentSize)
} }
func (ms *MySQLSession) readFromServer(respSeq int64, bytes []byte) {
if ms.expectSendSize < 1 && len(bytes) > 4 {
fmt.Printf("%v", bytes)
ms.expectSendSize = parseInt3(bytes[:3])
contents := bytes[4:]
respStatus := contents[0]
// the COM_STMT_PREPARE succeeded
if ms.prepareInfo != nil && respStatus == 0 {
ms.prepareInfo.prepareStmtID = parseInt4(contents[1:5])
} else {
if respStatus == 0x00 || respStatus == 0xfe {
ms.responseStatus = 1
errCode, _, _ := parseLengthEncodedInt(contents[1:])
ms.responseInfo = int(errCode)
} else if respStatus == 0xff {
ms.responseStatus = -1
ms.responseInfo = parseInt2(contents[1:3])
}
}
}
if ms.coverRanges.head.next == nil || ms.coverRanges.head.next.end != respSeq {
ms.clear()
}
}
func IsAuth(val byte) bool { func IsAuth(val byte) bool {
return val > 32 return val > 32
} }
func (ms *MysqlSession) GenerateQueryPiece() (qp model.QueryPiece) { func (ms *MySQLSession) GenerateQueryPiece() (qp model.QueryPiece) {
defer ms.clear() defer ms.clear()
if len(ms.cachedStmtBytes) < 1 { if len(ms.cachedStmtBytes) < 1 {
@ -278,7 +287,7 @@ func (ms *MysqlSession) GenerateQueryPiece() (qp model.QueryPiece) {
log.Infof("prepare statement %s, get id:%d", querySQL, ms.prepareInfo.prepareStmtID) log.Infof("prepare statement %s, get id:%d", querySQL, ms.prepareInfo.prepareStmtID)
case ComStmtExecute: case ComStmtExecute:
prepareStmtID := bytesToInt(ms.cachedStmtBytes[1:5]) prepareStmtID := parseInt4(ms.cachedStmtBytes[1:5])
mqp = ms.composeQueryPiece() mqp = ms.composeQueryPiece()
var ok bool var ok bool
querySQLInBytes, ok = ms.cachedPrepareStmt[prepareStmtID] querySQLInBytes, ok = ms.cachedPrepareStmt[prepareStmtID]
@ -291,7 +300,7 @@ func (ms *MysqlSession) GenerateQueryPiece() (qp model.QueryPiece) {
// log.Debugf("execute prepare statement:%d", prepareStmtID) // log.Debugf("execute prepare statement:%d", prepareStmtID)
case ComStmtClose: case ComStmtClose:
prepareStmtID := bytesToInt(ms.cachedStmtBytes[1:5]) prepareStmtID := parseInt4(ms.cachedStmtBytes[1:5])
delete(ms.cachedPrepareStmt, prepareStmtID) delete(ms.cachedPrepareStmt, prepareStmtID)
log.Infof("remove prepare statement:%d", prepareStmtID) log.Infof("remove prepare statement:%d", prepareStmtID)
@ -334,10 +343,13 @@ func filterQueryPieceBySQL(mqp *model.PooledMysqlQueryPiece, querySQL []byte) *m
return mqp return mqp
} }
func (ms *MysqlSession) composeQueryPiece() (mqp *model.PooledMysqlQueryPiece) { func (ms *MySQLSession) composeQueryPiece() (mqp *model.PooledMysqlQueryPiece) {
clientIP := ms.clientIP clientIP := ms.clientIP
clientPort := ms.clientPort clientPort := ms.clientPort
return model.NewPooledMysqlQueryPiece( mqp = model.NewPooledMysqlQueryPiece(
ms.connectionID, clientIP, ms.visitUser, ms.visitDB, ms.serverIP, ms.connectionID, clientIP, ms.visitUser, ms.visitDB, ms.serverIP,
clientPort, ms.serverPort, communicator.GetMysqlCapturePacketRate(), ms.stmtBeginTimeNano) clientPort, ms.serverPort, communicator.GetMysqlCapturePacketRate(), ms.stmtBeginTimeNano)
mqp.ResponseStatus = ms.responseStatus
mqp.ResponseInfo = ms.responseStatus
return
} }

View File

@ -121,10 +121,14 @@ func parseLengthEncodedInt(b []byte) (num uint64, isNull bool, n int) {
return return
} }
func extractMysqlPayloadSize(header []byte) int { func parseInt2(header []byte) int {
return int(uint32(header[0]) | uint32(header[1])<<8)
}
func parseInt3(header []byte) int {
return int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16) return int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16)
} }
func bytesToInt(contents []byte) int { func parseInt4(contents []byte) int {
return int(uint32(contents[0]) | uint32(contents[1])<<8 | uint32(contents[2])<<16 | uint32(contents[3])<<24) return int(uint32(contents[0]) | uint32(contents[1])<<8 | uint32(contents[2])<<16 | uint32(contents[3])<<24)
} }