Skip to content

Commit

Permalink
server: add more load stats to hot ranges v2 api
Browse files Browse the repository at this point in the history
Previously, only QPS was included in the hot ranges v2 api. This commit
adds the following range statistics to the API:

```
WritesPerSecond
ReadsPerSecond
WriteBytesPerSecond
ReadBytesPerSecond
CPUTimePerSecond
```

See the associated comments in `status.proto` for a description of each
load statistic.

These may be used to determine the hottest ranges. Note however that
these are sorted by default by QPS. The ordering of ranges w.r.t the new
load statistics has no guarantees. Likewise, ranges may be omitted which
have high relative values for the new load statistics but relatively low
QPS. In practice however, there usually exists a strong correlation that
ensures that such ranges would not be omitted entirely.

resolves: #95383

Release note: None
  • Loading branch information
kvoli committed Jan 24, 2023
1 parent 1e2c06b commit 134463b
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 31 deletions.
5 changes: 5 additions & 0 deletions docs/generated/http/full.md
Expand Up @@ -3571,6 +3571,11 @@ HotRange message describes a single hot range, ie its QPS, node ID it belongs to
| leaseholder_node_id | [int32](#cockroach.server.serverpb.HotRangesResponseV2-int32) | | leaseholder_node_id indicates the Node ID that is the current leaseholder for the given range. | [reserved](#support-status) |
| schema_name | [string](#cockroach.server.serverpb.HotRangesResponseV2-string) | | schema_name provides the name of schema (if exists) for table in current range. | [reserved](#support-status) |
| store_id | [int32](#cockroach.server.serverpb.HotRangesResponseV2-int32) | | store_id indicates the Store ID where range is stored. | [reserved](#support-status) |
| writes_per_second | [double](#cockroach.server.serverpb.HotRangesResponseV2-double) | | writes_per_second is the recent number of keys written per second on this range. | [reserved](#support-status) |
| reads_per_second | [double](#cockroach.server.serverpb.HotRangesResponseV2-double) | | reads_per_second is the recent number of keys read per second on this range. | [reserved](#support-status) |
| write_bytes_per_second | [double](#cockroach.server.serverpb.HotRangesResponseV2-double) | | write_bytes_per_second is the recent number of bytes written per second on this range. | [reserved](#support-status) |
| read_bytes_per_second | [double](#cockroach.server.serverpb.HotRangesResponseV2-double) | | read_bytes_per_second is the recent number of bytes read per second on this range. | [reserved](#support-status) |
| cpu_time_per_second | [double](#cockroach.server.serverpb.HotRangesResponseV2-double) | | CPU time (ns) per second is the recent cpu usage per second on this range. | [reserved](#support-status) |



Expand Down
27 changes: 26 additions & 1 deletion docs/generated/swagger/spec.json
Expand Up @@ -2104,6 +2104,31 @@
"format": "double",
"x-go-name": "QPS"
},
"writes_per_second": {
"type": "number",
"format": "double",
"x-go-name": "WritesPerSecond"
},
"reads_per_second": {
"type": "number",
"format": "double",
"x-go-name": "ReadsPerSecond"
},
"write_bytes_per_second": {
"type": "number",
"format": "double",
"x-go-name": "WriteBytesPerSecond"
},
"read_bytes_per_second": {
"type": "number",
"format": "double",
"x-go-name": "ReadBytesPerSecond"
},
"cpu_time_per_second": {
"type": "number",
"format": "double",
"x-go-name": "CPUTimePerSecond"
},
"range_id": {
"$ref": "#/definitions/RangeID"
},
Expand Down Expand Up @@ -2499,4 +2524,4 @@
"in": "header"
}
}
}
}
50 changes: 30 additions & 20 deletions pkg/server/api_v2_ranges.go
Expand Up @@ -440,16 +440,21 @@ type hotRangesResponse struct {
//
// swagger:model hotRangeInfo
type hotRangeInfo struct {
RangeID roachpb.RangeID `json:"range_id"`
NodeID roachpb.NodeID `json:"node_id"`
QPS float64 `json:"qps"`
LeaseholderNodeID roachpb.NodeID `json:"leaseholder_node_id"`
TableName string `json:"table_name"`
DatabaseName string `json:"database_name"`
IndexName string `json:"index_name"`
SchemaName string `json:"schema_name"`
ReplicaNodeIDs []roachpb.NodeID `json:"replica_node_ids"`
StoreID roachpb.StoreID `json:"store_id"`
RangeID roachpb.RangeID `json:"range_id"`
NodeID roachpb.NodeID `json:"node_id"`
QPS float64 `json:"qps"`
WritesPerSecond float64 `json:"writes_per_second"`
ReadsPerSecond float64 `json:"reads_per_second"`
WriteBytesPerSecond float64 `json:"write_bytes_per_second"`
ReadBytesPerSecond float64 `json:"read_bytes_per_second"`
CPUTimePerSecond float64 `json:"cpu_time_per_second"`
LeaseholderNodeID roachpb.NodeID `json:"leaseholder_node_id"`
TableName string `json:"table_name"`
DatabaseName string `json:"database_name"`
IndexName string `json:"index_name"`
SchemaName string `json:"schema_name"`
ReplicaNodeIDs []roachpb.NodeID `json:"replica_node_ids"`
StoreID roachpb.StoreID `json:"store_id"`
}

// swagger:operation GET /ranges/hot/ listHotRanges
Expand Down Expand Up @@ -522,16 +527,21 @@ func (a *apiV2Server) listHotRanges(w http.ResponseWriter, r *http.Request) {
var hotRangeInfos = make([]hotRangeInfo, len(resp.Ranges))
for i, r := range resp.Ranges {
hotRangeInfos[i] = hotRangeInfo{
RangeID: r.RangeID,
NodeID: r.NodeID,
QPS: r.QPS,
LeaseholderNodeID: r.LeaseholderNodeID,
TableName: r.TableName,
DatabaseName: r.DatabaseName,
IndexName: r.IndexName,
ReplicaNodeIDs: r.ReplicaNodeIds,
SchemaName: r.SchemaName,
StoreID: r.StoreID,
RangeID: r.RangeID,
NodeID: r.NodeID,
QPS: r.QPS,
WritesPerSecond: r.WritesPerSecond,
ReadsPerSecond: r.ReadsPerSecond,
WriteBytesPerSecond: r.WriteBytesPerSecond,
ReadBytesPerSecond: r.ReadBytesPerSecond,
CPUTimePerSecond: r.CPUTimePerSecond,
LeaseholderNodeID: r.LeaseholderNodeID,
TableName: r.TableName,
DatabaseName: r.DatabaseName,
IndexName: r.IndexName,
ReplicaNodeIDs: r.ReplicaNodeIds,
SchemaName: r.SchemaName,
StoreID: r.StoreID,
}
}
return hotRangeInfos, nil
Expand Down
15 changes: 15 additions & 0 deletions pkg/server/serverpb/status.proto
Expand Up @@ -1437,6 +1437,21 @@ message HotRangesResponseV2 {
(gogoproto.casttype) =
"github.com/cockroachdb/cockroach/pkg/roachpb.StoreID"
];
// writes_per_second is the recent number of keys written per second on
// this range.
double writes_per_second = 11;
// reads_per_second is the recent number of keys read per second on
// this range.
double reads_per_second = 12;
// write_bytes_per_second is the recent number of bytes written per second
// on this range.
double write_bytes_per_second = 13;
// read_bytes_per_second is the recent number of bytes read per second on
// this range.
double read_bytes_per_second = 14;
// CPU time (ns) per second is the recent cpu usage per second on this
// range.
double cpu_time_per_second = 15 [(gogoproto.customname) = "CPUTimePerSecond"];
}
// Ranges contain list of hot ranges info that has highest number of QPS.
repeated HotRange ranges = 1;
Expand Down
25 changes: 15 additions & 10 deletions pkg/server/status.go
Expand Up @@ -2585,16 +2585,21 @@ func (s *systemStatusServer) HotRangesV2(
}

ranges = append(ranges, &serverpb.HotRangesResponseV2_HotRange{
RangeID: r.Desc.RangeID,
NodeID: requestedNodeID,
QPS: r.QueriesPerSecond,
TableName: tableName,
SchemaName: schemaName,
DatabaseName: dbName,
IndexName: indexName,
ReplicaNodeIds: replicaNodeIDs,
LeaseholderNodeID: r.LeaseholderNodeID,
StoreID: store.StoreID,
RangeID: r.Desc.RangeID,
NodeID: requestedNodeID,
QPS: r.QueriesPerSecond,
WritesPerSecond: r.WritesPerSecond,
ReadsPerSecond: r.ReadsPerSecond,
WriteBytesPerSecond: r.WriteBytesPerSecond,
ReadBytesPerSecond: r.ReadBytesPerSecond,
CPUTimePerSecond: r.CPUTimePerSecond,
TableName: tableName,
SchemaName: schemaName,
DatabaseName: dbName,
IndexName: indexName,
ReplicaNodeIds: replicaNodeIDs,
LeaseholderNodeID: r.LeaseholderNodeID,
StoreID: store.StoreID,
})
}
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/server/status_test.go
Expand Up @@ -1093,6 +1093,15 @@ func TestHotRanges2Response(t *testing.T) {
if r.RangeID == 0 {
t.Errorf("unexpected empty range id: %d", r.RangeID)
}
if r.QPS > 0 {
if r.ReadsPerSecond == 0 && r.WritesPerSecond == 0 {
t.Errorf("qps %.2f > 0, expected either reads=%.2f or writes=%.2f to be non-zero",
r.QPS, r.ReadsPerSecond, r.WritesPerSecond)
}
if r.CPUTimePerSecond == 0 {
t.Errorf("qps %.2f > 0, expected cpu=%.2f to be non-zero", r.QPS, r.CPUTimePerSecond)
}
}
if r.QPS > lastQPS {
t.Errorf("unexpected increase in qps between ranges; prev=%.2f, current=%.2f", lastQPS, r.QPS)
}
Expand Down

0 comments on commit 134463b

Please sign in to comment.