Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions central/metrics/custom/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import (
"github.com/stackrox/rox/central/metrics/custom/tracker"
custom "github.com/stackrox/rox/central/metrics/custom/tracker"
policyDS "github.com/stackrox/rox/central/policy/datastore"
"github.com/stackrox/rox/central/telemetry/centralclient"
"github.com/stackrox/rox/generated/storage"
"github.com/stackrox/rox/pkg/grpc/authn"
"github.com/stackrox/rox/pkg/logging"
"github.com/stackrox/rox/pkg/sac"
"github.com/stackrox/rox/pkg/telemetry/phonehome/telemeter"
)

type trackerRunner []struct {
Expand Down Expand Up @@ -158,4 +160,16 @@ func (tr trackerRunner) ServeHTTP(w http.ResponseWriter, req *http.Request) {
registry.Lock()
defer registry.Unlock()
registry.ServeHTTP(w, req)
go phonehome()
}

func phonehome() {
props := map[string]any{
"Total custom Prometheus registries": metrics.GetCustomRegistriesCount(),
}

centralclient.Singleton().Telemeter().Track(
"Served custom Prometheus metrics", nil,
telemeter.WithTraits(props),
telemeter.WithNoDuplicates("prom_registries"))
}
31 changes: 30 additions & 1 deletion central/metrics/custom/tracker/tracker_base.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
package tracker

import (
"cmp"
"context"
"iter"
"maps"
"net/http"
"slices"
"strings"
"sync/atomic"
"time"

"github.com/pkg/errors"
"github.com/stackrox/rox/central/metrics"
"github.com/stackrox/rox/central/telemetry/centralclient"
"github.com/stackrox/rox/generated/storage"
"github.com/stackrox/rox/pkg/grpc/authn"
"github.com/stackrox/rox/pkg/logging"
"github.com/stackrox/rox/pkg/set"
"github.com/stackrox/rox/pkg/sync"
"github.com/stackrox/rox/pkg/telemetry/phonehome/telemeter"
)

var (
Expand Down Expand Up @@ -269,10 +274,34 @@ func (tracker *TrackerBase[Finding]) Gather(ctx context.Context) {
if cfg.period == 0 || time.Since(gatherer.lastGather) < cfg.period {
return
}
begin := time.Now()
if err := tracker.track(ctx, gatherer.registry, cfg.metrics); err != nil {
log.Errorf("Failed to gather %s metrics: %v", tracker.description, err)
}
gatherer.lastGather = time.Now()
end := time.Now()
gatherer.lastGather = end

descriptionTitle := strings.ToTitle(tracker.description[0:1]) + tracker.description[1:]
centralclient.Singleton().Telemeter().Track(
descriptionTitle+" metrics gathered", nil,
telemeter.WithTraits(tracker.makeProps(descriptionTitle, end.Sub(begin))),
telemeter.WithNoDuplicates(tracker.metricPrefix))
}

func (tracker *TrackerBase[Finding]) makeProps(descriptionTitle string, duration time.Duration) map[string]any {
props := make(map[string]any, 3)
props["Total "+descriptionTitle+" metrics"] = len(tracker.config.metrics)
props[descriptionTitle+" metrics labels"] = getLabels(tracker.config.metrics)
props[descriptionTitle+" gathering seconds"] = uint32(duration.Round(time.Second).Seconds())
return props
}

func getLabels(metrics MetricDescriptors) []Label {
labels := set.NewSet[Label]()
for _, metricLabels := range metrics {
labels.AddAll(metricLabels...)
}
return labels.AsSortedSlice(cmp.Less)
}

// getGatherer returns the existing or a new gatherer for the given userID.
Expand Down
31 changes: 31 additions & 0 deletions central/metrics/custom/tracker/tracker_base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"iter"
"maps"
"slices"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -307,3 +308,33 @@ func makeAdminContext(t *testing.T) context.Context {
ctx := basic.ContextWithAdminIdentity(t, authProvider)
return ctx
}

func Test_makeProps(t *testing.T) {
ctrl := gomock.NewController(t)
rf := mocks.NewMockCustomRegistry(ctrl)

tracker := MakeTrackerBase("test", "telemetry test",
testLabelGetters,
makeTestGatherFunc(testData))
tracker.registryFactory = func(string) metrics.CustomRegistry { return rf }

md := makeTestMetricDescriptors(t)
tracker.Reconfigure(&Configuration{
metrics: md,
toAdd: slices.Collect(maps.Keys(md)),
period: time.Hour,
})
descriptionTitle := strings.ToTitle(tracker.description[0:1]) + tracker.description[1:]
props := tracker.makeProps(descriptionTitle, 12345*time.Millisecond)
get := func(key string) any {
if v, ok := props[key]; ok {
return v
}
return nil
}

assert.Len(t, props, 3)
assert.ElementsMatch(t, get("Telemetry test metrics labels"), []Label{"Cluster", "Namespace", "Severity"})
assert.Equal(t, len(md), get("Total Telemetry test metrics"))
assert.Equal(t, uint32(12), get("Telemetry test gathering seconds"))
}
8 changes: 8 additions & 0 deletions central/metrics/custom_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,11 @@ func (cr *customRegistry) Reset(metricName string) {
gauge.(*prometheus.GaugeVec).Reset()
}
}

// GetCustomRegistriesCount returns the total number of currently known custom
// registries.
func GetCustomRegistriesCount() int {
registriesMux.Lock()
defer registriesMux.Unlock()
return len(userRegistries)
}
Loading