diff --git a/components/dashboard/src/admin/Settings.tsx b/components/dashboard/src/admin/Settings.tsx index d901fd2a83b1c3..2da3975859552f 100644 --- a/components/dashboard/src/admin/Settings.tsx +++ b/components/dashboard/src/admin/Settings.tsx @@ -45,24 +45,47 @@ export default function Settings() { subtitle="Configure settings for your Gitpod cluster." >

Usage Statistics

+

+ We collect usage telemetry to gain insights on how you use your Gitpod instance, so we can provide a + better overall experience. +

+

+ + Read our Privacy Policy + +

- The following usage data is sent to provide insights on how you use your Gitpod instance, so - we can provide a better overall experience.{" "} - - Read our Privacy Policy - + Enable usage telemetry on your Gitpod instance. A preview of your telemetry is available + below. } checked={adminSettings?.sendTelemetry ?? false} onChange={(evt) => actuallySetTelemetryPrefs({ + ...adminSettings, sendTelemetry: evt.target.checked, - }) + } as InstallationAdminSettings) } /> + + Include an optional customer ID in usage telemetry to provide individualized support. + + } + checked={adminSettings?.sendCustomerID ?? false} + onChange={(evt) => + actuallySetTelemetryPrefs({ + ...adminSettings, + sendCustomerID: evt.target.checked, + } as InstallationAdminSettings) + } + /> +

Telemetry preview

{JSON.stringify(telemetryData, null, 2)}
diff --git a/components/gitpod-protocol/src/installation-admin-protocol.ts b/components/gitpod-protocol/src/installation-admin-protocol.ts index ce3869fcd43d7d..f9f4870570ed4d 100644 --- a/components/gitpod-protocol/src/installation-admin-protocol.ts +++ b/components/gitpod-protocol/src/installation-admin-protocol.ts @@ -8,6 +8,7 @@ import { v4 as uuidv4 } from "uuid"; const InstallationAdminSettingsPrototype = { sendTelemetry: true, + sendCustomerID: true, }; export type InstallationAdminSettings = typeof InstallationAdminSettingsPrototype; @@ -29,6 +30,7 @@ export interface TelemetryData { totalWorkspaces: number; totalInstances: number; licenseType: string; + customerID?: string; } export namespace InstallationAdmin { diff --git a/components/installation-telemetry/cmd/send.go b/components/installation-telemetry/cmd/send.go index 3b9a4bc1ada568..196085ef23ead3 100644 --- a/components/installation-telemetry/cmd/send.go +++ b/components/installation-telemetry/cmd/send.go @@ -50,15 +50,20 @@ var sendCmd = &cobra.Command{ err = client.Close() }() + properties := analytics.NewProperties(). + Set("version", versionId). + Set("totalUsers", data.TotalUsers). + Set("totalWorkspaces", data.TotalWorkspaces). + Set("totalInstances", data.TotalInstances) + + if data.InstallationAdmin.Settings.SendCustomerID { + properties.Set("customerID", data.CustomerID) + } + telemetry := analytics.Track{ - UserId: data.InstallationAdmin.ID, - Event: "Installation telemetry", - Properties: analytics.NewProperties(). - Set("version", versionId). - Set("totalUsers", data.TotalUsers). - Set("totalWorkspaces", data.TotalWorkspaces). - Set("totalInstances", data.TotalInstances). - Set("licenseType", data.LicenseType), + UserId: data.InstallationAdmin.ID, + Event: "Installation telemetry", + Properties: properties, } client.Enqueue(telemetry) diff --git a/components/installation-telemetry/pkg/server/installationAdmin.go b/components/installation-telemetry/pkg/server/installationAdmin.go index c78520498946ac..489af244b8843b 100644 --- a/components/installation-telemetry/pkg/server/installationAdmin.go +++ b/components/installation-telemetry/pkg/server/installationAdmin.go @@ -14,7 +14,8 @@ import ( ) type InstallationAdminSettings struct { - SendTelemetry bool `json:"sendTelemetry"` + SendTelemetry bool `json:"sendTelemetry"` + SendCustomerID bool `json:"sendCustomerID"` } type Data struct { @@ -23,6 +24,7 @@ type Data struct { TotalWorkspaces int64 `json:"totalWorkspaces"` TotalInstances int64 `json:"totalInstances"` LicenseType string `json:"licenseType"` + CustomerID string `json:"customerID,omitempty"` } type InstallationAdmin struct { diff --git a/components/licensor/ee/pkg/licensor/licensor.go b/components/licensor/ee/pkg/licensor/licensor.go index 1b05a57d094643..3e1ee8bdfeebd8 100644 --- a/components/licensor/ee/pkg/licensor/licensor.go +++ b/components/licensor/ee/pkg/licensor/licensor.go @@ -53,6 +53,9 @@ type LicensePayload struct { // Seats == 0 means there's no seat limit Seats int `json:"seats"` + + // CustomerID is used to identify installations in installation analytics + CustomerID string `json:"customerID"` } type licensePayload struct { diff --git a/components/licensor/ee/pkg/licensor/replicated.go b/components/licensor/ee/pkg/licensor/replicated.go index 4793488174c9a2..9d67e28c480a48 100644 --- a/components/licensor/ee/pkg/licensor/replicated.go +++ b/components/licensor/ee/pkg/licensor/replicated.go @@ -118,6 +118,9 @@ func newReplicatedEvaluator(client *http.Client) (res *Evaluator) { case "seats": lic.Seats = int(i.Value.(float64)) + + case "customerId": + lic.CustomerID = i.Value.(string) } } diff --git a/components/licensor/typescript/ee/src/api.ts b/components/licensor/typescript/ee/src/api.ts index 84d8a65b58dd31..c3e2c8814a1ba5 100644 --- a/components/licensor/typescript/ee/src/api.ts +++ b/components/licensor/typescript/ee/src/api.ts @@ -29,6 +29,7 @@ export interface LicensePayload { level: LicenseLevel validUntil: string seats: number + customerID: string } export enum LicenseSubscriptionLevel { diff --git a/components/server/src/installation-admin/telemetry-data-provider.ts b/components/server/src/installation-admin/telemetry-data-provider.ts index 8adfd054f671cb..5647931e5360b5 100644 --- a/components/server/src/installation-admin/telemetry-data-provider.ts +++ b/components/server/src/installation-admin/telemetry-data-provider.ts @@ -27,7 +27,13 @@ export class InstallationAdminTelemetryDataProvider { totalWorkspaces: await this.workspaceDb.getWorkspaceCount(), totalInstances: await this.workspaceDb.getInstanceCount(), licenseType: this.licenseEvaluator.getLicenseData().type, + customerID: this.licenseEvaluator.getLicenseData().payload.customerID, } as TelemetryData; + + if (data.installationAdmin.settings.sendCustomerID) { + data.customerID = this.licenseEvaluator.getLicenseData().payload.customerID; + } + return data; } finally { span.finish();