github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/app/parse/event.go (about) 1 package parse 2 3 import ( 4 "strings" 5 "time" 6 7 mssql "github.com/denisenkom/go-mssqldb" 8 "github.com/google/uuid" 9 10 "github.com/kyleu/dbaudit/app/statement" 11 "github.com/kyleu/dbaudit/app/util" 12 ) 13 14 type Event struct { 15 EventTime time.Time `db:"event_time,omitempty" json:"eventTime,omitempty"` 16 SessionID int `db:"session_id,omitempty" json:"sessionID,omitempty"` 17 ActionID string `db:"action_id,omitempty" json:"actionID,omitempty"` 18 SequenceGroup mssql.UniqueIdentifier `db:"sequence_group_id" json:"sequenceGroup,omitempty"` 19 SequenceNumber int `db:"sequence_number,omitempty" json:"sequenceNumber,omitempty"` 20 Succeeded bool `db:"succeeded,omitempty" json:"succeeded,omitempty"` 21 ObjectID int `db:"object_id,omitempty" json:"objectID,omitempty"` 22 ClassType string `db:"class_type,omitempty" json:"classType,omitempty"` 23 PrincipalName string `db:"session_server_principal_name,omitempty" json:"principalName,omitempty"` 24 DatabaseName string `db:"database_name,omitempty" json:"databaseName,omitempty"` 25 ObjectName string `db:"object_name,omitempty" json:"objectName,omitempty"` 26 Statement string `db:"statement,omitempty" json:"statement,omitempty"` 27 AdditionalInfo string `db:"additional_information,omitempty" json:"additionalInfo,omitempty"` 28 Filename string `db:"file_name,omitempty" json:"filename,omitempty"` 29 Offset int `db:"audit_file_offset,omitempty" json:"offset,omitempty"` 30 TransactionID int `db:"transaction_id,omitempty" json:"transactionID,omitempty"` 31 ClientIP string `db:"client_ip,omitempty" json:"clientIP,omitempty"` 32 Application string `db:"application_name,omitempty" json:"application,omitempty"` 33 DurationMS int `db:"duration_milliseconds,omitempty" json:"durationMS,omitempty"` 34 ResponseRows int `db:"response_rows,omitempty" json:"responseRows,omitempty"` 35 AffectedRows int `db:"affected_rows,omitempty" json:"affectedRows,omitempty"` 36 ConnectionID mssql.UniqueIdentifier `db:"connection_id,omitempty" json:"connectionID,omitempty"` 37 HostName string `db:"host_name,omitempty" json:"hostName,omitempty"` 38 } 39 40 func (e *Event) ID() uuid.UUID { 41 return util.UUIDFromStringOK(e.SequenceGroup.String()) 42 } 43 44 func (e *Event) Type() string { 45 if e.Statement == "select 1;" { 46 return "healthcheck" 47 } 48 switch strings.ToLower(strings.TrimSpace(e.ActionID)) { 49 case "bst": 50 return "batch_start" 51 case "bcm": 52 return "batch_complete" 53 case "rst": 54 return "proc_start" 55 case "rcm": 56 return "proc_complete" 57 case "trbs": 58 return "tx_begin_start" 59 case "trbc": 60 return "tx_begin_complete" 61 case "trcs": 62 return "tx_commit_start" 63 case "trcc": 64 return "tx_commit_complete" 65 default: 66 return "unknown:" + e.ActionID 67 } 68 } 69 70 func (e *Event) Append(x *Event) { 71 e.Statement += x.Statement 72 } 73 74 func (e *Event) Parsed() (string, util.ValueMap, util.ValueMap, error) { 75 return parseSQL(e.Statement) 76 } 77 78 func (e *Event) ToStatement() *statement.Statement { 79 t := statement.AllActions.Get(e.Type(), nil) 80 conn := util.UUIDFromStringOK(e.ConnectionID.String()) 81 sql, typs, vals, err := e.Parsed() 82 if err != nil { 83 vals = util.ValueMap{"parse_error": err.Error()} 84 } 85 return &statement.Statement{ 86 ID: e.ID(), SessionID: e.SessionID, Action: t, Succeeded: e.Succeeded, Principal: e.PrincipalName, 87 Database: e.DatabaseName, Filename: e.Filename, Host: e.HostName, TransactionID: e.TransactionID, 88 ClientIP: e.ClientIP, Duration: e.DurationMS, ConnectionID: conn, RowsAffected: e.AffectedRows, 89 RowsReturned: e.ResponseRows, SQL: sql, Types: typs, Values: vals, Occurred: e.EventTime, 90 } 91 } 92 93 type Events []*Event 94 95 func (e Events) Collapse() Events { 96 ret := make(Events, 0, len(e)) 97 for _, x := range e { 98 if x.SequenceNumber == 1 { 99 ret = append(ret, x) 100 } else { 101 ret[len(ret)-1].Append(x) 102 } 103 } 104 return ret 105 } 106 107 func (e Events) ToStatements() statement.Statements { 108 ret := make(statement.Statements, 0, len(e)) 109 for _, x := range e { 110 curr := x.ToStatement() 111 switch x.Type() { 112 default: 113 ret = append(ret, curr) 114 } 115 } 116 return ret 117 }