github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/trace/metedata.go (about)

     1  // Copyright 2024 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package trace
    16  
    17  import (
    18  	"time"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/common/util"
    21  	"github.com/matrixorigin/matrixone/pkg/pb/api"
    22  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    23  	"github.com/matrixorigin/matrixone/pkg/pb/txn"
    24  )
    25  
    26  var (
    27  	// cannot import catalog, because cycle import
    28  
    29  	complexPKColumnName = "__mo_cpkey_col"
    30  	rowIDColumn         = "__mo_rowid"
    31  	deletePKColumn      = "pk"
    32  	disableColumns      = map[string]struct{}{
    33  		"object_stats":        {},
    34  		"__mo_%1_commit_time": {},
    35  		"%!%mo__meta_loc":     {},
    36  		"delta_loc":           {},
    37  		"segment_id":          {},
    38  		"trunc_pointt":        {},
    39  	}
    40  
    41  	txnCreateEvent               = "created"
    42  	txnActiveEvent               = "active"
    43  	txnClosedEvent               = "closed"
    44  	txnUpdateSnapshotEvent       = "update-snapshot"
    45  	txnExecuteEvent              = "execute"
    46  	txnUpdateSnapshotReasonEvent = "update-snapshot-reason"
    47  	txnNoConflictChanged         = "no-conflict-changed"
    48  	txnConflictChanged           = "conflict-changed"
    49  
    50  	entryApplyEvent         = "apply"
    51  	entryCommitEvent        = "commit"
    52  	entryReadEvent          = "read"
    53  	entryWriteEvent         = "write"
    54  	entryWorkspaceEvent     = "workspace"
    55  	entryReadBlockEvent     = "read-block"
    56  	entryApplyFlushEvent    = "apply-flush"
    57  	entryTransferRowIDEvent = "transfer-row-id"
    58  	entryDeleteObjectEvent  = "apply-delete-object"
    59  )
    60  
    61  func isComplexColumn(name string) bool {
    62  	return name == complexPKColumnName
    63  }
    64  
    65  func isRowIDColumn(name string) bool {
    66  	return name == rowIDColumn
    67  }
    68  
    69  func isDeletePKColumn(name string) bool {
    70  	return name == deletePKColumn
    71  }
    72  
    73  type txnEvent struct {
    74  	ts         int64
    75  	eventType  string
    76  	txnID      []byte
    77  	txnStatus  string
    78  	snapshotTS timestamp.Timestamp
    79  	commitTS   timestamp.Timestamp
    80  	info       string
    81  }
    82  
    83  func newTxnInfoEvent(
    84  	txn txn.TxnMeta,
    85  	eventType string,
    86  	info string) txnEvent {
    87  	e := newTxnEvent(txn, eventType)
    88  	e.info = info
    89  	return e
    90  }
    91  
    92  func newTxnCreated(txn txn.TxnMeta) txnEvent {
    93  	return newTxnEvent(txn, txnCreateEvent)
    94  }
    95  
    96  func newTxnActive(txn txn.TxnMeta) txnEvent {
    97  	return newTxnEvent(txn, txnActiveEvent)
    98  }
    99  
   100  func newTxnClosed(txn txn.TxnMeta) txnEvent {
   101  	return newTxnEvent(txn, txnClosedEvent)
   102  }
   103  
   104  func newTxnSnapshotUpdated(txn txn.TxnMeta) txnEvent {
   105  	return newTxnEvent(txn, txnUpdateSnapshotEvent)
   106  }
   107  
   108  func newTxnEvent(
   109  	txn txn.TxnMeta,
   110  	event string) txnEvent {
   111  	return txnEvent{
   112  		ts:         time.Now().UnixNano(),
   113  		eventType:  event,
   114  		txnID:      txn.ID,
   115  		snapshotTS: txn.SnapshotTS,
   116  		commitTS:   txn.CommitTS,
   117  		txnStatus:  txn.Status.String(),
   118  	}
   119  }
   120  
   121  func (e txnEvent) toCSVRecord(
   122  	cn string,
   123  	buf *buffer,
   124  	records []string) {
   125  	records[0] = buf.writeInt(e.ts)
   126  	records[1] = buf.writeHex(e.txnID)
   127  	records[2] = cn
   128  	records[3] = e.eventType
   129  	records[4] = e.txnStatus
   130  	records[5] = buf.writeTimestamp(e.snapshotTS)
   131  	records[6] = buf.writeTimestamp(e.commitTS)
   132  	records[7] = e.info
   133  }
   134  
   135  type dataEvent struct {
   136  	ts          int64
   137  	eventType   string
   138  	customEntry string
   139  	entryType   api.Entry_EntryType
   140  	tableID     uint64
   141  	txnID       []byte
   142  	row         []byte
   143  	commitTS    timestamp.Timestamp
   144  	snapshotTS  timestamp.Timestamp
   145  }
   146  
   147  func newApplyLogtailEvent(
   148  	ts int64,
   149  	tableID uint64,
   150  	entryType api.Entry_EntryType,
   151  	row []byte,
   152  	commitTS timestamp.Timestamp) dataEvent {
   153  	return dataEvent{
   154  		ts:        ts,
   155  		tableID:   tableID,
   156  		entryType: entryType,
   157  		row:       row,
   158  		commitTS:  commitTS,
   159  		eventType: entryApplyEvent,
   160  	}
   161  }
   162  
   163  func newCommitEntryEvent(
   164  	ts int64,
   165  	txnID []byte,
   166  	tableID uint64,
   167  	entryType api.Entry_EntryType,
   168  	row []byte) dataEvent {
   169  	return dataEvent{
   170  		ts:        ts,
   171  		tableID:   tableID,
   172  		entryType: entryType,
   173  		txnID:     txnID,
   174  		row:       row,
   175  		eventType: entryCommitEvent,
   176  	}
   177  }
   178  
   179  func newReadEntryEvent(
   180  	ts int64,
   181  	txnID []byte,
   182  	tableID uint64,
   183  	row []byte,
   184  	snapshotTS timestamp.Timestamp) dataEvent {
   185  	return dataEvent{
   186  		ts:          ts,
   187  		tableID:     tableID,
   188  		customEntry: "read",
   189  		txnID:       txnID,
   190  		row:         row,
   191  		eventType:   entryReadEvent,
   192  		snapshotTS:  snapshotTS,
   193  	}
   194  }
   195  
   196  func newWriteEntryEvent(
   197  	ts int64,
   198  	txnID []byte,
   199  	typ string,
   200  	tableID uint64,
   201  	row []byte) dataEvent {
   202  	return dataEvent{
   203  		ts:          ts,
   204  		tableID:     tableID,
   205  		customEntry: typ,
   206  		txnID:       txnID,
   207  		row:         row,
   208  		eventType:   entryWriteEvent,
   209  	}
   210  }
   211  
   212  func newWorkspaceEntryEvent(
   213  	ts int64,
   214  	txnID []byte,
   215  	typ string,
   216  	tableID uint64,
   217  	row []byte) dataEvent {
   218  	return dataEvent{
   219  		ts:          ts,
   220  		tableID:     tableID,
   221  		customEntry: typ,
   222  		txnID:       txnID,
   223  		row:         row,
   224  		eventType:   entryWorkspaceEvent,
   225  	}
   226  }
   227  
   228  func newFlushEvent(
   229  	ts int64,
   230  	txnID []byte,
   231  	tableID uint64,
   232  	row []byte) dataEvent {
   233  	return dataEvent{
   234  		ts:        ts,
   235  		txnID:     txnID,
   236  		tableID:   tableID,
   237  		row:       row,
   238  		eventType: entryApplyFlushEvent,
   239  	}
   240  }
   241  
   242  func newReadBlockEvent(
   243  	ts int64,
   244  	txnID []byte,
   245  	tableID uint64,
   246  	row []byte) dataEvent {
   247  	return dataEvent{
   248  		ts:        ts,
   249  		txnID:     txnID,
   250  		tableID:   tableID,
   251  		row:       row,
   252  		eventType: entryReadBlockEvent,
   253  	}
   254  }
   255  
   256  func newTransferEvent(
   257  	ts int64,
   258  	txnID []byte,
   259  	tableID uint64,
   260  	row []byte) dataEvent {
   261  	return dataEvent{
   262  		ts:        ts,
   263  		txnID:     txnID,
   264  		tableID:   tableID,
   265  		row:       row,
   266  		eventType: entryTransferRowIDEvent,
   267  	}
   268  }
   269  
   270  func newDeleteObjectEvent(
   271  	ts int64,
   272  	tableID uint64,
   273  	row []byte) dataEvent {
   274  	return dataEvent{
   275  		ts:        ts,
   276  		tableID:   tableID,
   277  		row:       row,
   278  		eventType: entryDeleteObjectEvent,
   279  	}
   280  }
   281  
   282  func (e dataEvent) toCSVRecord(
   283  	cn string,
   284  	buf *buffer,
   285  	records []string) {
   286  	records[0] = buf.writeInt(e.ts)
   287  	records[1] = cn
   288  	records[2] = e.eventType
   289  	if e.customEntry != "" {
   290  		records[3] = e.customEntry
   291  	} else {
   292  		records[3] = e.entryType.String()
   293  	}
   294  	records[4] = buf.writeUint(e.tableID)
   295  	records[5] = buf.writeHex(e.txnID)
   296  	records[6] = util.UnsafeBytesToString(e.row)
   297  	records[7] = buf.writeTimestamp(e.commitTS)
   298  	records[8] = buf.writeTimestamp(e.snapshotTS)
   299  }
   300  
   301  type actionEvent struct {
   302  	ts        int64
   303  	txnID     []byte
   304  	action    string
   305  	tableID   uint64
   306  	actionSeq uint64
   307  	value     int64
   308  	unit      string
   309  	err       string
   310  }
   311  
   312  func (e actionEvent) toCSVRecord(
   313  	cn string,
   314  	buf *buffer,
   315  	records []string) {
   316  	records[0] = buf.writeInt(e.ts)
   317  	records[1] = buf.writeHex(e.txnID)
   318  	records[2] = cn
   319  	records[3] = buf.writeUint(e.tableID)
   320  	records[4] = e.action
   321  	records[5] = buf.writeUint(e.actionSeq)
   322  	records[6] = buf.writeInt(e.value)
   323  	records[7] = e.unit
   324  	if len(e.err) > 100 {
   325  		e.err = e.err[:100]
   326  	}
   327  	records[8] = e.err
   328  }
   329  
   330  type statement struct {
   331  	ts    int64
   332  	txnID []byte
   333  	sql   string
   334  	cost  int64
   335  }
   336  
   337  func newStatement(
   338  	txnID []byte,
   339  	sql string,
   340  	cost time.Duration) statement {
   341  	return statement{
   342  		ts:    time.Now().UnixNano(),
   343  		txnID: txnID,
   344  		sql:   sql,
   345  		cost:  cost.Microseconds(),
   346  	}
   347  }
   348  
   349  func (e statement) toCSVRecord(
   350  	cn string,
   351  	buf *buffer,
   352  	records []string) {
   353  	records[0] = buf.writeInt(e.ts)
   354  	records[1] = buf.writeHex(e.txnID)
   355  	records[2] = e.sql
   356  	records[3] = buf.writeInt(e.cost)
   357  }
   358  
   359  func truncateSQL(sql string) string {
   360  	if len(sql) > 1000 {
   361  		return sql[:1000]
   362  	}
   363  	return sql
   364  }