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
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
3636package 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+
389460func 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 }
0 commit comments