Skip to content

Commit

Permalink
*: add telemetry support for account lock/unlock (#37344)
Browse files Browse the repository at this point in the history
close #37324
  • Loading branch information
CbcWestwolf authored Sep 7, 2022
1 parent 2959158 commit 62480cf
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 0 deletions.
11 changes: 11 additions & 0 deletions executor/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ type TelemetryInfo struct {
UseRecursive bool
UseMultiSchemaChange bool
PartitionTelemetry *PartitionTelemetryInfo
AccountLockTelemetry *AccountLockTelemetryInfo
}

// PartitionTelemetryInfo records table partition telemetry information during execution.
Expand All @@ -207,6 +208,16 @@ type PartitionTelemetryInfo struct {
TablePartitionMaxPartitionsNum uint64
}

// AccountLockTelemetryInfo records account lock/unlock information during execution
type AccountLockTelemetryInfo struct {
// The number of CREATE/ALTER USER statements that lock the user
LockUser int64
// The number of CREATE/ALTER USER statements that unlock the user
UnlockUser int64
// The number of CREATE/ALTER USER statements
CreateOrAlterUser int64
}

// ExecStmt implements the sqlexec.Statement interface, it builds a planner.Plan to an sqlexec.Statement.
type ExecStmt struct {
// GoCtx stores parent go context.Context for a stmt.
Expand Down
23 changes: 23 additions & 0 deletions executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,29 @@ func (b *executorBuilder) buildSimple(v *plannercore.Simple) Executor {
return b.buildRevoke(s)
case *ast.BRIEStmt:
return b.buildBRIE(s, v.Schema())
case *ast.CreateUserStmt, *ast.AlterUserStmt:
var lockOptions []*ast.PasswordOrLockOption
if b.Ti.AccountLockTelemetry == nil {
b.Ti.AccountLockTelemetry = &AccountLockTelemetryInfo{}
}
b.Ti.AccountLockTelemetry.CreateOrAlterUser += 1
if stmt, ok := v.Statement.(*ast.CreateUserStmt); ok {
lockOptions = stmt.PasswordOrLockOptions
} else if stmt, ok := v.Statement.(*ast.AlterUserStmt); ok {
lockOptions = stmt.PasswordOrLockOptions
}
if len(lockOptions) > 0 {
// Multiple lock options are supported for the parser, but only the last one option takes effect.
for i := len(lockOptions) - 1; i >= 0; i-- {
if lockOptions[i].Type == ast.Lock {
b.Ti.AccountLockTelemetry.LockUser += 1
break
} else if lockOptions[i].Type == ast.Unlock {
b.Ti.AccountLockTelemetry.UnlockUser += 1
break
}
}
}
}
base := newBaseExecutor(b.ctx, v.Schema(), v.ID())
base.initCap = chunk.ZeroCapacity
Expand Down
1 change: 1 addition & 0 deletions metrics/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ const (
LblVersion = "version"
LblHash = "hash"
LblCTEType = "cte_type"
LblAccountLock = "account_lock"
LblIdle = "idle"
LblRunning = "executing_sql"
LblLockWaiting = "waiting_for_lock"
Expand Down
32 changes: 32 additions & 0 deletions metrics/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ var (
Name: "table_partition_max_partition_usage",
Help: "Counter of partitions created by CREATE TABLE statements",
})
TelemetryAccountLockCnt = prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: "tidb",
Subsystem: "telemetry",
Name: "account_lock_usage",
Help: "Counter of locked/unlocked users",
}, []string{LblAccountLock})
)

// readCounter reads the value of a prometheus.Counter.
Expand Down Expand Up @@ -125,6 +132,31 @@ func GetCTECounter() CTEUsageCounter {
}
}

// AccountLockCounter records the number of lock users/roles
type AccountLockCounter struct {
LockUser int64 `json:"lockUser"`
UnlockUser int64 `json:"unlockUser"`
CreateOrAlterUser int64 `json:"createOrAlterUser"`
}

// Sub returns the difference of two counters.
func (c AccountLockCounter) Sub(rhs AccountLockCounter) AccountLockCounter {
return AccountLockCounter{
LockUser: c.LockUser - rhs.LockUser,
UnlockUser: c.UnlockUser - rhs.UnlockUser,
CreateOrAlterUser: c.CreateOrAlterUser - rhs.CreateOrAlterUser,
}
}

// GetAccountLockCounter gets the AccountLockCounter
func GetAccountLockCounter() AccountLockCounter {
return AccountLockCounter{
LockUser: readCounter(TelemetryAccountLockCnt.With(prometheus.Labels{LblAccountLock: "lockUser"})),
UnlockUser: readCounter(TelemetryAccountLockCnt.With(prometheus.Labels{LblAccountLock: "unlockUser"})),
CreateOrAlterUser: readCounter(TelemetryAccountLockCnt.With(prometheus.Labels{LblAccountLock: "createOrAlterUser"})),
}
}

// MultiSchemaChangeUsageCounter records the usages of multi-schema change.
type MultiSchemaChangeUsageCounter struct {
MultiSchemaChangeUsed int64 `json:"multi_schema_change_used"`
Expand Down
9 changes: 9 additions & 0 deletions session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ var (
telemetryTablePartitionRangeColumnsUsage = metrics.TelemetryTablePartitionRangeColumnsCnt
telemetryTablePartitionListColumnsUsage = metrics.TelemetryTablePartitionListColumnsCnt
telemetryTablePartitionMaxPartitionsUsage = metrics.TelemetryTablePartitionMaxPartitionsCnt
telemetryLockUserUsage = metrics.TelemetryAccountLockCnt.WithLabelValues("lockUser")
telemetryUnlockUserUsage = metrics.TelemetryAccountLockCnt.WithLabelValues("unlockUser")
telemetryCreateOrAlterUserUsage = metrics.TelemetryAccountLockCnt.WithLabelValues("createOrAlterUser")
)

// Session context, it is consistent with the lifecycle of a client connection.
Expand Down Expand Up @@ -3304,6 +3307,12 @@ func (s *session) updateTelemetryMetric(es *executor.ExecStmt) {
telemetryTablePartitionListColumnsUsage.Inc()
}
}

if ti.AccountLockTelemetry != nil {
telemetryLockUserUsage.Add(float64(ti.AccountLockTelemetry.LockUser))
telemetryUnlockUserUsage.Add(float64(ti.AccountLockTelemetry.UnlockUser))
telemetryCreateOrAlterUserUsage.Add(float64(ti.AccountLockTelemetry.CreateOrAlterUser))
}
}

// GetBuiltinFunctionUsage returns the replica of counting of builtin function usage
Expand Down
1 change: 1 addition & 0 deletions telemetry/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func generateTelemetryData(sctx sessionctx.Context, trackingID string) telemetry
func postReportTelemetryData() {
postReportTxnUsage()
postReportCTEUsage()
postReportAccountLockUsage()
postReportMultiSchemaChangeUsage()
postReportTablePartitionUsage()
postReportSlowQueryStats()
Expand Down
15 changes: 15 additions & 0 deletions telemetry/data_feature_usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type featureUsage struct {
NewClusterIndex *NewClusterIndexUsage `json:"newClusterIndex"`
TemporaryTable bool `json:"temporaryTable"`
CTE *m.CTEUsageCounter `json:"cte"`
AccountLock *m.AccountLockCounter `json:"accountLock"`
CachedTable bool `json:"cachedTable"`
AutoCapture bool `json:"autoCapture"`
PlacementPolicyUsage *placementPolicyUsage `json:"placementPolicy"`
Expand Down Expand Up @@ -76,6 +77,8 @@ func getFeatureUsage(ctx context.Context, sctx sessionctx.Context) (*featureUsag

usage.CTE = getCTEUsageInfo()

usage.AccountLock = getAccountLockUsageInfo()

usage.MultiSchemaChange = getMultiSchemaChangeUsageInfo()

usage.TablePartition = getTablePartitionUsageInfo()
Expand Down Expand Up @@ -218,6 +221,7 @@ type TxnUsage struct {

var initialTxnCommitCounter metrics.TxnCommitCounter
var initialCTECounter m.CTEUsageCounter
var initialAccountLockCounter m.AccountLockCounter
var initialNonTransactionalCounter m.NonTransactionalStmtCounter
var initialMultiSchemaChangeCounter m.MultiSchemaChangeUsageCounter
var initialTablePartitionCounter m.TablePartitionUsageCounter
Expand Down Expand Up @@ -266,6 +270,10 @@ func postReportCTEUsage() {
initialCTECounter = m.GetCTECounter()
}

func postReportAccountLockUsage() {
initialAccountLockCounter = m.GetAccountLockCounter()
}

// PostSavepointCount exports for testing.
func PostSavepointCount() {
initialSavepointStmtCounter = m.GetSavepointStmtCounter()
Expand All @@ -282,6 +290,13 @@ func getCTEUsageInfo() *m.CTEUsageCounter {
return &diff
}

// getAccountLockUsageInfo gets the AccountLock usages.
func getAccountLockUsageInfo() *m.AccountLockCounter {
curr := m.GetAccountLockCounter()
diff := curr.Sub(initialAccountLockCounter)
return &diff
}

func postReportMultiSchemaChangeUsage() {
initialMultiSchemaChangeCounter = m.GetMultiSchemaCounter()
}
Expand Down
27 changes: 27 additions & 0 deletions telemetry/data_feature_usage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,33 @@ func TestCachedTable(t *testing.T) {
require.False(t, usage.CachedTable)
}

func TestAccountLock(t *testing.T) {
store := testkit.CreateMockStore(t)

tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

usage, err := telemetry.GetFeatureUsage(tk.Session())
require.NoError(t, err)
require.Equal(t, int64(0), usage.AccountLock.LockUser)
require.Equal(t, int64(0), usage.AccountLock.UnlockUser)
require.Equal(t, int64(0), usage.AccountLock.CreateOrAlterUser)

tk.MustExec("drop user if exists testUser")
tk.MustExec("create user testUser account lock")
usage, err = telemetry.GetFeatureUsage(tk.Session())
require.NoError(t, err)
require.Equal(t, int64(1), usage.AccountLock.LockUser)
require.Equal(t, int64(0), usage.AccountLock.UnlockUser)
require.Equal(t, int64(1), usage.AccountLock.CreateOrAlterUser)
tk.MustExec("alter user testUser account unlock")
usage, err = telemetry.GetFeatureUsage(tk.Session())
require.NoError(t, err)
require.Equal(t, int64(1), usage.AccountLock.LockUser)
require.Equal(t, int64(1), usage.AccountLock.UnlockUser)
require.Equal(t, int64(2), usage.AccountLock.CreateOrAlterUser)
}

func TestMultiSchemaChange(t *testing.T) {
store := testkit.CreateMockStore(t)

Expand Down

0 comments on commit 62480cf

Please sign in to comment.