Skip to content

Commit 3be4e0b

Browse files
Pothulapatiroboquat
authored andcommitted
telmetry: show collected data under the disable option
Currently, The service ping can be disabled by going into the admin settings. Users are more likely to do that if they have no clue what is being sent. This PR tries to improve this experience, by showcasing the exact data that is being sent below the option. This is possible by creating a new TelemetryDataProvider and injecting that both in the `installation-admin-collector` controller and the `gitpod-service` (`getTelemetryData` func is added here that can be used). This PR also adds a gaurd to the `/admin/settings` page which was missing previously Signed-off-by: Tarun Pothulapati <[email protected]> replace cluster with gitpod instance in desc Signed-off-by: Tarun Pothulapati <[email protected]> easy nits around design and TelemetryData naming Signed-off-by: Tarun Pothulapati <[email protected]> gaurd telemetry method with admin access Signed-off-by: Tarun Pothulapati <[email protected]> replace TelemetryData at more places Signed-off-by: Tarun Pothulapati <[email protected]> gaurd access to `admin/settings` like other admin settings Signed-off-by: Tarun Pothulapati <[email protected]> call useEffect hook early Signed-off-by: Tarun Pothulapati <[email protected]>
1 parent 8fa98f9 commit 3be4e0b

File tree

8 files changed

+73
-19
lines changed

8 files changed

+73
-19
lines changed

components/dashboard/src/admin/Settings.tsx

+21-3
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,32 @@
55
*/
66

77
import { useContext } from "react";
8-
import { InstallationAdminSettings } from "@gitpod/gitpod-protocol";
8+
import { TelemetryData, InstallationAdminSettings } from "@gitpod/gitpod-protocol";
99
import { AdminContext } from "../admin-context";
1010
import CheckBox from "../components/CheckBox";
1111
import { PageWithSubMenu } from "../components/PageWithSubMenu";
1212
import { getGitpodService } from "../service/service";
1313
import { adminMenu } from "./admin-menu";
14+
import { useEffect, useState } from "react";
15+
import InfoBox from "../components/InfoBox";
16+
import { Redirect } from "react-router-dom";
17+
import { UserContext } from "../user-context";
1418

1519
export default function Settings() {
1620
const { adminSettings, setAdminSettings } = useContext(AdminContext);
21+
const [telemetryData, setTelemetryData] = useState<TelemetryData>();
22+
const { user } = useContext(UserContext);
23+
24+
useEffect(() => {
25+
(async () => {
26+
const data = await getGitpodService().server.adminGetTelemetryData();
27+
setTelemetryData(data)
28+
})();
29+
});
30+
31+
if (!user || !user?.rolesOrPermissions?.includes('admin')) {
32+
return <Redirect to="/"/>
33+
}
1734

1835
const actuallySetTelemetryPrefs = async (value: InstallationAdminSettings) => {
1936
await getGitpodService().server.adminUpdateSettings(value);
@@ -26,12 +43,13 @@ export default function Settings() {
2643
<h3>Usage Statistics</h3>
2744
<CheckBox
2845
title="Enable Service Ping"
29-
desc={<span>This is used to provide insights on how you use your cluster so we can provide a better overall experience. <a className="gp-link" href="https://www.gitpod.io/privacy">Read our Privacy Policy</a></span>}
46+
desc={<span>The following usage data is sent to provide insights on how you use your Gitpod instance, so we can provide a better overall experience. <a className="gp-link" href="https://www.gitpod.io/privacy">Read our Privacy Policy</a></span>}
3047
checked={adminSettings?.sendTelemetry ?? false}
3148
onChange={(evt) => actuallySetTelemetryPrefs({
3249
sendTelemetry: evt.target.checked,
3350
})} />
34-
</PageWithSubMenu>
51+
<InfoBox><pre>{JSON.stringify(telemetryData, null, 2)}</pre></InfoBox>
52+
</PageWithSubMenu >
3553
</div >
3654
)
3755
}

components/gitpod-protocol/src/gitpod-service.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { GithubUpgradeURL, PlanCoupon } from './payment-protocol';
3030
import { TeamSubscription, TeamSubscriptionSlot, TeamSubscriptionSlotResolved } from './team-subscription-protocol';
3131
import { RemotePageMessage, RemoteTrackMessage, RemoteIdentifyMessage } from './analytics';
3232
import { IDEServer } from './ide-protocol';
33-
import { InstallationAdminSettings } from './installation-admin-protocol';
33+
import { InstallationAdminSettings, TelemetryData } from './installation-admin-protocol';
3434

3535
export interface GitpodClient {
3636
onInstanceUpdate(instance: WorkspaceInstance): void;
@@ -136,6 +136,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
136136
// Admin Settings
137137
adminGetSettings(): Promise<InstallationAdminSettings>;
138138
adminUpdateSettings(settings: InstallationAdminSettings): Promise<void>;
139+
adminGetTelemetryData(): Promise<TelemetryData>;
139140

140141
// Projects
141142
getProviderRepositoriesForUser(params: GetProviderRepositoriesParams): Promise<ProviderRepository[]>;

components/gitpod-protocol/src/installation-admin-protocol.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export interface InstallationAdmin {
2323
settings: InstallationAdminSettings;
2424
}
2525

26-
export interface Data {
26+
export interface TelemetryData {
2727
installationAdmin: InstallationAdmin
2828
totalUsers: number
2929
totalWorkspaces: number

components/server/src/auth/rate-limiter.ts

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ function getConfig(config: RateLimiterConfig): RateLimiterConfig {
148148
"adminSetLicense": { group: "default", points: 1 },
149149
"adminGetSettings": { group: "default", points: 1 },
150150
"adminUpdateSettings": { group: "default", points: 1 },
151+
"adminGetTelemetryData": {group: "default", points: 1},
151152

152153
"validateLicense": { group: "default", points: 1 },
153154
"getLicenseInfo": { group: "default", points: 1 },

components/server/src/container-module.ts

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ import { DebugApp } from './debug-app';
8181
import { LocalMessageBroker, LocalRabbitMQBackedMessageBroker } from './messaging/local-message-broker';
8282
import { contentServiceBinder } from '@gitpod/content-service/lib/sugar';
8383
import { ReferrerPrefixParser } from './workspace/referrer-prefix-context-parser';
84+
import { InstallationAdminTelemetryDataProvider } from './installation-admin/telemetry-data-provider';
8485

8586
export const productionContainerModule = new ContainerModule((bind, unbind, isBound, rebind) => {
8687
bind(Config).toConstantValue(ConfigFile.fromFile());
@@ -193,6 +194,8 @@ export const productionContainerModule = new ContainerModule((bind, unbind, isBo
193194

194195
bind(TermsProvider).toSelf().inSingletonScope();
195196

197+
bind(InstallationAdminTelemetryDataProvider).toSelf().inSingletonScope();
198+
196199
// binds all content services
197200
(contentServiceBinder((ctx) => {
198201
const config = ctx.container.get<Config>(Config);

components/server/src/installation-admin/installation-admin-controller.ts

+3-13
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,17 @@
66

77
import { injectable, inject } from 'inversify';
88
import * as express from 'express';
9-
import { InstallationAdminDB, UserDB, WorkspaceDB } from '@gitpod/gitpod-db/lib';
10-
import { Data } from '@gitpod/gitpod-protocol'
9+
import { InstallationAdminTelemetryDataProvider } from './telemetry-data-provider';
1110

1211
@injectable()
1312
export class InstallationAdminController {
14-
@inject(InstallationAdminDB) protected readonly installationAdminDb: InstallationAdminDB;
15-
@inject(UserDB) protected readonly userDb: UserDB
16-
@inject(WorkspaceDB) protected readonly workspaceDb: WorkspaceDB
13+
@inject(InstallationAdminTelemetryDataProvider) protected readonly telemetryDataProvider: InstallationAdminTelemetryDataProvider;
1714

1815
public create(): express.Application {
1916
const app = express();
2017

2118
app.get('/data', async (req: express.Request, res: express.Response) => {
22-
const data: Data = {
23-
installationAdmin: await this.installationAdminDb.getData(),
24-
totalUsers: await this.userDb.getUserCount(true),
25-
totalWorkspaces: await this.workspaceDb.getWorkspaceCount(),
26-
totalInstances: await this.workspaceDb.getInstanceCount(),
27-
} as Data;
28-
29-
res.status(200).json(data);
19+
res.status(200).json(await this.telemetryDataProvider.getTelemetryData());
3020
});
3121

3222
return app;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright (c) 2020 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License-AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { injectable, inject } from 'inversify';
8+
9+
import { TelemetryData } from "@gitpod/gitpod-protocol"
10+
import { InstallationAdminDB, UserDB, WorkspaceDB } from '@gitpod/gitpod-db/lib';
11+
12+
@injectable()
13+
export class InstallationAdminTelemetryDataProvider {
14+
@inject(InstallationAdminDB) protected readonly installationAdminDb: InstallationAdminDB;
15+
@inject(UserDB) protected readonly userDb: UserDB
16+
@inject(WorkspaceDB) protected readonly workspaceDb: WorkspaceDB
17+
18+
async getTelemetryData(): Promise<TelemetryData> {
19+
const data: TelemetryData = {
20+
installationAdmin: await this.installationAdminDb.getData(),
21+
totalUsers: await this.userDb.getUserCount(true),
22+
totalWorkspaces: await this.workspaceDb.getWorkspaceCount(),
23+
totalInstances: await this.workspaceDb.getInstanceCount(),
24+
} as TelemetryData;
25+
26+
return data;
27+
}
28+
}

components/server/src/workspace/gitpod-server-impl.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ import { PartialProject } from '@gitpod/gitpod-protocol/src/teams-projects-proto
5757
import { ClientMetadata, traceClientMetadata } from '../websocket/websocket-connection-manager';
5858
import { ConfigurationService } from '../config/configuration-service';
5959
import { ProjectEnvVar } from '@gitpod/gitpod-protocol/src/protocol';
60-
import { InstallationAdminSettings } from '@gitpod/gitpod-protocol';
60+
import { InstallationAdminSettings, TelemetryData } from '@gitpod/gitpod-protocol';
6161
import { Deferred } from '@gitpod/gitpod-protocol/lib/util/deferred';
62+
import { InstallationAdminTelemetryDataProvider } from '../installation-admin/telemetry-data-provider';
6263

6364
// shortcut
6465
export const traceWI = (ctx: TraceContext, wi: Omit<LogContext, "userId">) => TraceContext.setOWI(ctx, wi); // userId is already taken care of in WebsocketConnectionManager
@@ -80,6 +81,8 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
8081
@inject(HostContextProvider) protected readonly hostContextProvider: HostContextProvider;
8182
@inject(GitpodFileParser) protected readonly gitpodParser: GitpodFileParser;
8283
@inject(InstallationAdminDB) protected readonly installationAdminDb: InstallationAdminDB;
84+
@inject(InstallationAdminTelemetryDataProvider) protected readonly telemetryDataProvider: InstallationAdminTelemetryDataProvider;
85+
8386

8487
@inject(WorkspaceStarter) protected readonly workspaceStarter: WorkspaceStarter;
8588
@inject(WorkspaceManagerClientProvider) protected readonly workspaceManagerClientProvider: WorkspaceManagerClientProvider;
@@ -2222,6 +2225,16 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
22222225
await this.installationAdminDb.setSettings(newSettings);
22232226
}
22242227

2228+
async adminGetTelemetryData(ctx: TraceContext): Promise<TelemetryData> {
2229+
traceAPIParams(ctx, {});
2230+
2231+
await this.guardAdminAccess("adminGetTelemetryData", {}, Permission.ADMIN_API);
2232+
2233+
return await this.telemetryDataProvider.getTelemetryData();
2234+
}
2235+
2236+
2237+
22252238
async getLicenseInfo(): Promise<GetLicenseInfoResult> {
22262239
throw new ResponseError(ErrorCodes.EE_FEATURE, `Licensing is implemented in Gitpod's Enterprise Edition`);
22272240
}

0 commit comments

Comments
 (0)