Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9cfd5ba

Browse files
authored
feat(coderd): export metric indicating each experiment's status (#12657)
1 parent1a9f7e7 commit9cfd5ba

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

‎cli/server.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ func enablePrometheus(
258258
),nil
259259
}
260260

261+
//nolint:gocognit // TODO(dannyk): reduce complexity of this function
261262
func (r*RootCmd)Server(newAPIfunc(context.Context,*coderd.Options) (*coderd.API, io.Closer,error))*serpent.Command {
262263
ifnewAPI==nil {
263264
newAPI=func(_ context.Context,o*coderd.Options) (*coderd.API, io.Closer,error) {
@@ -893,6 +894,15 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
893894
returnxerrors.Errorf("register agents prometheus metric: %w",err)
894895
}
895896
defercloseAgentsFunc()
897+
898+
varactive codersdk.Experiments
899+
for_,exp:=rangeoptions.DeploymentValues.Experiments.Value() {
900+
active=append(active,codersdk.Experiment(exp))
901+
}
902+
903+
iferr=prometheusmetrics.Experiments(options.PrometheusRegistry,active);err!=nil {
904+
returnxerrors.Errorf("register experiments metric: %w",err)
905+
}
896906
}
897907

898908
client:=codersdk.New(localURL)

‎coderd/prometheusmetrics/prometheusmetrics.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,32 @@ func AgentStats(ctx context.Context, logger slog.Logger, registerer prometheus.R
516516
},nil
517517
}
518518

519+
// Experiments registers a metric which indicates whether each experiment is enabled or not.
520+
funcExperiments(registerer prometheus.Registerer,active codersdk.Experiments)error {
521+
experimentsGauge:=prometheus.NewGaugeVec(prometheus.GaugeOpts{
522+
Namespace:"coderd",
523+
Name:"experiments",
524+
Help:"Indicates whether each experiment is enabled (1) or not (0)",
525+
}, []string{"experiment"})
526+
iferr:=registerer.Register(experimentsGauge);err!=nil {
527+
returnerr
528+
}
529+
530+
for_,exp:=rangecodersdk.ExperimentsAll {
531+
varvalfloat64
532+
for_,enabled:=rangeactive {
533+
ifexp==enabled {
534+
val=1
535+
break
536+
}
537+
}
538+
539+
experimentsGauge.WithLabelValues(string(exp)).Set(val)
540+
}
541+
542+
returnnil
543+
}
544+
519545
// filterAcceptableAgentLabels handles a slightly messy situation whereby `prometheus-aggregate-agent-stats-by` can control on
520546
// which labels agent stats are aggregated, but for these specific metrics in this file there is no `template` label value,
521547
// and therefore we have to exclude it from the list of acceptable labels.

‎coderd/prometheusmetrics/prometheusmetrics_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,88 @@ func TestAgentStats(t *testing.T) {
500500
assert.EqualValues(t,golden,collected)
501501
}
502502

503+
funcTestExperimentsMetric(t*testing.T) {
504+
t.Parallel()
505+
506+
tests:= []struct {
507+
namestring
508+
experiments codersdk.Experiments
509+
expectedmap[codersdk.Experiment]float64
510+
}{
511+
{
512+
name:"Enabled experiment is exported in metrics",
513+
experiments: codersdk.Experiments{codersdk.ExperimentSharedPorts},
514+
expected:map[codersdk.Experiment]float64{
515+
codersdk.ExperimentSharedPorts:1,
516+
},
517+
},
518+
{
519+
name:"Disabled experiment is exported in metrics",
520+
experiments: codersdk.Experiments{},
521+
expected:map[codersdk.Experiment]float64{
522+
codersdk.ExperimentSharedPorts:0,
523+
},
524+
},
525+
{
526+
name:"Unknown experiment is not exported in metrics",
527+
experiments: codersdk.Experiments{codersdk.Experiment("bob")},
528+
expected:map[codersdk.Experiment]float64{},
529+
},
530+
}
531+
532+
for_,tc:=rangetests {
533+
tc:=tc
534+
535+
t.Run(tc.name,func(t*testing.T) {
536+
t.Parallel()
537+
reg:=prometheus.NewRegistry()
538+
539+
require.NoError(t,prometheusmetrics.Experiments(reg,tc.experiments))
540+
541+
out,err:=reg.Gather()
542+
require.NoError(t,err)
543+
require.Lenf(t,out,1,"unexpected number of registered metrics")
544+
545+
seen:=make(map[codersdk.Experiment]float64)
546+
547+
for_,metric:=rangeout[0].GetMetric() {
548+
require.Equal(t,"coderd_experiments",out[0].GetName())
549+
550+
labels:=metric.GetLabel()
551+
require.Lenf(t,labels,1,"unexpected number of labels")
552+
553+
experiment:=codersdk.Experiment(labels[0].GetValue())
554+
value:=metric.GetGauge().GetValue()
555+
556+
seen[experiment]=value
557+
558+
expectedValue:=0
559+
560+
// Find experiment we expect to be enabled.
561+
for_,exp:=rangetc.experiments {
562+
ifexperiment==exp {
563+
expectedValue=1
564+
break
565+
}
566+
}
567+
568+
require.EqualValuesf(t,expectedValue,value,"expected %d value for experiment %q",expectedValue,experiment)
569+
}
570+
571+
// We don't want to define the state of all experiments because codersdk.ExperimentAll will change at some
572+
// point and break these tests; so we only validate the experiments we know about.
573+
forexp,val:=rangeseen {
574+
expectedVal,found:=tc.expected[exp]
575+
if!found {
576+
t.Logf("ignoring experiment %q; it is not listed in expectations",exp)
577+
continue
578+
}
579+
require.Equalf(t,expectedVal,val,"experiment %q did not match expected value %v",exp,expectedVal)
580+
}
581+
})
582+
}
583+
}
584+
503585
funcprepareWorkspaceAndAgent(t*testing.T,client*codersdk.Client,user codersdk.CreateFirstUserResponse,workspaceNumint)*agentsdk.Client {
504586
authToken:=uuid.NewString()
505587

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp