readAndMergeMetrics reads metrics from both generated and static files, merges them, and returns a sorted list. Generated metrics are produced by the AST scanner that extracts metric definitions from the coder source code while static metrics are manually maintained (e.g., go_*, process_*, external
()
| 94 | // Note: Static metrics take priority over generated metrics, allowing manual |
| 95 | // overrides for metrics that can't be accurately extracted by the scanner. |
| 96 | func readAndMergeMetrics() ([]*dto.MetricFamily, error) { |
| 97 | generatedMetrics, err := readMetricsFromFile(generatedMetricsFile) |
| 98 | if err != nil { |
| 99 | return nil, xerrors.Errorf("reading generated metrics: %w", err) |
| 100 | } |
| 101 | |
| 102 | staticMetrics, err := readMetricsFromFile(staticMetricsFile) |
| 103 | if err != nil { |
| 104 | return nil, xerrors.Errorf("reading static metrics: %w", err) |
| 105 | } |
| 106 | |
| 107 | // Merge metrics, using a map to deduplicate by name. |
| 108 | metricsByName := make(map[string]*dto.MetricFamily) |
| 109 | |
| 110 | // Add generated metrics first. |
| 111 | for _, m := range generatedMetrics { |
| 112 | metricsByName[*m.Name] = m |
| 113 | } |
| 114 | |
| 115 | // Static metrics overwrite generated metrics if they exist. |
| 116 | for _, m := range staticMetrics { |
| 117 | metricsByName[*m.Name] = m |
| 118 | } |
| 119 | |
| 120 | // Convert back to slice and sort. |
| 121 | var metrics []*dto.MetricFamily |
| 122 | for _, m := range metricsByName { |
| 123 | metrics = append(metrics, m) |
| 124 | } |
| 125 | |
| 126 | sort.Slice(metrics, func(i, j int) bool { |
| 127 | return *metrics[i].Name < *metrics[j].Name |
| 128 | }) |
| 129 | |
| 130 | return metrics, nil |
| 131 | } |
| 132 | |
| 133 | func readPrometheusDoc() ([]byte, error) { |
| 134 | doc, err := os.ReadFile(prometheusDocFile) |
no test coverage detected