github.com/grafana/pyroscope@v1.18.0/pkg/featureflags/feature_flags.go (about)

     1  package featureflags
     2  
     3  import (
     4  	"context"
     5  	"sort"
     6  
     7  	"connectrpc.com/connect"
     8  	"github.com/prometheus/client_golang/prometheus"
     9  	"github.com/prometheus/client_golang/prometheus/promauto"
    10  
    11  	capabilitiesv1 "github.com/grafana/pyroscope/api/gen/proto/go/capabilities/v1"
    12  )
    13  
    14  const (
    15  	V2StorageLayer          = "v2StorageLayer"
    16  	PyroscopeRuler          = "pyroscopeRuler"
    17  	PyroscopeRulerFunctions = "pyroscopeRulerFunctions"
    18  	UTF8LabelNames          = "utf8LabelNames"
    19  )
    20  
    21  func stringPtr(s string) *string {
    22  	return &s
    23  }
    24  
    25  var (
    26  	allFeatureFlags = map[string]*capabilitiesv1.FeatureFlag{
    27  		V2StorageLayer: {
    28  			Enabled:          false,
    29  			Description:      stringPtr("v2 storage layer"),
    30  			DocumentationUrl: stringPtr("https://github.com/grafana/pyroscope/blob/main/pkg/pyroscope/PYROSCOPE_V2.md"),
    31  		},
    32  		PyroscopeRuler: {
    33  			Enabled:     false,
    34  			Description: stringPtr("Supports the Pyroscope ruler, which exports Prometheus metrics from Profiling Data."),
    35  		},
    36  		PyroscopeRulerFunctions: {
    37  			Enabled:     false,
    38  			Description: stringPtr("Enables function support for the Pyroscope ruler, which allows to export resource usage on a per function level."),
    39  		},
    40  		UTF8LabelNames: {
    41  			Enabled:     false,
    42  			Description: stringPtr("Supports UTF-8 label names for Pyroscope read/write APIs."),
    43  		},
    44  	}
    45  )
    46  
    47  type FeatureFlags struct {
    48  	flags      []*capabilitiesv1.FeatureFlag
    49  	infoMetric *prometheus.GaugeVec
    50  }
    51  
    52  func (h *FeatureFlags) GetFeatureFlags(
    53  	ctx context.Context,
    54  	req *connect.Request[capabilitiesv1.GetFeatureFlagsRequest],
    55  ) (*connect.Response[capabilitiesv1.GetFeatureFlagsResponse], error) {
    56  	return &connect.Response[capabilitiesv1.GetFeatureFlagsResponse]{
    57  		Msg: &capabilitiesv1.GetFeatureFlagsResponse{
    58  			FeatureFlags: h.flags,
    59  		},
    60  	}, nil
    61  }
    62  
    63  func boolToFloat64(b bool) float64 {
    64  	if b {
    65  		return 1.0
    66  	}
    67  	return 0.0
    68  }
    69  
    70  func NewFromEnabled(reg prometheus.Registerer, enabled map[string]bool) *FeatureFlags {
    71  	ff := &FeatureFlags{
    72  		infoMetric: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{
    73  			Name: "pyroscope_feature_flags_enabled",
    74  			Help: "Shows the global feature flags",
    75  		}, []string{"name"}),
    76  	}
    77  
    78  	ff.flags = make([]*capabilitiesv1.FeatureFlag, 0, len(allFeatureFlags))
    79  	for name, flag := range allFeatureFlags {
    80  		flag := flag.CloneVT()
    81  		flag.Name = name
    82  		ff.flags = append(ff.flags, flag)
    83  		flag.Enabled = enabled[name]
    84  		enabled[name] = true
    85  		ff.infoMetric.WithLabelValues(flag.Name).Set(boolToFloat64(flag.Enabled))
    86  	}
    87  	sort.Slice(ff.flags, func(i, j int) bool {
    88  		return ff.flags[i].Name < ff.flags[j].Name
    89  
    90  	})
    91  
    92  	return ff
    93  }