diff --git a/go/vt/vttablet/tabletmanager/rpc_transaction_test.go b/go/vt/vttablet/tabletmanager/rpc_transaction_test.go index 3d697b6fa30..567a6561ec5 100644 --- a/go/vt/vttablet/tabletmanager/rpc_transaction_test.go +++ b/go/vt/vttablet/tabletmanager/rpc_transaction_test.go @@ -38,7 +38,7 @@ func TestTabletManager_UnresolvedTransactions(t *testing.T) { BatchCtx: ctx, } close(tm._waitForGrantsComplete) - tm.tmState = newTMState(tm, newTestTablet(t, 100, "ks", "-80")) + tm.tmState = newTMState(tm, newTestTablet(t, 100, "ks", "-80", nil)) _, err := tm.GetUnresolvedTransactions(ctx, 0) require.NoError(t, err) @@ -56,7 +56,7 @@ func TestTabletManager_ReadTransaction(t *testing.T) { BatchCtx: ctx, } close(tm._waitForGrantsComplete) - tm.tmState = newTMState(tm, newTestTablet(t, 100, "ks", "-80")) + tm.tmState = newTMState(tm, newTestTablet(t, 100, "ks", "-80", nil)) _, err := tm.ReadTransaction(ctx, &tabletmanagerdatapb.ReadTransactionRequest{ Dtid: "dtid01", @@ -76,7 +76,7 @@ func TestTabletManager_ConcludeTransaction(t *testing.T) { BatchCtx: ctx, } close(tm._waitForGrantsComplete) - tm.tmState = newTMState(tm, newTestTablet(t, 100, "ks", "-80")) + tm.tmState = newTMState(tm, newTestTablet(t, 100, "ks", "-80", nil)) err := tm.ConcludeTransaction(ctx, &tabletmanagerdatapb.ConcludeTransactionRequest{ Dtid: "dtid01", diff --git a/go/vt/vttablet/tabletmanager/shard_sync_test.go b/go/vt/vttablet/tabletmanager/shard_sync_test.go index 24078efa977..40a62d06b76 100644 --- a/go/vt/vttablet/tabletmanager/shard_sync_test.go +++ b/go/vt/vttablet/tabletmanager/shard_sync_test.go @@ -48,7 +48,7 @@ func TestShardSync(t *testing.T) { defer cancel() ts := memorytopo.NewServer(ctx, "cell1") statsTabletTypeCount.ResetAll() - tm := newTestTM(t, ts, 100, keyspace, shard) + tm := newTestTM(t, ts, 100, keyspace, shard, nil) defer tm.Stop() // update the primary info in the shard record and set it to nil diff --git a/go/vt/vttablet/tabletmanager/tm_init.go b/go/vt/vttablet/tabletmanager/tm_init.go index 2e70596b686..5433740d1c4 100644 --- a/go/vt/vttablet/tabletmanager/tm_init.go +++ b/go/vt/vttablet/tabletmanager/tm_init.go @@ -123,6 +123,9 @@ var ( // statsIsInSrvKeyspace is set to 1 (true), 0 (false) whether the tablet is in the serving keyspace statsIsInSrvKeyspace *stats.Gauge + // statsTabletTags is set to 1 (true) if a tablet tag exists. + statsTabletTags *stats.GaugesWithMultiLabels + statsKeyspace = stats.NewString("TabletKeyspace") statsShard = stats.NewString("TabletShard") statsKeyRangeStart = stats.NewString("TabletKeyRangeStart") @@ -142,6 +145,7 @@ func init() { statsTabletTypeCount = stats.NewCountersWithSingleLabel("TabletTypeCount", "Number of times the tablet changed to the labeled type", "type") statsBackupIsRunning = stats.NewGaugesWithMultiLabels("BackupIsRunning", "Whether a backup is running", []string{"mode"}) statsIsInSrvKeyspace = stats.NewGauge("IsInSrvKeyspace", "Whether the vttablet is in the serving keyspace (1 = true / 0 = false)") + statsTabletTags = stats.NewGaugesWithMultiLabels("TabletTags", "Tablet tags key/values", []string{"key", "value"}) } // TabletManager is the main class for the tablet manager. @@ -889,6 +893,9 @@ func (tm *TabletManager) exportStats() { statsKeyRangeEnd.Set(hex.EncodeToString(tablet.KeyRange.End)) } statsAlias.Set(topoproto.TabletAliasString(tablet.Alias)) + for k, v := range tablet.Tags { + statsTabletTags.Set([]string{k, v}, 1) + } } // withRetry will exponentially back off and retry a function upon diff --git a/go/vt/vttablet/tabletmanager/tm_init_test.go b/go/vt/vttablet/tabletmanager/tm_init_test.go index d0c0075eda3..b8c9c54dcc2 100644 --- a/go/vt/vttablet/tabletmanager/tm_init_test.go +++ b/go/vt/vttablet/tabletmanager/tm_init_test.go @@ -173,7 +173,7 @@ func TestStartCreateKeyspaceShard(t *testing.T) { statsTabletTypeCount.ResetAll() cell := "cell1" ts := memorytopo.NewServer(ctx, cell) - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) defer tm.Stop() assert.Equal(t, "replica", statsTabletType.Get()) @@ -193,7 +193,7 @@ func TestStartCreateKeyspaceShard(t *testing.T) { // keyspace-shard already created. _, err = ts.GetOrCreateShard(ctx, "ks1", "0") require.NoError(t, err) - tm = newTestTM(t, ts, 2, "ks1", "0") + tm = newTestTM(t, ts, 2, "ks1", "0", nil) defer tm.Stop() _, err = ts.GetShard(ctx, "ks1", "0") require.NoError(t, err) @@ -207,7 +207,7 @@ func TestStartCreateKeyspaceShard(t *testing.T) { require.NoError(t, err) err = topotools.RebuildKeyspace(ctx, logutil.NewConsoleLogger(), ts, "ks2", []string{cell}, false) require.NoError(t, err) - tm = newTestTM(t, ts, 3, "ks2", "0") + tm = newTestTM(t, ts, 3, "ks2", "0", nil) defer tm.Stop() _, err = ts.GetShard(ctx, "ks2", "0") require.NoError(t, err) @@ -224,7 +224,7 @@ func TestStartCreateKeyspaceShard(t *testing.T) { require.NoError(t, err) err = ts.RebuildSrvVSchema(ctx, []string{cell}) require.NoError(t, err) - tm = newTestTM(t, ts, 4, "ks3", "0") + tm = newTestTM(t, ts, 4, "ks3", "0", nil) defer tm.Stop() _, err = ts.GetShard(ctx, "ks3", "0") require.NoError(t, err) @@ -235,7 +235,7 @@ func TestStartCreateKeyspaceShard(t *testing.T) { assert.Equal(t, wantVSchema, srvVSchema.Keyspaces["ks3"]) // Multi-shard - tm1 := newTestTM(t, ts, 5, "ks4", "-80") + tm1 := newTestTM(t, ts, 5, "ks4", "-80", nil) defer tm1.Stop() // Wait a bit and make sure that srvKeyspace is still not created. @@ -243,7 +243,7 @@ func TestStartCreateKeyspaceShard(t *testing.T) { _, err = ts.GetSrvKeyspace(context.Background(), cell, "ks4") require.True(t, topo.IsErrType(err, topo.NoNode), err) - tm2 := newTestTM(t, ts, 6, "ks4", "80-") + tm2 := newTestTM(t, ts, 6, "ks4", "80-", nil) defer tm2.Stop() // Now that we've started the tablet for the other shard, srvKeyspace will succeed. ensureSrvKeyspace(t, ctx, ts, cell, "ks4") @@ -264,7 +264,7 @@ func TestCheckPrimaryShip(t *testing.T) { // 1. Initialize the tablet as REPLICA. // This will create the respective topology records. - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) tablet := tm.Tablet() ensureSrvKeyspace(t, ctx, ts, cell, "ks") ti, err := ts.GetTablet(ctx, alias) @@ -398,7 +398,7 @@ func TestStartCheckMysql(t *testing.T) { defer cancel() cell := "cell1" ts := memorytopo.NewServer(ctx, cell) - tablet := newTestTablet(t, 1, "ks", "0") + tablet := newTestTablet(t, 1, "ks", "0", nil) cp := mysql.ConnParams{ Host: "foo", Port: 1, @@ -429,7 +429,7 @@ func TestStartFindMysqlPort(t *testing.T) { defer cancel() cell := "cell1" ts := memorytopo.NewServer(ctx, cell) - tablet := newTestTablet(t, 1, "ks", "0") + tablet := newTestTablet(t, 1, "ks", "0", nil) fmd := newTestMysqlDaemon(t, -1) tm := &TabletManager{ BatchCtx: context.Background(), @@ -472,7 +472,7 @@ func TestStartFixesReplicationData(t *testing.T) { defer cancel() cell := "cell1" ts := memorytopo.NewServer(ctx, cell, "cell2") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) defer tm.Stop() tabletAlias := tm.tabletAlias @@ -505,14 +505,14 @@ func TestStartDoesNotUpdateReplicationDataForTabletInWrongShard(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1", "cell2") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) tm.Stop() tabletAliases, err := ts.FindAllTabletAliasesInShard(ctx, "ks", "0") require.NoError(t, err) assert.Equal(t, uint32(1), tabletAliases[0].Uid) - tablet := newTestTablet(t, 1, "ks", "-d0") + tablet := newTestTablet(t, 1, "ks", "-d0", nil) require.NoError(t, err) err = tm.Start(tablet, nil) assert.Contains(t, err.Error(), "existing tablet keyspace and shard ks/0 differ") @@ -537,7 +537,7 @@ func TestCheckTabletTypeResets(t *testing.T) { // 1. Initialize the tablet as REPLICA. // This will create the respective topology records. - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) tablet := tm.Tablet() ensureSrvKeyspace(t, ctx, ts, cell, "ks") ti, err := ts.GetTablet(ctx, alias) @@ -648,6 +648,27 @@ func TestGetBuildTags(t *testing.T) { } } +func TestStartExportStats(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ts := memorytopo.NewServer(ctx, "cell1") + _ = newTestTM(t, ts, 1, "ks", "0", map[string]string{ + "test": t.Name(), + }) + + assert.Equal(t, "ks", statsKeyspace.Get()) + assert.Equal(t, "0", statsShard.Get()) + assert.Equal(t, "replica", statsTabletType.Get()) + assert.Equal(t, map[string]int64{ + "replica": 1, + }, statsTabletTypeCount.Counts()) + assert.Equal(t, "cell1-0000000001", statsAlias.Get()) + assert.Equal(t, map[string]int64{ + "test." + t.Name(): 1, + }, statsTabletTags.Counts()) +} + func newTestMysqlDaemon(t *testing.T, port int32) *mysqlctl.FakeMysqlDaemon { t.Helper() @@ -662,10 +683,14 @@ func newTestMysqlDaemon(t *testing.T, port int32) *mysqlctl.FakeMysqlDaemon { return mysqld } -func newTestTM(t *testing.T, ts *topo.Server, uid int, keyspace, shard string) *TabletManager { +func newTestTM(t *testing.T, ts *topo.Server, uid int, keyspace, shard string, tags map[string]string) *TabletManager { + // reset stats + statsTabletTags.ResetAll() + statsTabletTypeCount.ResetAll() + t.Helper() ctx := context.Background() - tablet := newTestTablet(t, uid, keyspace, shard) + tablet := newTestTablet(t, uid, keyspace, shard, tags) tm := &TabletManager{ BatchCtx: ctx, TopoServer: ts, @@ -701,7 +726,7 @@ func newTestTM(t *testing.T, ts *topo.Server, uid int, keyspace, shard string) * } } -func newTestTablet(t *testing.T, uid int, keyspace, shard string) *topodatapb.Tablet { +func newTestTablet(t *testing.T, uid int, keyspace, shard string, tags map[string]string) *topodatapb.Tablet { shard, keyRange, err := topo.ValidateShardName(shard) require.NoError(t, err) return &topodatapb.Tablet{ @@ -718,6 +743,7 @@ func newTestTablet(t *testing.T, uid int, keyspace, shard string) *topodatapb.Ta Shard: shard, KeyRange: keyRange, Type: topodatapb.TabletType_REPLICA, + Tags: tags, } } diff --git a/go/vt/vttablet/tabletmanager/tm_state_test.go b/go/vt/vttablet/tabletmanager/tm_state_test.go index 8bd98edefff..7a507248e18 100644 --- a/go/vt/vttablet/tabletmanager/tm_state_test.go +++ b/go/vt/vttablet/tabletmanager/tm_state_test.go @@ -46,7 +46,7 @@ func TestStateOpenClose(t *testing.T) { defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) // Re-Open should be a no-op tm.tmState.mu.Lock() @@ -69,7 +69,7 @@ func TestStateRefreshFromTopo(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) defer tm.Stop() err := tm.RefreshState(ctx) @@ -80,7 +80,7 @@ func TestStateResharding(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) defer tm.Stop() tm.tmState.mu.Lock() @@ -108,7 +108,7 @@ func TestStateDenyList(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) defer tm.Stop() fmd := tm.MysqlDaemon.(*mysqlctl.FakeMysqlDaemon) @@ -140,7 +140,7 @@ func TestStateTabletControls(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) defer tm.Stop() ks := &topodatapb.SrvKeyspace{ @@ -169,7 +169,7 @@ func TestStateIsShardServingisInSrvKeyspace(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) defer tm.Stop() tm.tmState.mu.Lock() @@ -341,7 +341,7 @@ func TestStateNonServing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 1, "ks", "0") + tm := newTestTM(t, ts, 1, "ks", "0", nil) defer tm.Stop() tm.tmState.mu.Lock() @@ -359,7 +359,7 @@ func TestStateChangeTabletType(t *testing.T) { defer cancel() ts := memorytopo.NewServer(ctx, "cell1") statsTabletTypeCount.ResetAll() - tm := newTestTM(t, ts, 2, "ks", "0") + tm := newTestTM(t, ts, 2, "ks", "0", nil) defer tm.Stop() assert.Equal(t, 1, len(statsTabletTypeCount.Counts())) @@ -402,7 +402,7 @@ func TestStateChangeTabletTypeWithFailure(t *testing.T) { ts := memorytopo.NewServer(ctx, "cell1") statsTabletTypeCount.ResetAll() // create TM with replica and put a hook to return error during SetServingType - tm := newTestTM(t, ts, 2, "ks", "0") + tm := newTestTM(t, ts, 2, "ks", "0", nil) qsc := tm.QueryServiceControl.(*tabletservermock.Controller) qsc.SetServingTypeError = vterrors.Errorf(vtrpcpb.Code_RESOURCE_EXHAUSTED, "mocking resource exhaustion error ") defer tm.Stop() @@ -485,7 +485,7 @@ func TestChangeTypeErrorWhileWritingToTopo(t *testing.T) { fakeConn := factory.AddCell("cell1") ts := faketopo.NewFakeTopoServer(context.TODO(), factory) statsTabletTypeCount.ResetAll() - tm := newTestTM(t, ts, 2, "ks", "0") + tm := newTestTM(t, ts, 2, "ks", "0", nil) defer tm.Stop() // ChangeTabletType calls topotools.ChangeType which in-turn issues @@ -533,7 +533,7 @@ func TestPublishStateNew(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 42, "ks", "0") + tm := newTestTM(t, ts, 42, "ks", "0", nil) ttablet, err := tm.TopoServer.GetTablet(ctx, tm.tabletAlias) require.NoError(t, err) utils.MustMatch(t, tm.Tablet(), ttablet.Tablet) @@ -580,7 +580,7 @@ func TestPublishDeleted(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ts := memorytopo.NewServer(ctx, "cell1") - tm := newTestTM(t, ts, 2, "ks", "0") + tm := newTestTM(t, ts, 2, "ks", "0", nil) defer tm.Stop() alias := &topodatapb.TabletAlias{