Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tsdb: add tenant-level store metrics to tsdb #99860

Merged
merged 1 commit into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pkg/kv/kvbase/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "kvbase",
srcs = ["constants.go"],
srcs = [
"constants.go",
"metrics.go",
],
importpath = "github.com/cockroachdb/cockroach/pkg/kv/kvbase",
visibility = ["//visibility:public"],
)
Expand Down
17 changes: 17 additions & 0 deletions pkg/kv/kvbase/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package kvbase

// TenantsStorageMetricsSet is the set of all metric names contained
// within TenantsStorageMetrics, recorded at the individual tenant level.
//
// Made available in kvbase to help avoid import cycles.
var TenantsStorageMetricsSet map[string]struct{}
36 changes: 36 additions & 0 deletions pkg/kv/kvserver/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"time"
"unsafe"

"github.com/cockroachdb/cockroach/pkg/kv/kvbase"
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/allocator/allocatorimpl"
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/batcheval/result"
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverpb"
Expand All @@ -37,6 +38,12 @@ import (
"go.etcd.io/raft/v3/raftpb"
)

func init() {
// Inject the TenantStorageMetricsSet available in the kvbase pkg to
// avoid import cycles.
kvbase.TenantsStorageMetricsSet = tenantsStorageMetricsSet()
}

var (
// Replica metrics.
metaReplicaCount = metric.Metadata{
Expand Down Expand Up @@ -2204,6 +2211,8 @@ func (ref *tenantMetricsRef) assert(ctx context.Context) {
// call acquire and release to properly reference count the metrics for
// individual tenants.
type TenantsStorageMetrics struct {
// NB: If adding more metrics to this struct, be sure to
// also update tenantsStorageMetricsSet().
LiveBytes *aggmetric.AggGauge
KeyBytes *aggmetric.AggGauge
ValBytes *aggmetric.AggGauge
Expand Down Expand Up @@ -2232,6 +2241,33 @@ type TenantsStorageMetrics struct {
tenants syncutil.IntMap // map[int64(roachpb.TenantID)]*tenantStorageMetrics
}

// tenantsStorageMetricsSet returns the set of all metric names contained
// within TenantsStorageMetrics.
//
// see kvbase.TenantsStorageMetricsSet for public access. Assigned in init().
func tenantsStorageMetricsSet() map[string]struct{} {
return map[string]struct{}{
metaLiveBytes.Name: {},
metaKeyBytes.Name: {},
metaValBytes.Name: {},
metaRangeKeyBytes.Name: {},
metaRangeValBytes.Name: {},
metaTotalBytes.Name: {},
metaIntentBytes.Name: {},
metaLiveCount.Name: {},
metaKeyCount.Name: {},
metaValCount.Name: {},
metaRangeKeyCount.Name: {},
metaRangeValCount.Name: {},
metaIntentCount.Name: {},
metaIntentAge.Name: {},
metaGcBytesAge.Name: {},
metaSysBytes.Name: {},
metaSysCount.Name: {},
metaAbortSpanBytes.Name: {},
}
}

var _ metric.Struct = (*TenantsStorageMetrics)(nil)

// MetricStruct makes TenantsStorageMetrics a metric.Struct.
Expand Down
6 changes: 6 additions & 0 deletions pkg/server/status/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ go_library(
"//pkg/build",
"//pkg/keys",
"//pkg/kv",
"//pkg/kv/kvbase",
"//pkg/kv/kvpb",
"//pkg/kv/kvserver/liveness",
"//pkg/multitenant",
"//pkg/roachpb",
"//pkg/rpc",
"//pkg/server/status/statuspb",
Expand All @@ -69,6 +71,7 @@ go_library(
"@com_github_cockroachdb_redact//:redact",
"@com_github_dustin_go_humanize//:go-humanize",
"@com_github_elastic_gosigar//:gosigar",
"@com_github_prometheus_client_model//go",
"@com_github_shirou_gopsutil_v3//cpu",
"@com_github_shirou_gopsutil_v3//net",
] + select({
Expand Down Expand Up @@ -134,6 +137,7 @@ go_test(
deps = [
"//pkg/base",
"//pkg/build",
"//pkg/multitenant",
"//pkg/roachpb",
"//pkg/security/securityassets",
"//pkg/security/securitytest",
Expand All @@ -143,6 +147,7 @@ go_test(
"//pkg/sql/sem/catconstants",
"//pkg/testutils/serverutils",
"//pkg/ts/tspb",
"//pkg/ts/tsutil",
"//pkg/util/leaktest",
"//pkg/util/log",
"//pkg/util/log/eventpb",
Expand All @@ -151,6 +156,7 @@ go_test(
"//pkg/util/system",
"//pkg/util/timeutil",
"@com_github_kr_pretty//:pretty",
"@com_github_prometheus_client_model//go",
"@com_github_shirou_gopsutil_v3//net",
"@com_github_stretchr_testify//require",
],
Expand Down
79 changes: 79 additions & 0 deletions pkg/server/status/recorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import (
"github.com/cockroachdb/cockroach/pkg/build"
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/kv"
"github.com/cockroachdb/cockroach/pkg/kv/kvbase"
"github.com/cockroachdb/cockroach/pkg/kv/kvpb"
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/liveness"
"github.com/cockroachdb/cockroach/pkg/multitenant"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/cockroach/pkg/rpc"
"github.com/cockroachdb/cockroach/pkg/server/status/statuspb"
Expand All @@ -49,6 +51,7 @@ import (
"github.com/cockroachdb/redact"
"github.com/dustin/go-humanize"
"github.com/elastic/gosigar"
prometheusgo "github.com/prometheus/client_model/go"
)

const (
Expand Down Expand Up @@ -385,6 +388,7 @@ func (mr *MetricsRecorder) GetTimeSeriesData() []tspb.TimeSeriesData {
}

// Record time series from store-level registries.
tIDLabel := multitenant.TenantIDLabel
for storeID, r := range mr.mu.storeRegistries {
storeRecorder := registryRecorder{
registry: r,
Expand All @@ -393,6 +397,21 @@ func (mr *MetricsRecorder) GetTimeSeriesData() []tspb.TimeSeriesData {
timestampNanos: now.UnixNano(),
}
storeRecorder.record(&data)

// Now record secondary tenant store metrics, if any exist in the process.
for tenantID := range mr.mu.tenantRegistries {
tenantStoreRecorder := registryRecorder{
registry: r,
format: storeTimeSeriesPrefix,
source: tsutil.MakeTenantSource(storeID.String(), tenantID.String()),
timestampNanos: now.UnixNano(),
}
tenantID := tenantID.String()
tenantStoreRecorder.recordChild(&data, kvbase.TenantsStorageMetricsSet, &prometheusgo.LabelPair{
Name: &tIDLabel,
Value: &tenantID,
})
}
}
atomic.CompareAndSwapInt64(&mr.lastDataCount, lastDataCount, int64(len(data)))
return data
Expand Down Expand Up @@ -659,6 +678,66 @@ func (rr registryRecorder) record(dest *[]tspb.TimeSeriesData) {
})
}

// recordChild filters the metrics in the registry down to those provided in
// the metricsFilter argument, and iterates through any child metrics that
// may exist on said metric. Child metrics whose label sets contains a match
// against the childLabelFilter are recorded into the provided dest slice of
// type tspb.TimeSeriesData.
//
// NB: Only available for Counter and Gauge metrics.
func (rr registryRecorder) recordChild(
dest *[]tspb.TimeSeriesData,
metricsFilter map[string]struct{},
childLabelFilter *prometheusgo.LabelPair,
) {
labels := rr.registry.GetLabels()
rr.registry.Select(metricsFilter, func(name string, v interface{}) {
prom, ok := v.(metric.PrometheusExportable)
if !ok {
return
}
promIter, ok := v.(metric.PrometheusIterable)
if !ok {
return
}
m := prom.ToPrometheusMetric()
m.Label = append(labels, prom.GetLabels()...)

processChildMetric := func(metric *prometheusgo.Metric) {
found := false
for _, label := range metric.Label {
if label.GetName() == childLabelFilter.GetName() &&
label.GetValue() == childLabelFilter.GetValue() {
found = true
break
}
}
if !found {
return
}
var value float64
if metric.Gauge != nil {
value = *metric.Gauge.Value
} else if metric.Counter != nil {
value = *metric.Counter.Value
} else {
return
}
*dest = append(*dest, tspb.TimeSeriesData{
Name: fmt.Sprintf(rr.format, prom.GetName()),
Source: rr.source,
Datapoints: []tspb.TimeSeriesDatapoint{
{
TimestampNanos: rr.timestampNanos,
Value: value,
},
},
})
}
promIter.Each(m.Label, processChildMetric)
})
}

// GetTotalMemory returns either the total system memory (in bytes) or if
// possible the cgroups available memory.
func GetTotalMemory(ctx context.Context) (int64, error) {
Expand Down
Loading