Skip to content

Commit ba38e47

Browse files
juevldmonster
andauthored
add telemetry (#144)
Signed-off-by: Evsyukov Denis <[email protected]> Co-authored-by: Pavel Okhlopkov <[email protected]>
1 parent de66f03 commit ba38e47

File tree

8 files changed

+592
-193
lines changed

8 files changed

+592
-193
lines changed

Diff for: cmd/dmt/main.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,18 @@ func runLint(dir string) {
4040
cfg, err := config.NewDefaultRootConfig(dir)
4141
logger.CheckErr(err)
4242

43+
// init metrics storage
44+
metrics.GetClient(dir)
45+
4346
mng := manager.NewManager(dir, cfg)
4447
mng.Run()
4548
mng.PrintResult()
4649

47-
metricsClient, err := metrics.NewPrometheusMetricsService(os.Getenv("DMT_METRICS_URL"), os.Getenv("DMT_METRICS_TOKEN"))
48-
if err != nil {
49-
logger.ErrorF("Failed to create metrics client: %v", err)
50-
}
50+
metrics.SetDmtInfo()
51+
metrics.SetLinterWarningsMetrics(cfg.GlobalSettings)
52+
metrics.SetDmtRuntimeDuration()
5153

52-
metricsClient.AddMetrics(metrics.GetInfo(dir))
54+
metricsClient := metrics.GetClient(dir)
5355
metricsClient.Send(context.Background())
5456

5557
if mng.HasCriticalErrors() {

Diff for: internal/manager/manager.go

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"github.com/deckhouse/dmt/internal/flags"
3737
"github.com/deckhouse/dmt/internal/fsutils"
3838
"github.com/deckhouse/dmt/internal/logger"
39+
"github.com/deckhouse/dmt/internal/metrics"
3940
"github.com/deckhouse/dmt/internal/module"
4041
"github.com/deckhouse/dmt/internal/values"
4142
"github.com/deckhouse/dmt/pkg"
@@ -207,6 +208,7 @@ func (m *Manager) PrintResult() {
207208

208209
if err.Level == pkg.Warn {
209210
msgColor = color.FgHiYellow
211+
metrics.IncDmtLinterWarningsCount(err.LinterID, err.RuleID)
210212
}
211213

212214
// header

Diff for: internal/metrics/convert.go

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
Copyright 2025 Flant JSC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package metrics
18+
19+
import (
20+
"fmt"
21+
"slices"
22+
"time"
23+
24+
"github.com/deckhouse/dmt/internal/promremote"
25+
)
26+
27+
// GetTimeSeries converts Prometheus metric families to a map of promremote.TimeSeries
28+
// where the key is the metric name and the value is a slice of time series for that metric
29+
func (p *PrometheusMetricsService) GetTimeSeries() []promremote.TimeSeries {
30+
var series []promremote.TimeSeries
31+
32+
metricFamilies, err := p.Gatherer.Gather()
33+
if err != nil {
34+
return nil
35+
}
36+
// Store timestamp for consistent use across series
37+
timestamp := time.Now()
38+
39+
for _, metricFamily := range metricFamilies {
40+
metricName := metricFamily.GetName()
41+
for _, metric := range metricFamily.Metric {
42+
// Create labels from the metric's label pairs
43+
labels := make([]promremote.Label, 0, len(metric.Label)+1) // +1 for the name label
44+
for _, labelPair := range metric.Label {
45+
labels = append(labels, promremote.Label{
46+
Name: labelPair.GetName(),
47+
Value: labelPair.GetValue(),
48+
})
49+
}
50+
51+
// Extract value based on metric type
52+
switch {
53+
case metric.GetCounter() != nil:
54+
// Add counter as a single time series
55+
counterLabels := slices.Clone(labels)
56+
counterLabels = append(counterLabels, promremote.Label{
57+
Name: "__name__",
58+
Value: metricName,
59+
})
60+
61+
series = append(series, promremote.TimeSeries{
62+
Labels: counterLabels,
63+
Datapoint: promremote.Datapoint{
64+
Timestamp: timestamp,
65+
Value: metric.GetCounter().GetValue(),
66+
},
67+
})
68+
69+
case metric.GetGauge() != nil:
70+
// Add gauge as a single time series
71+
gaugeLabels := slices.Clone(labels)
72+
gaugeLabels = append(gaugeLabels, promremote.Label{
73+
Name: "__name__",
74+
Value: metricName,
75+
})
76+
77+
series = append(series, promremote.TimeSeries{
78+
Labels: gaugeLabels,
79+
Datapoint: promremote.Datapoint{
80+
Timestamp: timestamp,
81+
Value: metric.GetGauge().GetValue(),
82+
},
83+
})
84+
85+
case metric.GetHistogram() != nil:
86+
histogram := metric.GetHistogram()
87+
88+
// 1. Add sum time series
89+
sumLabels := slices.Clone(labels)
90+
sumLabels = append(sumLabels, promremote.Label{
91+
Name: "__name__",
92+
Value: metricName + "_sum",
93+
})
94+
95+
series = append(series, promremote.TimeSeries{
96+
Labels: sumLabels,
97+
Datapoint: promremote.Datapoint{
98+
Timestamp: timestamp,
99+
Value: histogram.GetSampleSum(),
100+
},
101+
})
102+
103+
// 2. Add count time series
104+
countLabels := slices.Clone(labels)
105+
countLabels = append(countLabels, promremote.Label{
106+
Name: "__name__",
107+
Value: metricName + "_count",
108+
})
109+
110+
series = append(series, promremote.TimeSeries{
111+
Labels: countLabels,
112+
Datapoint: promremote.Datapoint{
113+
Timestamp: timestamp,
114+
Value: float64(histogram.GetSampleCount()),
115+
},
116+
})
117+
118+
// 3. Add bucket time series
119+
for _, bucket := range histogram.GetBucket() {
120+
bucketLabels := slices.Clone(labels)
121+
bucketLabels = append(bucketLabels,
122+
promremote.Label{
123+
Name: "le",
124+
Value: fmt.Sprintf("%g", bucket.GetUpperBound()),
125+
},
126+
promremote.Label{
127+
Name: "__name__",
128+
Value: metricName + "_bucket",
129+
},
130+
)
131+
132+
series = append(series, promremote.TimeSeries{
133+
Labels: bucketLabels,
134+
Datapoint: promremote.Datapoint{
135+
Timestamp: timestamp,
136+
Value: float64(bucket.GetCumulativeCount()),
137+
},
138+
})
139+
}
140+
141+
case metric.GetSummary() != nil:
142+
summary := metric.GetSummary()
143+
144+
// 1. Add sum time series
145+
sumLabels := slices.Clone(labels)
146+
sumLabels = append(sumLabels, promremote.Label{
147+
Name: "__name__",
148+
Value: metricName + "_sum",
149+
})
150+
151+
series = append(series, promremote.TimeSeries{
152+
Labels: sumLabels,
153+
Datapoint: promremote.Datapoint{
154+
Timestamp: timestamp,
155+
Value: summary.GetSampleSum(),
156+
},
157+
})
158+
159+
// 2. Add count time series
160+
countLabels := slices.Clone(labels)
161+
countLabels = append(countLabels, promremote.Label{
162+
Name: "__name__",
163+
Value: metricName + "_count",
164+
})
165+
166+
series = append(series, promremote.TimeSeries{
167+
Labels: countLabels,
168+
Datapoint: promremote.Datapoint{
169+
Timestamp: timestamp,
170+
Value: float64(summary.GetSampleCount()),
171+
},
172+
})
173+
174+
// 3. Add quantile time series
175+
for _, quantile := range summary.GetQuantile() {
176+
quantileLabels := slices.Clone(labels)
177+
quantileLabels = append(quantileLabels,
178+
promremote.Label{
179+
Name: "quantile",
180+
Value: fmt.Sprintf("%g", quantile.GetQuantile()),
181+
},
182+
promremote.Label{
183+
Name: "__name__",
184+
Value: metricName,
185+
},
186+
)
187+
188+
series = append(series, promremote.TimeSeries{
189+
Labels: quantileLabels,
190+
Datapoint: promremote.Datapoint{
191+
Timestamp: timestamp,
192+
Value: quantile.GetValue(),
193+
},
194+
})
195+
}
196+
}
197+
}
198+
}
199+
200+
return series
201+
}

0 commit comments

Comments
 (0)