From 551a8fdfc5b1183e95dc128344d359026008bbcb Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Fri, 3 Feb 2023 00:41:02 +0000 Subject: [PATCH 1/2] chore: add `install_source` to telemetry This will help determine the number of installs from marketplaces! --- coderd/telemetry/telemetry.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/coderd/telemetry/telemetry.go b/coderd/telemetry/telemetry.go index 9d957f40eecb7..f2b8573a54863 100644 --- a/coderd/telemetry/telemetry.go +++ b/coderd/telemetry/telemetry.go @@ -230,6 +230,13 @@ func (r *remoteReporter) deployment() error { if sysInfo.Containerized != nil { containerized = *sysInfo.Containerized } + + // Tracks where Coder was installed from! + installSource := os.Getenv("CODER_TELEMETRY_INSTALL_SOURCE") + if installSource != "" && installSource != "aws_marketplace" { + return xerrors.Errorf("invalid installce source: %s", installSource) + } + data, err := json.Marshal(&Deployment{ ID: r.options.DeploymentID, Architecture: sysInfo.Architecture, @@ -243,6 +250,7 @@ func (r *remoteReporter) deployment() error { OIDCAuth: r.options.OIDCAuth, OIDCIssuerURL: r.options.OIDCIssuerURL, Prometheus: r.options.Prometheus, + InstallSource: installSource, STUN: r.options.STUN, Tunnel: r.options.Tunnel, OSType: sysInfo.OS.Type, @@ -677,6 +685,7 @@ type Deployment struct { OIDCAuth bool `json:"oidc_auth"` OIDCIssuerURL string `json:"oidc_issuer_url"` Prometheus bool `json:"prometheus"` + InstallSource string `json:"install_source"` STUN bool `json:"stun"` OSType string `json:"os_type"` OSFamily string `json:"os_family"` From 928d061d1e6648e69897f04149ae9aa88bbe4053 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Fri, 3 Feb 2023 00:48:10 +0000 Subject: [PATCH 2/2] Add test --- coderd/telemetry/telemetry_test.go | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/coderd/telemetry/telemetry_test.go b/coderd/telemetry/telemetry_test.go index 3df1ba9776b3e..4bc988314a1bb 100644 --- a/coderd/telemetry/telemetry_test.go +++ b/coderd/telemetry/telemetry_test.go @@ -117,7 +117,7 @@ func TestTelemetry(t *testing.T) { }, }) assert.NoError(t, err) - snapshot := collectSnapshot(t, db) + _, snapshot := collectSnapshot(t, db) require.Len(t, snapshot.ParameterSchemas, 1) require.Len(t, snapshot.ProvisionerJobs, 1) require.Len(t, snapshot.Licenses, 1) @@ -140,21 +140,32 @@ func TestTelemetry(t *testing.T) { LoginType: database.LoginTypePassword, }) require.NoError(t, err) - snapshot := collectSnapshot(t, db) + _, snapshot := collectSnapshot(t, db) require.Len(t, snapshot.Users, 1) require.Equal(t, snapshot.Users[0].EmailHashed, "bb44bf07cf9a2db0554bba63a03d822c927deae77df101874496df5a6a3e896d@coder.com") }) } -func collectSnapshot(t *testing.T, db database.Store) *telemetry.Snapshot { +// nolint:paralleltest +func TestTelemetryInstallSource(t *testing.T) { + t.Setenv("CODER_TELEMETRY_INSTALL_SOURCE", "aws_marketplace") + db := databasefake.New() + deployment, _ := collectSnapshot(t, db) + require.Equal(t, "aws_marketplace", deployment.InstallSource) +} + +func collectSnapshot(t *testing.T, db database.Store) (*telemetry.Deployment, *telemetry.Snapshot) { t.Helper() - deployment := make(chan struct{}, 64) + deployment := make(chan *telemetry.Deployment, 64) snapshot := make(chan *telemetry.Snapshot, 64) r := chi.NewRouter() r.Post("/deployment", func(w http.ResponseWriter, r *http.Request) { require.Equal(t, buildinfo.Version(), r.Header.Get(telemetry.VersionHeader)) w.WriteHeader(http.StatusAccepted) - deployment <- struct{}{} + dd := &telemetry.Deployment{} + err := json.NewDecoder(r.Body).Decode(dd) + require.NoError(t, err) + deployment <- dd }) r.Post("/snapshot", func(w http.ResponseWriter, r *http.Request) { require.Equal(t, buildinfo.Version(), r.Header.Get(telemetry.VersionHeader)) @@ -176,6 +187,5 @@ func collectSnapshot(t *testing.T, db database.Store) *telemetry.Snapshot { }) require.NoError(t, err) t.Cleanup(reporter.Close) - <-deployment - return <-snapshot + return <-deployment, <-snapshot }