Skip to content

Commit 17235ec

Browse files
committed
roachprod,cli: metric name consolidation in tsdump upload
Previously, tsdump was uploading time series data with metrics name defined in registry. This was inadequate because same metric has different name in the Datadog integration based on offering. We are working on consolidating observability stack across our offerings. To address this, this patch updates the tsdump upload functionality generate metrics renaming during execution. We have updated gen-cockroachdb-metrics tool to generate yaml files. The generation will support comprehensive and datadog only mode. In the comprehensive mode, we are generating crdb metrics renaming mapping. The datadog only mode would only generate the datadog integration metric renaming mapping file. We had to created datadog only mode to avoid circular dependency on package cli. Part of: CRDB-56324 Epic: None Release note: None
1 parent a027188 commit 17235ec

File tree

14 files changed

+4981
-2714
lines changed

14 files changed

+4981
-2714
lines changed

build/tools/gen-cockroachdb-metrics/main.go

Lines changed: 151 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Use of this software is governed by the CockroachDB Software License
44
// included in the /LICENSE file.
55

6-
// gen-cockroachdb-metrics generates the cockroachdb_metrics.go file for roachprod's OpenTelemetry
6+
// gen-cockroachdb-metrics generates the cockroachdb_metrics.yaml file for roachprod's OpenTelemetry
77
// integration, enabling proper metric forwarding to Datadog from CockroachDB clusters.
88
//
99
// This generator creates a comprehensive mapping of CockroachDB metric names to Datadog-compatible
@@ -31,7 +31,7 @@
3131
// c) Processes metrics.yaml and runtime_conditional_metrics, converting them to Prometheus format and applying
3232
// Datadog naming conventions (including histogram variants like _bucket, _count, _sum)
3333
// d) Merges the processed mappings with legacy_metrics
34-
// e) Generates cockroachdb_metrics.go containing the final consolidated mapping
34+
// e) Generates cockroachdb_metrics.yaml containing the final consolidated mapping
3535

3636
package main
3737

@@ -108,43 +108,63 @@ var (
108108
prometheusNameRegex = regexp.MustCompile(`[^a-zA-Z0-9]`)
109109
)
110110

111-
// Go code template for generating the cockroachdb_metrics.go file
112-
const goTemplate = `// Copyright 2024 The Cockroach Authors.
113-
//
114-
// Use of this software is governed by the CockroachDB Software License
115-
// included in the /LICENSE file.
116-
//
117-
// DO NOT EDIT THIS FILE MANUALLY
118-
//
119-
// This file is auto-generated when running "./dev generate".
120-
// Manual edits will be overwritten.
121-
//
122-
// Generator: build/tools/gen-cockroachdb-metrics
123-
//
124-
// This file is generated by merging metrics from three sources:
125-
// 1. runtime_conditional_metrics from cockroachdb_metrics_base.yaml
126-
// - Conditionally emitted metrics not documented in metrics.yaml
127-
// - Processed through Datadog mapping rules
128-
// 2. legacy_metrics from cockroachdb_metrics_base.yaml
129-
// - Legacy metrics from older CRDB versions for backward compatibility
130-
// - Used as-is
131-
// 3. docs/generated/metrics/metrics.yaml
132-
// - All current metrics documented in the latest CRDB version
133-
// - Processed through Datadog mapping rules
134-
135-
package opentelemetry
136-
137-
// cockroachdbMetrics is a mapping of CockroachDB metric names to cockroachdb
138-
// Datadog integration metric names. This allows CockroachDB metrics to comply
139-
// with the naming requirements for the cockroachdb Datadog integration listed
140-
// in its metadata.csv.
141-
// - https://github.com/DataDog/integrations-core/blob/master/cockroachdb/metadata.csv
142-
143-
var cockroachdbMetrics = map[string]string{
111+
// YAML template for generating the cockroachdb_metrics.yaml file
112+
const yamlTemplate = `# Copyright 2024 The Cockroach Authors.
113+
#
114+
# Use of this software is governed by the CockroachDB Software License
115+
# included in the /LICENSE file.
116+
#
117+
# DO NOT EDIT THIS FILE MANUALLY
118+
#
119+
# This file is auto-generated when running "./dev generate".
120+
# Manual edits will be overwritten.
121+
#
122+
# Generator: build/tools/gen-cockroachdb-metrics
123+
#
124+
# This file is generated by merging metrics from three sources:
125+
# 1. runtime_conditional_metrics from cockroachdb_metrics_base.yaml
126+
# - Conditionally emitted metrics not documented in metrics.yaml
127+
# - Processed through Datadog mapping rules
128+
# 2. legacy_metrics from cockroachdb_metrics_base.yaml
129+
# - Legacy metrics from older CRDB versions for backward compatibility
130+
# - Used as-is
131+
# 3. docs/generated/metrics/metrics.yaml
132+
# - All current metrics documented in the latest CRDB version
133+
# - Processed through Datadog mapping rules
134+
#
135+
# cockroachdbMetrics is a mapping of CockroachDB metric names to cockroachdb
136+
# Datadog integration metric names. This allows CockroachDB metrics to comply
137+
# with the naming requirements for the cockroachdb Datadog integration listed
138+
# in its metadata.csv.
139+
# - https://github.com/DataDog/integrations-core/blob/master/cockroachdb/metadata.csv
140+
144141
{{- range $key, $value := .Metrics }}
145-
"{{ $key }}": "{{ $value }}",
142+
{{ $key }}: {{ $value }}
143+
{{- end }}
144+
`
145+
146+
// YAML template for generating the raw Datadog mappings YAML file
147+
const datadogMappingsTemplate = `# Copyright 2025 The Cockroach Authors.
148+
#
149+
# Use of this software is governed by the CockroachDB Software License
150+
# included in the /LICENSE file.
151+
#
152+
# DO NOT EDIT THIS FILE MANUALLY
153+
#
154+
# This file is auto-generated when running "./dev generate".
155+
# Manual edits will be overwritten.
156+
#
157+
# Generator: build/tools/gen-cockroachdb-metrics
158+
#
159+
# Source: https://github.com/DataDog/integrations-core/blob/master/cockroachdb/datadog_checks/cockroachdb/metrics.py
160+
#
161+
# This file contains the raw Datadog metric name mappings from METRIC_MAP and OMV2_METRIC_MAP.
162+
# The key is the CockroachDB metric name in Prometheus format, and the value is the
163+
# corresponding metric name as it appears in Datadog.
164+
165+
{{- range $key, $value := .Metrics }}
166+
{{ $key }}: {{ $value }}
146167
{{- end }}
147-
}
148168
`
149169

150170
// loadDatadogMappings loads the Datadog metrics mapping from a local file
@@ -170,9 +190,9 @@ func parseDatadogMappings(r io.Reader) (map[string]string, error) {
170190

171191
// CRDB-Datadog mappings are stored as python dictionaries in the following file:
172192
// https://github.com/DataDog/integrations-core/blob/master/cockroachdb/datadog_checks/cockroachdb/metrics.py
173-
// - METRIC_MAP: represents the raw CRDB-Datadog metric name mapping.
193+
// - METRIC_MAP: represents the raw CRDB-Datadog metric name mapping.
174194
// - OMV2_METRIC_MAP: represents the metric in OpenMetrics V2 format.
175-
// E.g.
195+
// E.g.
176196
// 'admission_errored_sql_kv_response': 'admission.errored.sql_kv.response'
177197
// here the key is the CRDB metric name in prometheus format, and the value is the corresponding metric name visible in Datadog.
178198
// Both maps are mutually exclusive. Parse both dictionaries to get the complete mapping.
@@ -214,12 +234,17 @@ func parsePythonDict(lines []string, dictName string) (map[string]string, error)
214234
break
215235
}
216236

237+
// Skip commented lines
238+
if strings.HasPrefix(trimmed, "#") {
239+
continue
240+
}
241+
217242
// Parse metric mapping line: 'key': 'value',
218243
if strings.Contains(trimmed, ":") && strings.Contains(trimmed, "'") {
219244
parts := strings.SplitN(trimmed, ":", 2)
220245
if len(parts) == 2 {
221-
key := strings.Trim(strings.TrimSpace(parts[0]), "'\"")
222-
value := strings.Trim(strings.TrimSpace(parts[1]), "',\"")
246+
key := strings.Trim(strings.TrimSpace(parts[0]), " '\"")
247+
value := strings.Trim(strings.TrimSpace(parts[1]), " ',\"")
223248
if key != "" && value != "" {
224249
metrics[strings.ToLower(key)] = value
225250
}
@@ -348,9 +373,47 @@ func mergeLegacyMappings(legacyMappings, newMappings map[string]string) map[stri
348373
return result
349374
}
350375

351-
// writeGoFile generates the cockroachdb_metrics.go file
352-
func writeGoFile(outputPath string, metrics map[string]string) error {
353-
tmpl, err := template.New("cockroachdb_metrics").Parse(goTemplate)
376+
// writeYAMLFile generates the cockroachdb_metrics.yaml file
377+
func writeYAMLFile(outputPath string, metrics map[string]string) error {
378+
tmpl, err := template.New("cockroachdb_metrics").Parse(yamlTemplate)
379+
if err != nil {
380+
return fmt.Errorf("parsing template: %w", err)
381+
}
382+
383+
// Sort keys for consistent output
384+
keys := make([]string, 0, len(metrics))
385+
for k := range metrics {
386+
keys = append(keys, k)
387+
}
388+
sort.Strings(keys)
389+
390+
sortedMetrics := make(map[string]string)
391+
for _, k := range keys {
392+
sortedMetrics[k] = metrics[k]
393+
}
394+
395+
file, err := os.Create(outputPath)
396+
if err != nil {
397+
return fmt.Errorf("creating file: %w", err)
398+
}
399+
defer file.Close()
400+
401+
data := struct {
402+
Metrics map[string]string
403+
}{
404+
Metrics: sortedMetrics,
405+
}
406+
407+
if err := tmpl.Execute(file, data); err != nil {
408+
return fmt.Errorf("executing template: %w", err)
409+
}
410+
411+
return nil
412+
}
413+
414+
// writeDatadogMappingsYAML generates the raw Datadog mappings YAML file
415+
func writeDatadogMappingsYAML(outputPath string, metrics map[string]string) error {
416+
tmpl, err := template.New("datadog_mappings").Parse(datadogMappingsTemplate)
354417
if err != nil {
355418
return fmt.Errorf("parsing template: %w", err)
356419
}
@@ -386,9 +449,51 @@ func writeGoFile(outputPath string, metrics map[string]string) error {
386449
return nil
387450
}
388451

452+
func printUsage() {
453+
fmt.Fprintf(os.Stderr, "Usage:\n")
454+
fmt.Fprintf(os.Stderr, " Generate CockroachDB metrics with Datadog mappings:\n")
455+
fmt.Fprintf(os.Stderr, " %s <metrics.yaml> <output.yaml> <datadog-mappings.py> [base.yaml]\n\n", os.Args[0])
456+
fmt.Fprintf(os.Stderr, " Generate raw Datadog mappings only:\n")
457+
fmt.Fprintf(os.Stderr, " %s --datadog-only <datadog-mappings.py> <output.yaml>\n", os.Args[0])
458+
}
459+
389460
func main() {
461+
if len(os.Args) < 2 {
462+
printUsage()
463+
os.Exit(1)
464+
}
465+
466+
// Check if running in datadog-only mode
467+
if os.Args[1] == "--datadog-only" {
468+
if len(os.Args) < 4 {
469+
printUsage()
470+
os.Exit(1)
471+
}
472+
473+
datadogMappingsPath := os.Args[2]
474+
outputPath := os.Args[3]
475+
476+
datadogMappings, err := loadDatadogMappings(datadogMappingsPath)
477+
if err != nil {
478+
fmt.Fprintln(os.Stderr, "ERROR:", err)
479+
os.Exit(1)
480+
}
481+
482+
if err := writeDatadogMappingsYAML(outputPath, datadogMappings); err != nil {
483+
fmt.Fprintln(os.Stderr, "ERROR:", err)
484+
os.Exit(1)
485+
}
486+
487+
if !strings.Contains(outputPath, "-exec-") && !strings.Contains(outputPath, "for tool") {
488+
fmt.Printf("Generated %d raw Datadog metric mappings\n", len(datadogMappings))
489+
fmt.Printf("Output written to: %s\n", outputPath)
490+
}
491+
return
492+
}
493+
494+
// Normal mode: generate cockroachdb_metrics.yaml
390495
if len(os.Args) < 4 {
391-
fmt.Fprintf(os.Stderr, "Usage: %s <metrics.yaml> <output.go> <datadog-mappings.py> [base.yaml]\n", os.Args[0])
496+
printUsage()
392497
os.Exit(1)
393498
}
394499

@@ -424,7 +529,7 @@ func main() {
424529
newMappings := mapMetricsToDatadog(allMetrics, datadogMappings)
425530
finalMappings := mergeLegacyMappings(baseMetrics.LegacyMetrics, newMappings)
426531

427-
if err := writeGoFile(outputPath, finalMappings); err != nil {
532+
if err := writeYAMLFile(outputPath, finalMappings); err != nil {
428533
fmt.Fprintln(os.Stderr, "ERROR:", err)
429534
os.Exit(1)
430535
}

pkg/cli/BUILD.bazel

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
22
load("//build:STRINGER.bzl", "stringer")
33
load("//pkg/testutils:buildutil/buildutil.bzl", "disallowed_imports_test")
44

5+
genrule(
6+
name = "cockroachdb_datadog_metrics",
7+
srcs = ["@datadog_cockroachdb_metrics//:metrics.py"],
8+
outs = ["files/cockroachdb_datadog_metrics.yaml"],
9+
cmd = "$(location //build/tools/gen-cockroachdb-metrics) --datadog-only $(location @datadog_cockroachdb_metrics//:metrics.py) $@",
10+
tools = ["//build/tools/gen-cockroachdb-metrics"],
11+
visibility = ["//pkg/gen:__pkg__"],
12+
)
13+
514
go_library(
615
name = "cli",
716
srcs = [
@@ -97,6 +106,10 @@ go_library(
97106
cppopts = [
98107
"-DJEMALLOC_NO_DEMANGLE",
99108
],
109+
embedsrcs = [
110+
"files/cockroachdb_metrics_base.yaml",
111+
"files/cockroachdb_datadog_metrics.yaml",
112+
],
100113
importpath = "github.com/cockroachdb/cockroach/pkg/cli",
101114
visibility = ["//visibility:public"],
102115
deps = [
@@ -231,6 +244,7 @@ go_library(
231244
"//pkg/util/tracing/tracingpb",
232245
"//pkg/util/tracing/zipper",
233246
"//pkg/util/uuid",
247+
"//pkg/util/yamlutil",
234248
"//pkg/workload",
235249
"//pkg/workload/bank",
236250
"//pkg/workload/bulkingest",

0 commit comments

Comments
 (0)