grafana/pkg/tsdb/grafana-pyroscope-datasource/profile_metadata.go

90 lines
2.5 KiB
Go

package pyroscope
import (
_ "embed"
"encoding/json"
"sync"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
)
//go:embed profile-metrics.json
var profileMetricsJSON []byte
type ProfileMetadata struct {
ID string `json:"id"`
Description string `json:"description"`
Type string `json:"type"`
Group string `json:"group"`
Unit string `json:"unit"`
AggregationType string `json:"aggregationType"`
}
type ProfileMetadataRegistry struct {
profiles map[string]*ProfileMetadata
mu sync.RWMutex
logger log.Logger
}
var (
registry *ProfileMetadataRegistry
registryOnce sync.Once
)
// GetProfileMetadataRegistry returns the singleton instance of the profile metadata registry
func GetProfileMetadataRegistry() *ProfileMetadataRegistry {
registryOnce.Do(func() {
registry = &ProfileMetadataRegistry{
profiles: make(map[string]*ProfileMetadata),
logger: backend.NewLoggerWith("logger", "tsdb.pyroscope.profile-metadata"),
}
registry.loadProfileMetadata()
})
return registry
}
// loadProfileMetadata loads the profile metadata from the embedded JSON file
func (r *ProfileMetadataRegistry) loadProfileMetadata() {
var profilesMap map[string]*ProfileMetadata
err := json.Unmarshal(profileMetricsJSON, &profilesMap)
if err != nil {
r.logger.Error("Failed to parse embedded profile-metrics.json", "error", err)
return
}
r.mu.Lock()
defer r.mu.Unlock()
r.profiles = profilesMap
r.logger.Info("Loaded profile metadata", "count", len(profilesMap))
}
// GetProfileMetadata returns the metadata for a given profile type ID
func (r *ProfileMetadataRegistry) GetProfileMetadata(profileTypeID string) *ProfileMetadata {
r.mu.RLock()
defer r.mu.RUnlock()
return r.profiles[profileTypeID]
}
// IsCumulativeProfile returns true if the profile type requires rate calculation
func (r *ProfileMetadataRegistry) IsCumulativeProfile(profileTypeID string) bool {
metadata := r.GetProfileMetadata(profileTypeID)
if metadata == nil {
r.logger.Debug("Profile metadata not found, using fallback logic", "profileTypeID", profileTypeID)
return isCumulativeProfileUnitFallback(getUnits(profileTypeID))
}
return metadata.AggregationType == "cumulative"
}
// isCumulativeProfileUnitFallback is the (old) fallback logic for unknown profile types
func isCumulativeProfileUnitFallback(unit string) bool {
switch unit {
case "ns":
return true
case "bytes":
return true
default:
return false
}
}