mirror of https://github.com/coder/coder.git
feat(coderd): add enabled experiments to telemetry (#12656)
This commit is contained in:
parent
f0f9569d51
commit
ab95ae827d
|
@ -11,9 +11,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coder/coder/v2/testutil"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/coder/coder/v2/testutil"
|
||||||
|
|
||||||
"github.com/coder/coder/v2/cli/cliui"
|
"github.com/coder/coder/v2/cli/cliui"
|
||||||
"github.com/coder/coder/v2/coderd/database/dbtime"
|
"github.com/coder/coder/v2/coderd/database/dbtime"
|
||||||
"github.com/coder/coder/v2/codersdk"
|
"github.com/coder/coder/v2/codersdk"
|
||||||
|
|
|
@ -819,6 +819,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
|
||||||
Prometheus: vals.Prometheus.Enable.Value(),
|
Prometheus: vals.Prometheus.Enable.Value(),
|
||||||
STUN: len(vals.DERP.Server.STUNAddresses) != 0,
|
STUN: len(vals.DERP.Server.STUNAddresses) != 0,
|
||||||
Tunnel: tunnel != nil,
|
Tunnel: tunnel != nil,
|
||||||
|
Experiments: vals.Experiments.Value(),
|
||||||
ParseLicenseJWT: func(lic *telemetry.License) error {
|
ParseLicenseJWT: func(lic *telemetry.License) error {
|
||||||
// This will be nil when running in AGPL-only mode.
|
// This will be nil when running in AGPL-only mode.
|
||||||
if options.ParseLicenseClaims == nil {
|
if options.ParseLicenseClaims == nil {
|
||||||
|
|
|
@ -54,6 +54,7 @@ type Options struct {
|
||||||
SnapshotFrequency time.Duration
|
SnapshotFrequency time.Duration
|
||||||
Tunnel bool
|
Tunnel bool
|
||||||
ParseLicenseJWT func(lic *License) error
|
ParseLicenseJWT func(lic *License) error
|
||||||
|
Experiments []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New constructs a reporter for telemetry data.
|
// New constructs a reporter for telemetry data.
|
||||||
|
@ -480,6 +481,10 @@ func (r *remoteReporter) createSnapshot() (*Snapshot, error) {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
eg.Go(func() error {
|
||||||
|
snapshot.Experiments = ConvertExperiments(r.options.Experiments)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
err := eg.Wait()
|
err := eg.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -741,6 +746,16 @@ func ConvertExternalProvisioner(id uuid.UUID, tags map[string]string, provisione
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ConvertExperiments(experiments []string) []Experiment {
|
||||||
|
var out []Experiment
|
||||||
|
|
||||||
|
for _, exp := range experiments {
|
||||||
|
out = append(out, Experiment{Name: exp})
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// Snapshot represents a point-in-time anonymized database dump.
|
// Snapshot represents a point-in-time anonymized database dump.
|
||||||
// Data is aggregated by latest on the server-side, so partial data
|
// Data is aggregated by latest on the server-side, so partial data
|
||||||
// can be sent without issue.
|
// can be sent without issue.
|
||||||
|
@ -763,6 +778,7 @@ type Snapshot struct {
|
||||||
WorkspaceResourceMetadata []WorkspaceResourceMetadata `json:"workspace_resource_metadata"`
|
WorkspaceResourceMetadata []WorkspaceResourceMetadata `json:"workspace_resource_metadata"`
|
||||||
WorkspaceResources []WorkspaceResource `json:"workspace_resources"`
|
WorkspaceResources []WorkspaceResource `json:"workspace_resources"`
|
||||||
Workspaces []Workspace `json:"workspaces"`
|
Workspaces []Workspace `json:"workspaces"`
|
||||||
|
Experiments []Experiment `json:"experiments"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deployment contains information about the host running Coder.
|
// Deployment contains information about the host running Coder.
|
||||||
|
@ -971,6 +987,10 @@ type ExternalProvisioner struct {
|
||||||
ShutdownAt *time.Time `json:"shutdown_at"`
|
ShutdownAt *time.Time `json:"shutdown_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Experiment struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
type noopReporter struct{}
|
type noopReporter struct{}
|
||||||
|
|
||||||
func (*noopReporter) Report(_ *Snapshot) {}
|
func (*noopReporter) Report(_ *Snapshot) {}
|
||||||
|
|
|
@ -85,7 +85,7 @@ func TestTelemetry(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, _ = dbgen.WorkspaceProxy(t, db, database.WorkspaceProxy{})
|
_, _ = dbgen.WorkspaceProxy(t, db, database.WorkspaceProxy{})
|
||||||
|
|
||||||
_, snapshot := collectSnapshot(t, db)
|
_, snapshot := collectSnapshot(t, db, nil)
|
||||||
require.Len(t, snapshot.ProvisionerJobs, 1)
|
require.Len(t, snapshot.ProvisionerJobs, 1)
|
||||||
require.Len(t, snapshot.Licenses, 1)
|
require.Len(t, snapshot.Licenses, 1)
|
||||||
require.Len(t, snapshot.Templates, 1)
|
require.Len(t, snapshot.Templates, 1)
|
||||||
|
@ -110,21 +110,32 @@ func TestTelemetry(t *testing.T) {
|
||||||
_ = dbgen.User(t, db, database.User{
|
_ = dbgen.User(t, db, database.User{
|
||||||
Email: "kyle@coder.com",
|
Email: "kyle@coder.com",
|
||||||
})
|
})
|
||||||
_, snapshot := collectSnapshot(t, db)
|
_, snapshot := collectSnapshot(t, db, nil)
|
||||||
require.Len(t, snapshot.Users, 1)
|
require.Len(t, snapshot.Users, 1)
|
||||||
require.Equal(t, snapshot.Users[0].EmailHashed, "bb44bf07cf9a2db0554bba63a03d822c927deae77df101874496df5a6a3e896d@coder.com")
|
require.Equal(t, snapshot.Users[0].EmailHashed, "bb44bf07cf9a2db0554bba63a03d822c927deae77df101874496df5a6a3e896d@coder.com")
|
||||||
})
|
})
|
||||||
|
t.Run("Experiments", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
const expName = "my-experiment"
|
||||||
|
exps := []string{expName}
|
||||||
|
_, snapshot := collectSnapshot(t, dbmem.New(), func(opts telemetry.Options) telemetry.Options {
|
||||||
|
opts.Experiments = exps
|
||||||
|
return opts
|
||||||
|
})
|
||||||
|
require.Equal(t, []telemetry.Experiment{{Name: expName}}, snapshot.Experiments)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:paralleltest
|
// nolint:paralleltest
|
||||||
func TestTelemetryInstallSource(t *testing.T) {
|
func TestTelemetryInstallSource(t *testing.T) {
|
||||||
t.Setenv("CODER_TELEMETRY_INSTALL_SOURCE", "aws_marketplace")
|
t.Setenv("CODER_TELEMETRY_INSTALL_SOURCE", "aws_marketplace")
|
||||||
db := dbmem.New()
|
db := dbmem.New()
|
||||||
deployment, _ := collectSnapshot(t, db)
|
deployment, _ := collectSnapshot(t, db, nil)
|
||||||
require.Equal(t, "aws_marketplace", deployment.InstallSource)
|
require.Equal(t, "aws_marketplace", deployment.InstallSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectSnapshot(t *testing.T, db database.Store) (*telemetry.Deployment, *telemetry.Snapshot) {
|
func collectSnapshot(t *testing.T, db database.Store, addOptionsFn func(opts telemetry.Options) telemetry.Options) (*telemetry.Deployment, *telemetry.Snapshot) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
deployment := make(chan *telemetry.Deployment, 64)
|
deployment := make(chan *telemetry.Deployment, 64)
|
||||||
snapshot := make(chan *telemetry.Snapshot, 64)
|
snapshot := make(chan *telemetry.Snapshot, 64)
|
||||||
|
@ -149,12 +160,17 @@ func collectSnapshot(t *testing.T, db database.Store) (*telemetry.Deployment, *t
|
||||||
t.Cleanup(server.Close)
|
t.Cleanup(server.Close)
|
||||||
serverURL, err := url.Parse(server.URL)
|
serverURL, err := url.Parse(server.URL)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
reporter, err := telemetry.New(telemetry.Options{
|
options := telemetry.Options{
|
||||||
Database: db,
|
Database: db,
|
||||||
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
|
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
|
||||||
URL: serverURL,
|
URL: serverURL,
|
||||||
DeploymentID: uuid.NewString(),
|
DeploymentID: uuid.NewString(),
|
||||||
})
|
}
|
||||||
|
if addOptionsFn != nil {
|
||||||
|
options = addOptionsFn(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
reporter, err := telemetry.New(options)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Cleanup(reporter.Close)
|
t.Cleanup(reporter.Close)
|
||||||
return <-deployment, <-snapshot
|
return <-deployment, <-snapshot
|
||||||
|
|
Loading…
Reference in New Issue