Skip to content

docs: update deployments experiments for June 3 release #18196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
32 changes: 11 additions & 21 deletions cli/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,7 @@ func enablePrometheus(
afterCtx(ctx, closeInsightsMetricsCollector)

if vals.Prometheus.CollectAgentStats {
experiments := coderd.ReadExperiments(options.Logger, options.DeploymentValues.Experiments.Value())
closeAgentStatsFunc, err := prometheusmetrics.AgentStats(ctx, logger, options.PrometheusRegistry, options.Database, time.Now(), 0, options.DeploymentValues.Prometheus.AggregateAgentStatsBy.Value(), experiments.Enabled(codersdk.ExperimentWorkspaceUsage))
closeAgentStatsFunc, err := prometheusmetrics.AgentStats(ctx, logger, options.PrometheusRegistry, options.Database, time.Now(), 0, options.DeploymentValues.Prometheus.AggregateAgentStatsBy.Value(), true)
if err != nil {
return nil, xerrors.Errorf("register agent stats prometheus metric: %w", err)
}
Expand Down Expand Up @@ -814,27 +813,18 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
}

// Manage push notifications.
experiments := coderd.ReadExperiments(options.Logger, options.DeploymentValues.Experiments.Value())
if experiments.Enabled(codersdk.ExperimentWebPush) {
if !strings.HasPrefix(options.AccessURL.String(), "https://") {
options.Logger.Warn(ctx, "access URL is not HTTPS, so web push notifications may not work on some browsers", slog.F("access_url", options.AccessURL.String()))
}
webpusher, err := webpush.New(ctx, ptr.Ref(options.Logger.Named("webpush")), options.Database, options.AccessURL.String())
if err != nil {
options.Logger.Error(ctx, "failed to create web push dispatcher", slog.Error(err))
options.Logger.Warn(ctx, "web push notifications will not work until the VAPID keys are regenerated")
webpusher = &webpush.NoopWebpusher{
Msg: "Web Push notifications are disabled due to a system error. Please contact your Coder administrator.",
}
}
options.WebPushDispatcher = webpusher
} else {
options.WebPushDispatcher = &webpush.NoopWebpusher{
// Users will likely not see this message as the endpoints return 404
// if not enabled. Just in case...
Msg: "Web Push notifications are an experimental feature and are disabled by default. Enable the 'web-push' experiment to use this feature.",
if !strings.HasPrefix(options.AccessURL.String(), "https://") {
options.Logger.Warn(ctx, "access URL is not HTTPS, so web push notifications may not work on some browsers", slog.F("access_url", options.AccessURL.String()))
}
webpusher, err := webpush.New(ctx, ptr.Ref(options.Logger.Named("webpush")), options.Database, options.AccessURL.String())
if err != nil {
options.Logger.Error(ctx, "failed to create web push dispatcher", slog.Error(err))
options.Logger.Warn(ctx, "web push notifications will not work until the VAPID keys are regenerated")
webpusher = &webpush.NoopWebpusher{
Msg: "Web Push notifications are disabled due to a system error. Please contact your Coder administrator.",
}
}
options.WebPushDispatcher = webpusher

githubOAuth2ConfigParams, err := getGithubOAuth2ConfigParams(ctx, options.Database, vals)
if err != nil {
Expand Down
35 changes: 15 additions & 20 deletions cli/ssh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1587,8 +1587,8 @@ func TestSSH(t *testing.T) {
t.Parallel()

type testCase struct {
name string
experiment bool
name string

usageAppName string
expectedCalls int
expectedCountSSH int
Expand All @@ -1597,45 +1597,42 @@ func TestSSH(t *testing.T) {
}
tcs := []testCase{
{
name: "NoExperiment",
},
{
name: "Empty",
experiment: true,
name: "Empty",

expectedCalls: 1,
expectedCountSSH: 1,
},
{
name: "SSH",
experiment: true,
name: "SSH",

usageAppName: "ssh",
expectedCalls: 1,
expectedCountSSH: 1,
},
{
name: "Jetbrains",
experiment: true,
name: "Jetbrains",

usageAppName: "jetbrains",
expectedCalls: 1,
expectedCountJetbrains: 1,
},
{
name: "Vscode",
experiment: true,
name: "Vscode",

usageAppName: "vscode",
expectedCalls: 1,
expectedCountVscode: 1,
},
{
name: "InvalidDefaultsToSSH",
experiment: true,
name: "InvalidDefaultsToSSH",

usageAppName: "invalid",
expectedCalls: 1,
expectedCountSSH: 1,
},
{
name: "Disable",
experiment: true,
name: "Disable",

usageAppName: "disable",
},
}
Expand All @@ -1646,9 +1643,7 @@ func TestSSH(t *testing.T) {
t.Parallel()

dv := coderdtest.DeploymentValues(t)
if tc.experiment {
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceUsage)}
}

batcher := &workspacestatstest.StatsBatcher{
LastStats: &agentproto.Stats{},
}
Expand Down
2 changes: 1 addition & 1 deletion cli/vscodessh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestVSCodeSSH(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
dv := coderdtest.DeploymentValues(t)
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceUsage)}

batcher := &workspacestatstest.StatsBatcher{
LastStats: &agentproto.Stats{},
}
Expand Down
14 changes: 5 additions & 9 deletions coderd/agentapi/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,11 @@ func (a *StatsAPI) UpdateStats(ctx context.Context, req *agentproto.UpdateStatsR
slog.F("payload", req),
)

if a.Experiments.Enabled(codersdk.ExperimentWorkspaceUsage) {
// while the experiment is enabled we will not report
// session stats from the agent. This is because it is
// being handled by the CLI and the postWorkspaceUsage route.
req.Stats.SessionCountSsh = 0
req.Stats.SessionCountJetbrains = 0
req.Stats.SessionCountVscode = 0
req.Stats.SessionCountReconnectingPty = 0
}
// Session stats are now handled by the CLI and the postWorkspaceUsage route.
req.Stats.SessionCountSsh = 0
req.Stats.SessionCountJetbrains = 0
req.Stats.SessionCountVscode = 0
req.Stats.SessionCountReconnectingPty = 0

err = a.StatsReporter.ReportAgentStats(
ctx,
Expand Down
4 changes: 1 addition & 3 deletions coderd/agentapi/stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,7 @@ func TestUpdateStates(t *testing.T) {
TimeNowFn: func() time.Time {
return now
},
Experiments: codersdk.Experiments{
codersdk.ExperimentWorkspaceUsage,
},
Experiments: codersdk.Experiments{},
}

// Workspace gets fetched.
Expand Down
11 changes: 1 addition & 10 deletions coderd/apidoc/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 1 addition & 10 deletions coderd/apidoc/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ func New(options *Options) *API {
TemplateBuildTimes: options.MetricsCacheRefreshInterval,
DeploymentStats: options.AgentStatsRefreshInterval,
},
experiments.Enabled(codersdk.ExperimentWorkspaceUsage),
true,
)

oauthConfigs := &httpmw.OAuth2Configs{
Expand Down
11 changes: 8 additions & 3 deletions coderd/prometheusmetrics/insights/metricscollector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func TestCollectInsights(t *testing.T) {
err = json.Unmarshal(goldenFile, &golden)
require.NoError(t, err)

collected := map[string]int{}
var collected map[string]int
ok := assert.Eventuallyf(t, func() bool {
// When
metrics, err := registry.Gather()
Expand All @@ -191,6 +191,7 @@ func TestCollectInsights(t *testing.T) {
}

// Then
currentCollected := map[string]int{}
for _, metric := range metrics {
t.Logf("metric: %s: %#v", metric.GetName(), metric)
switch metric.GetName() {
Expand All @@ -200,14 +201,18 @@ func TestCollectInsights(t *testing.T) {
if len(m.Label) > 0 {
key = key + "[" + metricLabelAsString(m) + "]"
}
collected[key] = int(m.Gauge.GetValue())
currentCollected[key] = int(m.Gauge.GetValue())
}
default:
assert.Failf(t, "unexpected metric collected", "metric: %s", metric.GetName())
}
}

return assert.ObjectsAreEqualValues(golden, collected)
if assert.ObjectsAreEqualValues(golden, currentCollected) {
collected = currentCollected
return true
}
return false
}, testutil.WaitMedium, testutil.IntervalFast, "template insights are inconsistent with golden files")
if !ok {
diff := cmp.Diff(golden, collected)
Expand Down
27 changes: 8 additions & 19 deletions coderd/telemetry/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"os"
"regexp"
"runtime"
"slices"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -605,24 +604,14 @@ func (r *remoteReporter) createSnapshot() (*Snapshot, error) {
return nil
})
eg.Go(func() error {
if r.options.DeploymentConfig != nil && slices.Contains(r.options.DeploymentConfig.Experiments, string(codersdk.ExperimentWorkspaceUsage)) {
agentStats, err := r.options.Database.GetWorkspaceAgentUsageStats(ctx, createdAfter)
if err != nil {
return xerrors.Errorf("get workspace agent stats: %w", err)
}
snapshot.WorkspaceAgentStats = make([]WorkspaceAgentStat, 0, len(agentStats))
for _, stat := range agentStats {
snapshot.WorkspaceAgentStats = append(snapshot.WorkspaceAgentStats, ConvertWorkspaceAgentStat(database.GetWorkspaceAgentStatsRow(stat)))
}
} else {
agentStats, err := r.options.Database.GetWorkspaceAgentStats(ctx, createdAfter)
if err != nil {
return xerrors.Errorf("get workspace agent stats: %w", err)
}
snapshot.WorkspaceAgentStats = make([]WorkspaceAgentStat, 0, len(agentStats))
for _, stat := range agentStats {
snapshot.WorkspaceAgentStats = append(snapshot.WorkspaceAgentStats, ConvertWorkspaceAgentStat(stat))
}
// Use the usage stats version (previously behind ExperimentWorkspaceUsage)
agentStats, err := r.options.Database.GetWorkspaceAgentUsageStats(ctx, createdAfter)
if err != nil {
return xerrors.Errorf("get workspace agent stats: %w", err)
}
snapshot.WorkspaceAgentStats = make([]WorkspaceAgentStat, 0, len(agentStats))
for _, stat := range agentStats {
snapshot.WorkspaceAgentStats = append(snapshot.WorkspaceAgentStats, ConvertWorkspaceAgentStat(database.GetWorkspaceAgentStatsRow(stat)))
}
return nil
})
Expand Down
14 changes: 0 additions & 14 deletions coderd/webpush.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ import (
func (api *API) postUserWebpushSubscription(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user := httpmw.UserParam(r)
if !api.Experiments.Enabled(codersdk.ExperimentWebPush) {
httpapi.ResourceNotFound(rw)
return
}

var req codersdk.WebpushSubscription
if !httpapi.Read(ctx, rw, r, &req) {
Expand Down Expand Up @@ -77,11 +73,6 @@ func (api *API) deleteUserWebpushSubscription(rw http.ResponseWriter, r *http.Re
ctx := r.Context()
user := httpmw.UserParam(r)

if !api.Experiments.Enabled(codersdk.ExperimentWebPush) {
httpapi.ResourceNotFound(rw)
return
}

var req codersdk.DeleteWebpushSubscription
if !httpapi.Read(ctx, rw, r, &req) {
return
Expand Down Expand Up @@ -134,11 +125,6 @@ func (api *API) postUserPushNotificationTest(rw http.ResponseWriter, r *http.Req
ctx := r.Context()
user := httpmw.UserParam(r)

if !api.Experiments.Enabled(codersdk.ExperimentWebPush) {
httpapi.ResourceNotFound(rw)
return
}

// We need to authorize the user to send a push notification to themselves.
if !api.Authorize(r, policy.ActionCreate, rbac.ResourceNotificationMessage.WithOwner(user.ID.String())) {
httpapi.Forbidden(rw)
Expand Down
2 changes: 1 addition & 1 deletion coderd/webpush_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestWebpushSubscribeUnsubscribe(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitShort)

dv := coderdtest.DeploymentValues(t)
dv.Experiments = []string{string(codersdk.ExperimentWebPush)}

client := coderdtest.New(t, &coderdtest.Options{
DeploymentValues: dv,
})
Expand Down
6 changes: 0 additions & 6 deletions coderd/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -1507,12 +1507,6 @@ func (api *API) postWorkspaceUsage(rw http.ResponseWriter, r *http.Request) {

api.statsReporter.TrackUsage(workspace.ID)

if !api.Experiments.Enabled(codersdk.ExperimentWorkspaceUsage) {
// Continue previous behavior if the experiment is not enabled.
rw.WriteHeader(http.StatusNoContent)
return
}

if r.Body == http.NoBody {
// Continue previous behavior if no body is present.
rw.WriteHeader(http.StatusNoContent)
Expand Down
2 changes: 1 addition & 1 deletion coderd/workspaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4126,7 +4126,7 @@ func TestWorkspaceUsageTracking(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
defer cancel()
dv := coderdtest.DeploymentValues(t)
dv.Experiments = []string{string(codersdk.ExperimentWorkspaceUsage)}

client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
DeploymentValues: dv,
})
Expand Down
3 changes: 0 additions & 3 deletions codersdk/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -3353,9 +3353,6 @@ const (
// Add new experiments here!
ExperimentExample Experiment = "example" // This isn't used for anything.
ExperimentAutoFillParameters Experiment = "auto-fill-parameters" // This should not be taken out of experiments until we have redesigned the feature.
ExperimentNotifications Experiment = "notifications" // Sends notifications via SMTP and webhooks following certain events.
ExperimentWorkspaceUsage Experiment = "workspace-usage" // Enables the new workspace usage tracking.
ExperimentWebPush Experiment = "web-push" // Enables web push notifications through the browser.
ExperimentDynamicParameters Experiment = "dynamic-parameters" // Enables dynamic parameters when creating a workspace.
ExperimentWorkspacePrebuilds Experiment = "workspace-prebuilds" // Enables the new workspace prebuilds feature.
ExperimentAgenticChat Experiment = "agentic-chat" // Enables the new agentic AI chat feature.
Expand Down
Loading
Loading