Skip to content

Commit 5aeb68e

Browse files
vtorc: add tablets watched stats (#17911)
Signed-off-by: Tim Vaillancourt <tim@timvaillancourt.com>
1 parent 987480d commit 5aeb68e

6 files changed

Lines changed: 136 additions & 41 deletions

File tree

go/vt/vtorc/inst/shard_dao.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,6 @@ func ReadShardNames(keyspaceName string) (shardNames []string, err error) {
4141
return shardNames, err
4242
}
4343

44-
// ReadAllShardNames reads the names of all vitess shards by keyspace.
45-
func ReadAllShardNames() (shardNames map[string][]string, err error) {
46-
shardNames = make(map[string][]string)
47-
query := `select keyspace, shard from vitess_shard`
48-
err = db.QueryVTOrc(query, nil, func(row sqlutils.RowMap) error {
49-
ks := row.GetString("keyspace")
50-
shardNames[ks] = append(shardNames[ks], row.GetString("shard"))
51-
return nil
52-
})
53-
return shardNames, err
54-
}
55-
5644
// ReadShardPrimaryInformation reads the vitess shard record and gets the shard primary alias and timestamp.
5745
func ReadShardPrimaryInformation(keyspaceName, shardName string) (primaryAlias string, primaryTimestamp string, err error) {
5846
if err = topo.ValidateKeyspaceName(keyspaceName); err != nil {

go/vt/vtorc/inst/shard_dao_test.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,6 @@ func TestSaveReadAndDeleteShard(t *testing.T) {
108108
require.NoError(t, err)
109109
require.Equal(t, []string{tt.shardName}, shardNames)
110110

111-
// ReadAllShardNames
112-
allShardNames, err := ReadAllShardNames()
113-
require.NoError(t, err)
114-
ksShards, found := allShardNames[tt.keyspaceName]
115-
require.True(t, found)
116-
require.Equal(t, []string{tt.shardName}, ksShards)
117-
118111
// DeleteShard
119112
require.NoError(t, DeleteShard(tt.keyspaceName, tt.shardName))
120113
_, _, err = ReadShardPrimaryInformation(tt.keyspaceName, tt.shardName)

go/vt/vtorc/inst/tablet_dao.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,50 @@ func ReadTablet(tabletAlias string) (*topodatapb.Tablet, error) {
7474
return tablet, nil
7575
}
7676

77+
// ReadTabletCountsByCell returns the count of tablets watched by cell.
78+
// The backend query uses an index by "cell": cell_idx_vitess_tablet.
79+
func ReadTabletCountsByCell() (map[string]int64, error) {
80+
tabletCounts := make(map[string]int64)
81+
query := `SELECT
82+
cell,
83+
COUNT() AS count
84+
FROM
85+
vitess_tablet
86+
GROUP BY
87+
cell`
88+
err := db.QueryVTOrc(query, nil, func(row sqlutils.RowMap) error {
89+
cell := row.GetString("cell")
90+
tabletCounts[cell] = row.GetInt64("count")
91+
return nil
92+
})
93+
return tabletCounts, err
94+
}
95+
96+
// ReadTabletCountsByKeyspaceShard returns the count of tablets watched by keyspace/shard.
97+
// The backend query uses an index by "keyspace, shard": ks_idx_vitess_tablet.
98+
func ReadTabletCountsByKeyspaceShard() (map[string]map[string]int64, error) {
99+
tabletCounts := make(map[string]map[string]int64)
100+
query := `SELECT
101+
keyspace,
102+
shard,
103+
COUNT() AS count
104+
FROM
105+
vitess_tablet
106+
GROUP BY
107+
keyspace,
108+
shard`
109+
err := db.QueryVTOrc(query, nil, func(row sqlutils.RowMap) error {
110+
keyspace := row.GetString("keyspace")
111+
shard := row.GetString("shard")
112+
if _, found := tabletCounts[keyspace]; !found {
113+
tabletCounts[keyspace] = make(map[string]int64)
114+
}
115+
tabletCounts[keyspace][shard] = row.GetInt64("count")
116+
return nil
117+
})
118+
return tabletCounts, err
119+
}
120+
77121
// SaveTablet saves the tablet record against the instanceKey.
78122
func SaveTablet(tablet *topodatapb.Tablet) error {
79123
tabletp, err := prototext.Marshal(tablet)

go/vt/vtorc/inst/tablet_dao_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,56 @@ func TestSaveAndReadTablet(t *testing.T) {
9191
})
9292
}
9393
}
94+
95+
func TestReadTabletCountsByCell(t *testing.T) {
96+
// Clear the database after the test. The easiest way to do that is to run all the initialization commands again.
97+
defer func() {
98+
db.ClearVTOrcDatabase()
99+
}()
100+
101+
for i := 0; i < 100; i++ {
102+
require.NoError(t, SaveTablet(&topodatapb.Tablet{
103+
Alias: &topodatapb.TabletAlias{
104+
Cell: "cell1",
105+
Uid: uint32(i),
106+
},
107+
Keyspace: "test",
108+
Shard: "-",
109+
}))
110+
}
111+
tabletCounts, err := ReadTabletCountsByCell()
112+
require.NoError(t, err)
113+
require.Equal(t, map[string]int64{"cell1": 100}, tabletCounts)
114+
}
115+
116+
func TestReadTabletCountsByKeyspaceShard(t *testing.T) {
117+
// Clear the database after the test. The easiest way to do that is to run all the initialization commands again.
118+
defer func() {
119+
db.ClearVTOrcDatabase()
120+
}()
121+
122+
var uid uint32
123+
for _, shard := range []string{"-40", "40-80", "80-c0", "c0-"} {
124+
for i := 0; i < 100; i++ {
125+
require.NoError(t, SaveTablet(&topodatapb.Tablet{
126+
Alias: &topodatapb.TabletAlias{
127+
Cell: "cell1",
128+
Uid: uid,
129+
},
130+
Keyspace: "test",
131+
Shard: shard,
132+
}))
133+
uid++
134+
}
135+
}
136+
tabletCounts, err := ReadTabletCountsByKeyspaceShard()
137+
require.NoError(t, err)
138+
require.Equal(t, map[string]map[string]int64{
139+
"test": {
140+
"-40": 100,
141+
"40-80": 100,
142+
"80-c0": 100,
143+
"c0-": 100,
144+
},
145+
}, tabletCounts)
146+
}

go/vt/vtorc/logic/keyspace_shard_discovery.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,35 +23,13 @@ import (
2323
"golang.org/x/exp/maps"
2424
"golang.org/x/sync/errgroup"
2525

26-
"vitess.io/vitess/go/stats"
2726
"vitess.io/vitess/go/vt/key"
2827
"vitess.io/vitess/go/vt/log"
2928
"vitess.io/vitess/go/vt/topo"
3029
"vitess.io/vitess/go/vt/topo/topoproto"
3130
"vitess.io/vitess/go/vt/vtorc/inst"
3231
)
3332

34-
var statsShardsWatched = stats.NewGaugesFuncWithMultiLabels("ShardsWatched",
35-
"Keyspace/shards currently watched",
36-
[]string{"Keyspace", "Shard"},
37-
getShardsWatchedStats)
38-
39-
// getShardsWatchedStats returns the keyspace/shards watched in a format for stats.
40-
func getShardsWatchedStats() map[string]int64 {
41-
shardsWatched := make(map[string]int64)
42-
allShardNames, err := inst.ReadAllShardNames()
43-
if err != nil {
44-
log.Errorf("Failed to read all shard names: %+v", err)
45-
return shardsWatched
46-
}
47-
for ks, shards := range allShardNames {
48-
for _, shard := range shards {
49-
shardsWatched[ks+"."+shard] = 1
50-
}
51-
}
52-
return shardsWatched
53-
}
54-
5533
// refreshAllKeyspacesAndShardsMu ensures RefreshAllKeyspacesAndShards
5634
// is not executed concurrently.
5735
var refreshAllKeyspacesAndShardsMu sync.Mutex

go/vt/vtorc/logic/tablet_discovery.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"google.golang.org/protobuf/encoding/prototext"
3232
"google.golang.org/protobuf/proto"
3333

34+
"vitess.io/vitess/go/stats"
3435
"vitess.io/vitess/go/vt/external/golib/sqlutils"
3536
"vitess.io/vitess/go/vt/key"
3637
"vitess.io/vitess/go/vt/log"
@@ -54,10 +55,48 @@ var (
5455
// This is populated by parsing `--clusters_to_watch` flag.
5556
shardsToWatch map[string][]*topodatapb.KeyRange
5657

58+
// tablet stats
59+
statsTabletsWatchedByCell = stats.NewGaugesFuncWithMultiLabels(
60+
"TabletsWatchedByCell",
61+
"Number of tablets watched by cell",
62+
[]string{"Cell"},
63+
getTabletsWatchedByCellStats,
64+
)
65+
statsTabletsWatchedByShard = stats.NewGaugesFuncWithMultiLabels(
66+
"TabletsWatchedByShard",
67+
"Number of tablets watched by keyspace/shard",
68+
[]string{"Keyspace", "Shard"},
69+
getTabletsWatchedByShardStats,
70+
)
71+
5772
// ErrNoPrimaryTablet is a fixed error message.
5873
ErrNoPrimaryTablet = errors.New("no primary tablet found")
5974
)
6075

76+
// getTabletsWatchedByCellStats returns the number of tablets watched by cell in stats format.
77+
func getTabletsWatchedByCellStats() map[string]int64 {
78+
tabletCountsByCell, err := inst.ReadTabletCountsByCell()
79+
if err != nil {
80+
log.Errorf("Failed to read tablet counts by cell: %+v", err)
81+
}
82+
return tabletCountsByCell
83+
}
84+
85+
// getTabletsWatchedByShardStats returns the number of tablets watched by keyspace/shard in stats format.
86+
func getTabletsWatchedByShardStats() map[string]int64 {
87+
tabletsWatchedByShard := make(map[string]int64)
88+
tabletCountsByKS, err := inst.ReadTabletCountsByKeyspaceShard()
89+
if err != nil {
90+
log.Errorf("Failed to read tablet counts by shard: %+v", err)
91+
}
92+
for keyspace, countsByShard := range tabletCountsByKS {
93+
for shard, tabletCount := range countsByShard {
94+
tabletsWatchedByShard[keyspace+"."+shard] = tabletCount
95+
}
96+
}
97+
return tabletsWatchedByShard
98+
}
99+
61100
// RegisterFlags registers the flags required by VTOrc
62101
func RegisterFlags(fs *pflag.FlagSet) {
63102
fs.StringSliceVar(&clustersToWatch, "clusters_to_watch", clustersToWatch, "Comma-separated list of keyspaces or keyspace/keyranges that this instance will monitor and repair. Defaults to all clusters in the topology. Example: \"ks1,ks2/-80\"")

0 commit comments

Comments
 (0)