添加查询结果信息
This commit is contained in:
parent
b705210cdb
commit
857f74990b
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
Loading…
Reference in New Issue