Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
74377: server: hot ranges api r=koorosh a=koorosh

This change implements second version of hot ranges api that's required
for UI to represent enhanced Hot Ranges view.

It reuses former implementation but doesn't expose sensitive internal data.
Instead, it provides flat structure of fields required for ui.

New `HotRangeV2` endpoint is established to:
- maintain backward compatibility
- do not expose internal data as it's done in `HotRange` endpoint

Release note: None

Release justification: bug fixes and low-risk updates to new functionality

76837: ttljob: add row statistics r=rafiss a=otan

This commit adds the ability for the TTL job to generate statistics on
number of rows and number of expired rows on the table. This is off by
default, controllable by the `ttl_automatic_stats_poll_interval` storage
parameter syntax.


Release justification: low risk high benefit changes to new
functionality


76986: kvserver: disable assertion in SetPriorityID r=erikgrinaker a=tbg

Merge-to-master is currently pretty red, and this has popped up once or
twice. Disable the assertion (which is fine for tests, for now) while
we investigate.

Touches #75939

Release justification: temporarily de-flakes tests.
Release note: None


Co-authored-by: Andrii Vorobiov <[email protected]>
Co-authored-by: Oliver Tan <[email protected]>
Co-authored-by: Tobias Grieger <[email protected]>
  • Loading branch information
4 people committed Mar 2, 2022
4 parents bd5def5 + af62e80 + 6cf5b12 + 86f51ef commit bb54797
Show file tree
Hide file tree
Showing 27 changed files with 796 additions and 62 deletions.
87 changes: 87 additions & 0 deletions docs/generated/http/full.md
Original file line number Diff line number Diff line change
Expand Up @@ -3192,6 +3192,8 @@ of ranges currently considered “hot” by the node(s).
| Field | Type | Label | Description | Support status |
| ----- | ---- | ----- | ----------- | -------------- |
| node_id | [string](#cockroach.server.serverpb.HotRangesRequest-string) | | NodeID indicates which node to query for a hot range report. It is possible to populate any node ID; if the node receiving the request is not the target node, it will forward the request to the target node.<br><br>If left empty, the request is forwarded to every node in the cluster. | [alpha](#support-status) |
| page_size | [int32](#cockroach.server.serverpb.HotRangesRequest-int32) | | | [reserved](#support-status) |
| page_token | [string](#cockroach.server.serverpb.HotRangesRequest-string) | | | [reserved](#support-status) |



Expand Down Expand Up @@ -3271,6 +3273,91 @@ target node(s) selected in a HotRangesRequest.
| ----- | ---- | ----- | ----------- | -------------- |
| desc | [cockroach.roachpb.RangeDescriptor](#cockroach.server.serverpb.HotRangesResponse-cockroach.roachpb.RangeDescriptor) | | Desc is the descriptor of the range for which the report was produced.<br><br>TODO(knz): This field should be removed. See: https://github.com/cockroachdb/cockroach/issues/53212 | [reserved](#support-status) |
| queries_per_second | [double](#cockroach.server.serverpb.HotRangesResponse-double) | | QueriesPerSecond is the recent number of queries per second on this range. | [alpha](#support-status) |
| leaseholder_node_id | [int32](#cockroach.server.serverpb.HotRangesResponse-int32) | | LeaseholderNodeID indicates the Node ID that is the current leaseholder for the given range. | [reserved](#support-status) |






## HotRangesV2

`POST /_status/v2/hotranges`



Support status: [reserved](#support-status)

#### Request Parameters




HotRangesRequest queries one or more cluster nodes for a list
of ranges currently considered “hot” by the node(s).


| Field | Type | Label | Description | Support status |
| ----- | ---- | ----- | ----------- | -------------- |
| node_id | [string](#cockroach.server.serverpb.HotRangesRequest-string) | | NodeID indicates which node to query for a hot range report. It is possible to populate any node ID; if the node receiving the request is not the target node, it will forward the request to the target node.<br><br>If left empty, the request is forwarded to every node in the cluster. | [alpha](#support-status) |
| page_size | [int32](#cockroach.server.serverpb.HotRangesRequest-int32) | | | [reserved](#support-status) |
| page_token | [string](#cockroach.server.serverpb.HotRangesRequest-string) | | | [reserved](#support-status) |







#### Response Parameters




HotRangesResponseV2 is a response payload returned by `HotRangesV2` service.


| Field | Type | Label | Description | Support status |
| ----- | ---- | ----- | ----------- | -------------- |
| ranges | [HotRangesResponseV2.HotRange](#cockroach.server.serverpb.HotRangesResponseV2-cockroach.server.serverpb.HotRangesResponseV2.HotRange) | repeated | Ranges contain list of hot ranges info that has highest number of QPS. | [reserved](#support-status) |
| errors_by_node_id | [HotRangesResponseV2.ErrorsByNodeIdEntry](#cockroach.server.serverpb.HotRangesResponseV2-cockroach.server.serverpb.HotRangesResponseV2.ErrorsByNodeIdEntry) | repeated | errors contains any errors that occurred during fan-out calls to other nodes. | [reserved](#support-status) |
| next_page_token | [string](#cockroach.server.serverpb.HotRangesResponseV2-string) | | NextPageToken represents next pagination token to request next slice of data. | [reserved](#support-status) |






<a name="cockroach.server.serverpb.HotRangesResponseV2-cockroach.server.serverpb.HotRangesResponseV2.HotRange"></a>
#### HotRangesResponseV2.HotRange

HotRange message describes a single hot range, ie its QPS, node ID it belongs to, etc.

| Field | Type | Label | Description | Support status |
| ----- | ---- | ----- | ----------- | -------------- |
| range_id | [int32](#cockroach.server.serverpb.HotRangesResponseV2-int32) | | range_id indicates Range ID that's identified as hot range. | [reserved](#support-status) |
| node_id | [int32](#cockroach.server.serverpb.HotRangesResponseV2-int32) | | node_id indicates the node that contains the current hot range. | [reserved](#support-status) |
| qps | [double](#cockroach.server.serverpb.HotRangesResponseV2-double) | | qps (queries per second) shows the amount of queries that interact with current range. | [reserved](#support-status) |
| table_name | [string](#cockroach.server.serverpb.HotRangesResponseV2-string) | | table_name indicates the SQL table that the range belongs to. | [reserved](#support-status) |
| database_name | [string](#cockroach.server.serverpb.HotRangesResponseV2-string) | | database_name indicates on database that has current hot range. | [reserved](#support-status) |
| index_name | [string](#cockroach.server.serverpb.HotRangesResponseV2-string) | | index_name indicates the index name for current range. | [reserved](#support-status) |
| replica_node_ids | [int32](#cockroach.server.serverpb.HotRangesResponseV2-int32) | repeated | replica_node_ids specifies the list of node ids that contain replicas with current hot range. | [reserved](#support-status) |
| 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) |





<a name="cockroach.server.serverpb.HotRangesResponseV2-cockroach.server.serverpb.HotRangesResponseV2.ErrorsByNodeIdEntry"></a>
#### HotRangesResponseV2.ErrorsByNodeIdEntry



| Field | Type | Label | Description | Support status |
| ----- | ---- | ----- | ----------- | -------------- |
| key | [int32](#cockroach.server.serverpb.HotRangesResponseV2-int32) | | | |
| value | [string](#cockroach.server.serverpb.HotRangesResponseV2-string) | | | |



Expand Down
1 change: 1 addition & 0 deletions docs/generated/http/hotranges-other.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,6 @@ Support status: [alpha](#support-status)
| ----- | ---- | ----- | ----------- | -------------- |
| desc | [cockroach.roachpb.RangeDescriptor](#cockroach.roachpb.RangeDescriptor) | | Desc is the descriptor of the range for which the report was produced.<br><br>TODO(knz): This field should be removed. See: https://github.com/cockroachdb/cockroach/issues/53212 | [reserved](#support-status) |
| queries_per_second | [double](#double) | | QueriesPerSecond is the recent number of queries per second on this range. | [alpha](#support-status) |
| leaseholder_node_id | [int32](#int32) | | LeaseholderNodeID indicates the Node ID that is the current leaseholder for the given range. | [reserved](#support-status) |


2 changes: 2 additions & 0 deletions docs/generated/http/hotranges-request.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ Support status: [alpha](#support-status)
| Field | Type | Label | Description | Support status |
| ----- | ---- | ----- | ----------- | -------------- |
| node_id | [string](#string) | | NodeID indicates which node to query for a hot range report. It is possible to populate any node ID; if the node receiving the request is not the target node, it will forward the request to the target node.<br><br>If left empty, the request is forwarded to every node in the cluster. | [alpha](#support-status) |
| page_size | [int32](#int32) | | | [reserved](#support-status) |
| page_token | [string](#string) | | | [reserved](#support-status) |


64 changes: 56 additions & 8 deletions docs/generated/swagger/spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,12 @@
},
"x-go-package": "github.com/cockroachdb/cockroach/pkg/util/metric"
},
"RangeID": {
"type": "integer",
"format": "int64",
"title": "A RangeID is a unique ID associated to a Raft consensus group.",
"x-go-package": "github.com/cockroachdb/cockroach/pkg/roachpb"
},
"RangeProblems": {
"type": "object",
"title": "RangeProblems describes issues reported by a range. For internal use only.",
Expand Down Expand Up @@ -1788,6 +1794,51 @@
},
"x-go-package": "github.com/cockroachdb/cockroach/pkg/server"
},
"hotRangeInfo": {
"description": "(ie its range ID, QPS, table name, etc.).",
"type": "object",
"title": "Hot range details struct describes common information about hot range,",
"properties": {
"database_name": {
"type": "string",
"x-go-name": "DatabaseName"
},
"index_name": {
"type": "string",
"x-go-name": "IndexName"
},
"leaseholder_node_id": {
"$ref": "#/definitions/NodeID"
},
"node_id": {
"$ref": "#/definitions/NodeID"
},
"qps": {
"type": "number",
"format": "double",
"x-go-name": "QPS"
},
"range_id": {
"$ref": "#/definitions/RangeID"
},
"replica_node_ids": {
"type": "array",
"items": {
"$ref": "#/definitions/NodeID"
},
"x-go-name": "ReplicaNodeIDs"
},
"schema_name": {
"type": "string",
"x-go-name": "SchemaName"
},
"table_name": {
"type": "string",
"x-go-name": "TableName"
}
},
"x-go-package": "github.com/cockroachdb/cockroach/pkg/server"
},
"hotRangesResponse": {
"type": "object",
"title": "Response struct for listHotRanges.",
Expand All @@ -1797,15 +1848,12 @@
"type": "string",
"x-go-name": "Next"
},
"ranges_by_node_id": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "#/definitions/rangeDescriptorInfo"
}
"ranges": {
"type": "array",
"items": {
"$ref": "#/definitions/hotRangeInfo"
},
"x-go-name": "RangesByNodeID"
"x-go-name": "Ranges"
},
"response_error": {
"type": "array",
Expand Down
5 changes: 4 additions & 1 deletion pkg/kv/kvserver/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@ func (q *rangeIDQueue) Len() int {
}

func (q *rangeIDQueue) SetPriorityID(id roachpb.RangeID) {
if q.priorityID != 0 && q.priorityID != id {
if q.priorityID != 0 && q.priorityID != id &&
// This assertion is temporarily disabled, see:
// https://github.com/cockroachdb/cockroach/issues/75939
false {
panic(fmt.Sprintf(
"priority range ID already set: old=%d, new=%d",
q.priorityID, id))
Expand Down
1 change: 1 addition & 0 deletions pkg/server/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ go_library(
"//pkg/spanconfig/spanconfigsqltranslator",
"//pkg/spanconfig/spanconfigsqlwatcher",
"//pkg/sql",
"//pkg/sql/catalog",
"//pkg/sql/catalog/bootstrap",
"//pkg/sql/catalog/catalogkeys",
"//pkg/sql/catalog/catconstants",
Expand Down
60 changes: 35 additions & 25 deletions pkg/server/api_v2_ranges.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"context"
"fmt"
"net/http"
"sort"
"strconv"
"strings"

Expand Down Expand Up @@ -415,13 +414,29 @@ type responseError struct {
//
// swagger:model hotRangesResponse
type hotRangesResponse struct {
RangesByNodeID map[string][]rangeDescriptorInfo `json:"ranges_by_node_id"`
Errors []responseError `json:"response_error,omitempty"`
Ranges []hotRangeInfo `json:"ranges"`
Errors []responseError `json:"response_error,omitempty"`
// Continuation token for the next paginated call. Use as the `start`
// parameter.
Next string `json:"next,omitempty"`
}

// Hot range details struct describes common information about hot range,
// (ie its range ID, QPS, table name, etc.).
//
// 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"`
}

// swagger:operation GET /ranges/hot/ listHotRanges
//
// List hot ranges
Expand Down Expand Up @@ -464,9 +479,7 @@ func (a *apiV2Server) listHotRanges(w http.ResponseWriter, r *http.Request) {
nodeIDStr := r.URL.Query().Get("node_id")
limit, start := getRPCPaginationValues(r)

response := &hotRangesResponse{
RangesByNodeID: make(map[string][]rangeDescriptorInfo),
}
response := &hotRangesResponse{}
var requestedNodes []roachpb.NodeID
if len(nodeIDStr) > 0 {
requestedNodeID, _, err := a.status.parseNodeID(nodeIDStr)
Expand All @@ -484,32 +497,29 @@ func (a *apiV2Server) listHotRanges(w http.ResponseWriter, r *http.Request) {
remoteRequest := serverpb.HotRangesRequest{NodeID: "local"}
nodeFn := func(ctx context.Context, client interface{}, nodeID roachpb.NodeID) (interface{}, error) {
status := client.(serverpb.StatusClient)
resp, err := status.HotRanges(ctx, &remoteRequest)
resp, err := status.HotRangesV2(ctx, &remoteRequest)
if err != nil || resp == nil {
return nil, err
}
rangeDescriptorInfos := make([]rangeDescriptorInfo, 0)
for _, store := range resp.HotRangesByNodeID[nodeID].Stores {
for _, hotRange := range store.HotRanges {
var r rangeDescriptorInfo
r.init(&hotRange.Desc)
r.StoreID = int32(store.StoreID)
r.QueriesPerSecond = hotRange.QueriesPerSecond
rangeDescriptorInfos = append(rangeDescriptorInfos, r)

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,
}
}
sort.Slice(rangeDescriptorInfos, func(i, j int) bool {
if rangeDescriptorInfos[i].StoreID == rangeDescriptorInfos[j].StoreID {
return rangeDescriptorInfos[i].RangeID < rangeDescriptorInfos[j].RangeID
}
return rangeDescriptorInfos[i].StoreID < rangeDescriptorInfos[j].StoreID
})
return rangeDescriptorInfos, nil
return hotRangeInfos, nil
}
responseFn := func(nodeID roachpb.NodeID, resp interface{}) {
if hotRangesResp, ok := resp.([]rangeDescriptorInfo); ok {
response.RangesByNodeID[nodeID.String()] = hotRangesResp
}
response.Ranges = append(response.Ranges, resp.([]hotRangeInfo)...)
}
errorFn := func(nodeID roachpb.NodeID, err error) {
response.Errors = append(response.Errors, responseError{
Expand Down
17 changes: 4 additions & 13 deletions pkg/server/api_v2_ranges_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,16 @@ func TestHotRangesV2(t *testing.T) {
require.NoError(t, json.NewDecoder(resp.Body).Decode(&hotRangesResp))
require.NoError(t, resp.Body.Close())

if len(hotRangesResp.RangesByNodeID) == 0 {
if len(hotRangesResp.Ranges) == 0 {
t.Fatalf("didn't get hot range responses from any nodes")
}
if len(hotRangesResp.Errors) > 0 {
t.Errorf("got an error in hot range response from n%d: %v",
hotRangesResp.Errors[0].NodeID, hotRangesResp.Errors[0].ErrorMessage)
}

for nodeID, nodeResp := range hotRangesResp.RangesByNodeID {
if len(nodeResp) == 0 {
t.Fatalf("didn't get hot range response from node n%s", nodeID)
}
// We don't check for ranges being sorted by QPS, as this hot ranges
// report does not use that as its sort key (for stability across multiple
// pagination calls).
for _, r := range nodeResp {
if r.RangeID == 0 || (len(r.StartKey) == 0 && len(r.EndKey) == 0) {
t.Errorf("unexpected empty/unpopulated range descriptor: %+v", r)
}
for _, r := range hotRangesResp.Ranges {
if r.RangeID == 0 || r.NodeID == 0 {
t.Errorf("unexpected empty/unpopulated range descriptor: %+v", r)
}
}
}
Expand Down
Loading

0 comments on commit bb54797

Please sign in to comment.