diff --git a/executor/compiler.go b/executor/compiler.go index 17c09041a5932..894e86e6b7ba8 100644 --- a/executor/compiler.go +++ b/executor/compiler.go @@ -31,16 +31,17 @@ import ( ) var ( - stmtNodeCounterUse = metrics.StmtNodeCounter.WithLabelValues("Use") - stmtNodeCounterShow = metrics.StmtNodeCounter.WithLabelValues("Show") - stmtNodeCounterBegin = metrics.StmtNodeCounter.WithLabelValues("Begin") - stmtNodeCounterCommit = metrics.StmtNodeCounter.WithLabelValues("Commit") - stmtNodeCounterRollback = metrics.StmtNodeCounter.WithLabelValues("Rollback") - stmtNodeCounterInsert = metrics.StmtNodeCounter.WithLabelValues("Insert") - stmtNodeCounterReplace = metrics.StmtNodeCounter.WithLabelValues("Replace") - stmtNodeCounterDelete = metrics.StmtNodeCounter.WithLabelValues("Delete") - stmtNodeCounterUpdate = metrics.StmtNodeCounter.WithLabelValues("Update") - stmtNodeCounterSelect = metrics.StmtNodeCounter.WithLabelValues("Select") + stmtNodeCounterUse = metrics.StmtNodeCounter.WithLabelValues("Use") + stmtNodeCounterShow = metrics.StmtNodeCounter.WithLabelValues("Show") + stmtNodeCounterBegin = metrics.StmtNodeCounter.WithLabelValues("Begin") + stmtNodeCounterCommit = metrics.StmtNodeCounter.WithLabelValues("Commit") + stmtNodeCounterRollback = metrics.StmtNodeCounter.WithLabelValues("Rollback") + stmtNodeCounterInsert = metrics.StmtNodeCounter.WithLabelValues("Insert") + stmtNodeCounterReplace = metrics.StmtNodeCounter.WithLabelValues("Replace") + stmtNodeCounterDelete = metrics.StmtNodeCounter.WithLabelValues("Delete") + stmtNodeCounterUpdate = metrics.StmtNodeCounter.WithLabelValues("Update") + stmtNodeCounterSelect = metrics.StmtNodeCounter.WithLabelValues("Select") + stmtNodeCounterSavepoint = metrics.StmtNodeCounter.WithLabelValues("Savepoint") ) // Compiler compiles an ast.StmtNode to a physical plan. @@ -174,6 +175,8 @@ func CountStmtNode(stmtNode ast.StmtNode, inRestrictedSQL bool) { stmtNodeCounterUpdate.Inc() case "Select": stmtNodeCounterSelect.Inc() + case "Savepoint": + stmtNodeCounterSavepoint.Inc() default: metrics.StmtNodeCounter.WithLabelValues(typeLabel).Inc() } @@ -411,6 +414,8 @@ func GetStmtLabel(stmtNode ast.StmtNode) string { return "Trace" case *ast.ShutdownStmt: return "Shutdown" + case *ast.SavepointStmt: + return "Savepoint" } return "other" } diff --git a/metrics/telemetry.go b/metrics/telemetry.go index 79bcbf7c9f9a1..e67af80d57204 100644 --- a/metrics/telemetry.go +++ b/metrics/telemetry.go @@ -112,3 +112,8 @@ func GetNonTransactionalStmtCounter() NonTransactionalStmtCounter { DeleteCount: readCounter(NonTransactionalDeleteCount), } } + +// GetSavepointStmtCounter gets the savepoint statement executed counter. +func GetSavepointStmtCounter() int64 { + return readCounter(StmtNodeCounter.With(prometheus.Labels{LblType: "Savepoint"})) +} diff --git a/telemetry/data.go b/telemetry/data.go index b1ef37c7a009e..119293560b631 100644 --- a/telemetry/data.go +++ b/telemetry/data.go @@ -63,4 +63,5 @@ func postReportTelemetryData() { postReportMultiSchemaChangeUsage() postReportSlowQueryStats() postReportNonTransactionalCounter() + PostSavepointCount() } diff --git a/telemetry/data_feature_usage.go b/telemetry/data_feature_usage.go index 3dc122adf8e04..7caf0dd286314 100644 --- a/telemetry/data_feature_usage.go +++ b/telemetry/data_feature_usage.go @@ -209,12 +209,14 @@ type TxnUsage struct { MutationCheckerUsed bool `json:"mutationCheckerUsed"` AssertionLevel string `json:"assertionLevel"` RcCheckTS bool `json:"rcCheckTS"` + SavepointCounter int64 `json:"SavepointCounter"` } var initialTxnCommitCounter metrics.TxnCommitCounter var initialCTECounter m.CTEUsageCounter var initialNonTransactionalCounter m.NonTransactionalStmtCounter var initialMultiSchemaChangeCounter m.MultiSchemaChangeUsageCounter +var initialSavepointStmtCounter int64 // getTxnUsageInfo gets the usage info of transaction related features. It's exported for tests. func getTxnUsageInfo(ctx sessionctx.Context) *TxnUsage { @@ -240,7 +242,9 @@ func getTxnUsageInfo(ctx sessionctx.Context) *TxnUsage { if val, err := variable.GetGlobalSystemVar(ctx.GetSessionVars(), variable.TiDBRCReadCheckTS); err == nil { rcCheckTSUsed = val == variable.On } - return &TxnUsage{asyncCommitUsed, onePCUsed, diff, mutationCheckerUsed, assertionUsed, rcCheckTSUsed} + currSavepointCount := m.GetSavepointStmtCounter() + diffSavepointCount := currSavepointCount - initialSavepointStmtCounter + return &TxnUsage{asyncCommitUsed, onePCUsed, diff, mutationCheckerUsed, assertionUsed, rcCheckTSUsed, diffSavepointCount} } func postReportTxnUsage() { @@ -251,6 +255,11 @@ func postReportCTEUsage() { initialCTECounter = m.GetCTECounter() } +// PostSavepointCount exports for testing. +func PostSavepointCount() { + initialSavepointStmtCounter = m.GetSavepointStmtCounter() +} + // getCTEUsageInfo gets the CTE usages. func getCTEUsageInfo() *m.CTEUsageCounter { curr := m.GetCTECounter() diff --git a/telemetry/data_feature_usage_test.go b/telemetry/data_feature_usage_test.go index 96a39c4e77a19..5c50756ebcd59 100644 --- a/telemetry/data_feature_usage_test.go +++ b/telemetry/data_feature_usage_test.go @@ -394,3 +394,23 @@ func TestPagingUsageInfo(t *testing.T) { require.NoError(t, err) require.False(t, usage.EnablePaging) } + +func TestTxnSavepointUsageInfo(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("savepoint sp1") + tk.MustExec("savepoint sp2") + txnUsage := telemetry.GetTxnUsageInfo(tk.Session()) + require.Equal(t, int64(2), txnUsage.SavepointCounter) + + tk.MustExec("savepoint sp3") + txnUsage = telemetry.GetTxnUsageInfo(tk.Session()) + require.Equal(t, int64(3), txnUsage.SavepointCounter) + + telemetry.PostSavepointCount() + tk.MustExec("savepoint sp1") + txnUsage = telemetry.GetTxnUsageInfo(tk.Session()) + require.Equal(t, int64(1), txnUsage.SavepointCounter) +}