The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/registry/apis/provisioning/usage/usage.go

85 lines
2.8 KiB

package usage
import (
"context"
"fmt"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apiserver/pkg/endpoints/request"
"github.com/grafana/grafana/pkg/apimachinery/identity"
listers "github.com/grafana/grafana/pkg/generated/listers/provisioning/v0alpha1"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
)
func MetricCollector(tracer tracing.Tracer, repositoryLister listers.RepositoryLister, unified resource.ResourceClient) usagestats.MetricsFunc {
return func(ctx context.Context) (metrics map[string]any, err error) {
ctx, span := tracer.Start(ctx, "Provisioning.Usage.collectProvisioningStats")
defer func() {
span.SetStatus(codes.Error, fmt.Sprintf("failed to fetch provisioning usage stats: %v", err))
span.End()
}()
m := map[string]any{}
if unified == nil {
// FIXME: does this case make any sense? no unified storage -> no game
span.SetStatus(codes.Ok, "unified storage is not available")
return m, nil
}
// FIXME: hardcoded to "default" for now -- it works for single tenant deployments
// we could discover the set of valid namespaces, but that would count everything for
// each instance in cloud.
ns := "default"
ctx, _, err = identity.WithProvisioningIdentity(ctx, ns)
if err != nil {
return nil, err
}
ctx = request.WithNamespace(ctx, ns)
// FIXME: hardcoded to "default" for now -- it works for single tenant deployments
// we could discover the set of valid namespaces, but that would count everything for
// each instance in cloud.
//
// We could get namespaces from the list of repos below, but that could be zero
// while we still have resources managed by terraform, etc
count, err := unified.CountManagedObjects(ctx, &resourcepb.CountManagedObjectsRequest{
Namespace: ns,
})
if err != nil {
return m, fmt.Errorf("count managed objects: %w", err)
}
counts := make(map[string]int, 10)
for _, v := range count.Items {
counts[v.Kind] = counts[v.Kind] + int(v.Count)
}
span.SetAttributes(attribute.Int("totalManagedObjectsCount", len(count.Items)))
for k, v := range counts {
m[fmt.Sprintf("stats.managed_by.%s.count", k)] = v
}
// Inspect all configs
repos, err := repositoryLister.List(labels.Everything())
if err != nil {
return m, fmt.Errorf("list repositories: %w", err)
}
clear(counts)
for _, repo := range repos {
counts[string(repo.Spec.Type)] = counts[string(repo.Spec.Type)] + 1
}
span.SetAttributes(attribute.Int("repositoryCount", len(repos)))
// Count how many items of each repository type
for k, v := range counts {
m[fmt.Sprintf("stats.repository.%s.count", k)] = v
}
return m, nil
}
}