From c5ea17918834fc03059a37c8dc1011ed34f42c4e Mon Sep 17 00:00:00 2001 From: Alex Castilio Date: Thu, 23 Jan 2025 17:34:10 +0000 Subject: [PATCH] feat: add metricscardinality to heartbeat (#1235) # Description Add `metricscardinality` to heartbeat. This will give visibility on the number of time series being exposed by retina. ## Related Issue #1040 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/contributing). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Metrics exported with heartbeat: ![image](https://github.com/user-attachments/assets/6fb4d76b-5780-4751-91c0-46e3c4f0fb85) ## Additional Notes Metrics of types `histogram` and `summary` expose multiple time series during a scrape. Code is counting according to number of time series exposed at /metrics endpoint. Ref: https://prometheus.io/docs/concepts/metric_types/#histogram https://prometheus.io/docs/concepts/metric_types/#summary --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. Signed-off-by: Alex Castilio dos Santos --- pkg/telemetry/telemetry.go | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go index 4984df42db..b680728784 100644 --- a/pkg/telemetry/telemetry.go +++ b/pkg/telemetry/telemetry.go @@ -10,12 +10,15 @@ import ( "os" "runtime" "runtime/debug" + "strconv" "sync" "time" "github.com/microsoft/ApplicationInsights-Go/appinsights" "github.com/microsoft/ApplicationInsights-Go/appinsights/contracts" + "github.com/microsoft/retina/pkg/exporter" "github.com/microsoft/retina/pkg/log" + io_prometheus_client "github.com/prometheus/client_model/go" ) var ( @@ -174,10 +177,55 @@ func (t *TelemetryClient) heartbeat(ctx context.Context) { if err != nil { t.trackWarning(err, "failed to get cpu usage") } + + metricscardinality, err := metricsCardinality() + if err != nil { + t.trackWarning(err, "failed to get metrics cardinality") + } + + props["metricscardinality"] = strconv.Itoa(metricscardinality) + maps.Copy(props, cpuProps) maps.Copy(props, t.profile.GetMemoryUsage()) t.TrackEvent("heartbeat", props) } +func metricsCardinality() (int, error) { + metricFamilies, err := exporter.CombinedGatherer.Gather() + if err != nil { + return 0, fmt.Errorf("failed to gather metrics: %w", err) + } + + metricscardinality := 0 + + for _, mf := range metricFamilies { + switch mf.GetType() { //nolint:exhaustive // 'default' satisfies exhaustiveness + + case io_prometheus_client.MetricType_HISTOGRAM: + metrics := mf.GetMetric() + for _, m := range metrics { + metricscardinality += len(m.GetHistogram().GetBucket()) + 3 // +3 for le="+Inf", _sum and _count + } + + case io_prometheus_client.MetricType_GAUGE_HISTOGRAM: + metrics := mf.GetMetric() + for _, m := range metrics { + metricscardinality += len(m.GetHistogram().GetBucket()) + 3 // +3 for le="+Inf", _sum and _count + } + + case io_prometheus_client.MetricType_SUMMARY: + metrics := mf.GetMetric() + for _, m := range metrics { + metricscardinality += len(m.GetSummary().GetQuantile()) + 2 // +2 for _sum and _count + } + + default: + metricscardinality += len(mf.GetMetric()) + + } + } + + return metricscardinality, nil +} func bToMb(b uint64) uint64 { return b >> mbShift