| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- package model
- import (
- "context"
- "database/sql"
- "fmt"
- "strings"
- "time"
- "github.com/zeromicro/go-zero/core/stores/sqlx"
- )
- // TSystemLog is the audit log entry of one request/operation. It has no
- // json tags on purpose: the HMAC-SM3 chain signs the marshalled Go field
- // names, which must stay stable (see internal/audit/hmac.go).
- type TSystemLog struct {
- Id int64 `db:"id"` // 自增主键
- Iden string `db:"iden"` // 日志编号
- TraceId string `db:"trace_id"` // 全链路唯一Trace ID
- SpanId string `db:"span_id"` // 本次跨度唯一Span ID
- ParentSpanId sql.NullString `db:"parent_span_id"` // 父SpanID,用于构建调用树
- Type int64 `db:"type"` // 日志类型:1.系统日志;2.接口日志
- ServiceName string `db:"service_name"` // 所属服务或模块名
- UriPath sql.NullString `db:"uri_path"` // 接口请求路径
- HttpMethod sql.NullString `db:"http_method"` // 请求方法:GET/POST/PUT/DELETE
- Method string `db:"method"` // 请求业务方法
- Level string `db:"level"` // 日志级别:DEBUG/INFO/WARN/ERROR
- AppKey sql.NullString `db:"app_key"` // 调用接口应用标识
- UserId sql.NullString `db:"user_id"` // 系统用户ID
- UserName sql.NullString `db:"user_name"` // 系统用户名
- ClientIp sql.NullString `db:"client_ip"` // 客户端IP
- RequestHeader sql.NullString `db:"request_header"` // 请求头,脱敏后
- RequestBodyDigest string `db:"request_body_digest"` // 请求体摘要(SM3)
- RequestBodyFileKey string `db:"request_body_file_key"` // 请求体FileKey
- ResponseCode int64 `db:"response_code"` // 响应业务码
- ResponseBodyDigest string `db:"response_body_digest"` // 响应体摘要(SM3)
- ResponseBodyFileKey string `db:"response_body_file_key"` // 响应体FileKey
- ErrorMessage sql.NullString `db:"error_message"` // 错误提示,仅 ERROR 时填
- DurationMs int64 `db:"duration_ms"` // 本 Span 耗时(毫秒)
- CreatedAt time.Time `db:"created_at"` // 写入时间
- HMac string `db:"h_mac"` // Hmac值
- AuditStatus int64 `db:"audit_status"` // 审计状态:1.未审计;2.审计通过;3.审计异常
- }
- // tSystemLogRows is the full column list.
- var tSystemLogRows = strings.Join([]string{
- "`id`", "`iden`", "`trace_id`", "`span_id`", "`parent_span_id`", "`type`",
- "`service_name`", "`uri_path`", "`http_method`", "`method`", "`level`",
- "`app_key`", "`user_id`", "`user_name`", "`client_ip`", "`request_header`",
- "`request_body_digest`", "`request_body_file_key`", "`response_code`",
- "`response_body_digest`", "`response_body_file_key`", "`error_message`",
- "`duration_ms`", "`created_at`", "`h_mac`", "`audit_status`",
- }, ",")
- // SystemLogFilter mirrors SystemLogListReq; empty fields mean no filtering.
- // TypeValid marks that Type was provided (so type=0 can be an explicit
- // invalid request instead of "unfiltered").
- type SystemLogFilter struct {
- Iden string
- UserName string
- AppKey string
- UriPath string
- HttpMethod string
- CreatedStartTime string
- CreatedEndTime string
- ClientIp string
- ErrorMsg string
- AuditStatus int64
- Type int64
- TypeValid bool
- }
- type TSystemLogModel interface {
- // Insert stores a new audit entry; id and created_at are db generated
- // (created_at default CURRENT_TIMESTAMP, same as sdf-serve).
- Insert(ctx context.Context, data *TSystemLog) (sql.Result, error)
- // FindOneByIden returns the entry with the given iden.
- FindOneByIden(ctx context.Context, iden string) (*TSystemLog, error)
- // FindPage lists entries with optional filters and returns the page and
- // the total count, newest first (created_at DESC).
- FindPage(ctx context.Context, page, pageSize int64, f SystemLogFilter) ([]TSystemLog, int64, error)
- // FindByTraceId returns every entry of one trace, system-log first.
- FindByTraceId(ctx context.Context, traceId string) ([]TSystemLog, error)
- // FindByIdens returns the entries whose iden is contained in idens.
- FindByIdens(ctx context.Context, idens []string) ([]TSystemLog, error)
- // FindForArchive returns entries selected by the id list and/or the
- // created_at range (closed interval), ordered by created_at.
- FindForArchive(ctx context.Context, ids []int64, start, end string) ([]TSystemLog, error)
- // FindAllWithLimit returns up to threshold oldest entries for the
- // automatic archive job.
- FindAllWithLimit(ctx context.Context, threshold int) ([]*TSystemLog, error)
- // DeleteByIds batch-deletes rows by id; meant to run inside a tx.
- DeleteByIds(ctx context.Context, session sqlx.Session, ids []int64) error
- }
- type customTSystemLogModel struct {
- conn sqlx.SqlConn
- table string
- }
- var _ TSystemLogModel = (*customTSystemLogModel)(nil)
- // NewTSystemLogModel returns the model for the t_system_log table.
- func NewTSystemLogModel(conn sqlx.SqlConn) TSystemLogModel {
- return &customTSystemLogModel{
- conn: conn,
- table: "`t_system_log`",
- }
- }
- // tSystemLogInsertColumns is the insert column list; id and created_at are
- // generated by the database.
- func tSystemLogInsertColumns() string {
- return strings.Join([]string{
- "`iden`", "`trace_id`", "`span_id`", "`parent_span_id`", "`type`",
- "`service_name`", "`uri_path`", "`http_method`", "`method`", "`level`",
- "`app_key`", "`user_id`", "`user_name`", "`client_ip`", "`request_header`",
- "`request_body_digest`", "`request_body_file_key`", "`response_code`",
- "`response_body_digest`", "`response_body_file_key`", "`error_message`",
- "`duration_ms`", "`h_mac`", "`audit_status`",
- }, ",")
- }
- func (m *customTSystemLogModel) Insert(ctx context.Context, data *TSystemLog) (sql.Result, error) {
- query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- m.table, tSystemLogInsertColumns())
- ret, err := m.conn.ExecCtx(ctx, query,
- data.Iden, data.TraceId, data.SpanId, data.ParentSpanId, data.Type,
- data.ServiceName, data.UriPath, data.HttpMethod, data.Method, data.Level,
- data.AppKey, data.UserId, data.UserName, data.ClientIp, data.RequestHeader,
- data.RequestBodyDigest, data.RequestBodyFileKey, data.ResponseCode,
- data.ResponseBodyDigest, data.ResponseBodyFileKey, data.ErrorMessage,
- data.DurationMs, data.HMac, data.AuditStatus)
- return ret, err
- }
- func (m *customTSystemLogModel) FindOneByIden(ctx context.Context, iden string) (*TSystemLog, error) {
- var resp TSystemLog
- query := fmt.Sprintf("select %s from %s where `iden` = ? limit 1", tSystemLogRows, m.table)
- err := m.conn.QueryRowCtx(ctx, &resp, query, iden)
- switch err {
- case nil:
- return &resp, nil
- case sqlx.ErrNotFound:
- return nil, ErrNotFound
- default:
- return nil, err
- }
- }
- func (m *customTSystemLogModel) FindPage(ctx context.Context, page, pageSize int64, f SystemLogFilter) ([]TSystemLog, int64, error) {
- var conds []string
- var args []any
- if f.Iden != "" {
- conds = append(conds, "`iden` = ?")
- args = append(args, f.Iden)
- }
- if f.UserName != "" {
- conds = append(conds, "`user_name` like ? escape '\\\\'")
- args = append(args, "%"+escapeLike(f.UserName)+"%")
- }
- if f.AppKey != "" {
- conds = append(conds, "`app_key` = ?")
- args = append(args, f.AppKey)
- }
- if f.CreatedStartTime != "" {
- conds = append(conds, "`created_at` >= ?")
- args = append(args, f.CreatedStartTime)
- }
- if f.CreatedEndTime != "" {
- conds = append(conds, "`created_at` <= ?")
- args = append(args, f.CreatedEndTime)
- }
- if f.UriPath != "" {
- conds = append(conds, "`uri_path` = ?")
- args = append(args, f.UriPath)
- }
- if f.HttpMethod != "" {
- conds = append(conds, "`http_method` = ?")
- args = append(args, f.HttpMethod)
- }
- if f.ClientIp != "" {
- conds = append(conds, "`client_ip` = ?")
- args = append(args, f.ClientIp)
- }
- if f.ErrorMsg != "" {
- conds = append(conds, "`error_message` like ? escape '\\\\'")
- args = append(args, "%"+escapeLike(f.ErrorMsg)+"%")
- }
- if f.AuditStatus != 0 {
- conds = append(conds, "`audit_status` = ?")
- args = append(args, f.AuditStatus)
- }
- if f.TypeValid {
- conds = append(conds, "`type` = ?")
- args = append(args, f.Type)
- }
- where := ""
- if len(conds) > 0 {
- where = " where " + strings.Join(conds, " and ")
- }
- var total int64
- if err := m.conn.QueryRowCtx(ctx, &total, fmt.Sprintf("select count(*) from %s%s", m.table, where), args...); err != nil {
- return nil, 0, err
- }
- if total == 0 {
- return nil, 0, nil
- }
- offset := (page - 1) * pageSize
- args = append(args, pageSize, offset)
- query := fmt.Sprintf("select %s from %s%s order by `created_at` desc limit ? offset ?", tSystemLogRows, m.table, where)
- var resp []TSystemLog
- if err := m.conn.QueryRowsCtx(ctx, &resp, query, args...); err != nil {
- return nil, 0, err
- }
- return resp, total, nil
- }
- func (m *customTSystemLogModel) FindByTraceId(ctx context.Context, traceId string) ([]TSystemLog, error) {
- var resp []TSystemLog
- query := fmt.Sprintf(
- "select %s from %s where `trace_id` = ? order by case `type` when 1 then 0 when 2 then 1 else 2 end, `id` asc",
- tSystemLogRows, m.table)
- if err := m.conn.QueryRowsCtx(ctx, &resp, query, traceId); err != nil {
- return nil, err
- }
- return resp, nil
- }
- func (m *customTSystemLogModel) FindByIdens(ctx context.Context, idens []string) ([]TSystemLog, error) {
- placeholders := strings.TrimSuffix(strings.Repeat("?,", len(idens)), ",")
- args := make([]any, len(idens))
- for i, v := range idens {
- args[i] = v
- }
- var resp []TSystemLog
- query := fmt.Sprintf("select %s from %s where `iden` in (%s)", tSystemLogRows, m.table, placeholders)
- if err := m.conn.QueryRowsCtx(ctx, &resp, query, args...); err != nil {
- return nil, err
- }
- return resp, nil
- }
- func (m *customTSystemLogModel) FindForArchive(ctx context.Context, ids []int64, start, end string) ([]TSystemLog, error) {
- var conds []string
- var args []any
- if len(ids) > 0 {
- placeholders := strings.TrimSuffix(strings.Repeat("?,", len(ids)), ",")
- conds = append(conds, "`id` in ("+placeholders+")")
- for _, v := range ids {
- args = append(args, v)
- }
- }
- if start != "" && end != "" {
- conds = append(conds, "`created_at` >= ? and `created_at` <= ?")
- args = append(args, start, end)
- }
- where := ""
- if len(conds) > 0 {
- where = " where " + strings.Join(conds, " and ")
- }
- var resp []TSystemLog
- query := fmt.Sprintf("select %s from %s%s order by `created_at` asc", tSystemLogRows, m.table, where)
- if err := m.conn.QueryRowsCtx(ctx, &resp, query, args...); err != nil {
- return nil, err
- }
- return resp, nil
- }
- func (m *customTSystemLogModel) FindAllWithLimit(ctx context.Context, threshold int) ([]*TSystemLog, error) {
- var resp []*TSystemLog
- query := fmt.Sprintf("select %s from %s order by `created_at` asc limit ?", tSystemLogRows, m.table)
- if err := m.conn.QueryRowsCtx(ctx, &resp, query, threshold); err != nil {
- return nil, err
- }
- return resp, nil
- }
- func (m *customTSystemLogModel) DeleteByIds(ctx context.Context, session sqlx.Session, ids []int64) error {
- const deleteBatchSize = 1000
- for i := 0; i < len(ids); i += deleteBatchSize {
- end := i + deleteBatchSize
- if end > len(ids) {
- end = len(ids)
- }
- batchIds := ids[i:end]
- placeholders := strings.TrimSuffix(strings.Repeat("?,", len(batchIds)), ",")
- query := fmt.Sprintf("delete from t_system_log where id in (%s)", placeholders)
- args := make([]interface{}, len(batchIds))
- for j, v := range batchIds {
- args[j] = v
- }
- if _, err := session.ExecCtx(ctx, query, args...); err != nil {
- return err
- }
- }
- return nil
- }
|