Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9e9e47b
Ask user about collecting data (disabled for now)
gzdunek Dec 21, 2022
93b2558
Add `UsageEventService`, generate `IAppContext` basing on `AppContext`
gzdunek Dec 21, 2022
40858ae
Add gRPC method to report usage events
gzdunek Dec 21, 2022
7c55c5c
Extend `RuntimeSettings` with some os/connect info
gzdunek Dec 21, 2022
3a682f9
Collect actual events
gzdunek Dec 21, 2022
ceb2097
Merge branch 'master' into gzdunek/collect-usage-events
gzdunek Dec 30, 2022
f985129
Revert adding `runBeforeUiIsVisible/runAfterUiIsVisible` to context, …
gzdunek Dec 30, 2022
febea18
Move logger to the class
gzdunek Dec 30, 2022
5aac72c
Send events in dev mode
gzdunek Dec 30, 2022
2b1093e
Revert changes to `IAppContext`
gzdunek Dec 30, 2022
943ebb6
Remove tshd usage events, create Prehog events directly
gzdunek Dec 30, 2022
1e4505e
Remove `connect.` from `distinctId` (it will be added in prehog)
gzdunek Dec 30, 2022
b97f5d7
Rename `UsageEventService` to `UsageService`
gzdunek Jan 3, 2023
492fe48
Rename `UsageEventWithDate` to `ReportUsageEventRequest`
gzdunek Jan 3, 2023
10a2977
Rename `prehogEvent`, `prehogApiEvent` etc
gzdunek Jan 3, 2023
c04639e
Add more comments
gzdunek Jan 3, 2023
98dd193
Merge branch 'master' into gzdunek/collect-usage-events
gzdunek Jan 3, 2023
3b27e8c
Read version from `package.json` in dev mode
gzdunek Jan 3, 2023
1aca8f9
Fix tests
gzdunek Jan 3, 2023
b74a13d
Rename method and type in `UsageService`
gzdunek Jan 3, 2023
7a6a408
Rename `ReportEvent` to `ReportUsageEvent` in gRPC service for better…
gzdunek Jan 3, 2023
d596be5
Move warning up, adjust some methods names to events names
gzdunek Jan 3, 2023
207d623
Rename `connectVersion` to `appVersion`
gzdunek Jan 3, 2023
02df49a
Show warning when reporting usage event fails
gzdunek Jan 3, 2023
a860fa9
Merge branch 'master' into gzdunek/collect-usage-events
gzdunek Jan 4, 2023
97f8c63
Provide `authClusterId` in `getClusterProperties`
gzdunek Jan 4, 2023
e8e394d
Update protos to final version
gzdunek Jan 10, 2023
7836241
Collect connector type
gzdunek Jan 10, 2023
3330210
Pass prehog address to tshd
gzdunek Jan 10, 2023
a69c7af
Merge branch 'master' into gzdunek/collect-usage-events
gzdunek Jan 10, 2023
b3ac84d
Merge branch 'master' into gzdunek/collect-usage-events
gzdunek Jan 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/teleterm/src/mainProcess/fixtures/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class MockMainProcessClient implements MainProcessClient {
this.getRuntimeSettings().platform
);
}

getRuntimeSettings(): RuntimeSettings {
return { ...defaultRuntimeSettings, ...this.runtimeSettings };
}
Expand All @@ -22,7 +23,9 @@ export class MockMainProcessClient implements MainProcessClient {
Promise.resolve({ tsh: '', shared: '' });

openTerminalContextMenu() {}

openClusterContextMenu() {}

openTabContextMenu() {}

showFileSaveDialog() {
Expand All @@ -40,6 +43,7 @@ export class MockMainProcessClient implements MainProcessClient {
async symlinkTshMacOs() {
return true;
}

async removeTshSymlinkMacOs() {
return true;
}
Expand Down Expand Up @@ -67,4 +71,7 @@ const defaultRuntimeSettings = {
requestedNetworkAddress: '',
},
installationId: '123e4567-e89b-12d3-a456-426614174000',
arch: 'arm64',
osVersion: '22.2.0',
appVersion: '11.1.0',
};
13 changes: 13 additions & 0 deletions packages/teleterm/src/mainProcess/runtimeSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const dev = env.NODE_ENV === 'development' || env.DEBUG_PROD === 'true';
// Allows running tsh in insecure mode (development)
const isInsecure = dev || argv.includes('--insecure');

const PREHOG_ADDR = 'https://reporting-staging.teleportinfra.dev'; // TODO(gzdunek): change to prod before going live
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See, if we had a proper config file for dev & prod, we could use staging in dev and the prod address in the packaged app.

We have to spend a little bit of time on that some time. I'm thinking of adding something like dotenv. Perhaps there are other libs which are better suited for the kind of app we're working on.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'm happy to do it in a proper way. I think for now we can leave it as it is (we don't have prod env for Connect yet) and I will fix it soon.


function getRuntimeSettings(): RuntimeSettings {
const userDataDir = app.getPath('userData');
const {
Expand All @@ -49,6 +51,7 @@ function getRuntimeSettings(): RuntimeSettings {
// for tshd we have to specify the protocol as well.
`--addr=${tshAddress}`,
`--certs-dir=${getCertsDir()}`,
`--prehog-addr=${PREHOG_ADDR}`,
],
};
const sharedProcess = {
Expand Down Expand Up @@ -77,6 +80,16 @@ function getRuntimeSettings(): RuntimeSettings {
installationId: loadInstallationId(
path.resolve(app.getPath('userData'), 'installation_id')
),
arch: os.arch(),
osVersion: os.release(),
// To start the app in dev mode we run `electron path_to_main.js`. It means
// that app is run without package.json context, so it can not read the version
// from it.
// The way we run Electron can be changed (`electron .`), but it has one major
// drawback - dev app and bundled app will use the same app data directory.
//
// A workaround is to read the version from `process.env.npm_package_version`.
appVersion: dev ? process.env.npm_package_version : app.getVersion(),
};
}

Expand Down
3 changes: 3 additions & 0 deletions packages/teleterm/src/mainProcess/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export type RuntimeSettings = {
requestedNetworkAddress: string;
};
installationId: string;
arch: string;
osVersion: string;
appVersion: string;
};

export type MainProcessClient = {
Expand Down
15 changes: 15 additions & 0 deletions packages/teleterm/src/services/tshd/createClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import middleware, { withLogging } from './middleware';
import * as types from './types';
import createAbortController from './createAbortController';
import { AccessRequest, ResourceID } from './v1/access_request_pb';
import { mapUsageEvent } from './mapUsageEvent';
import { ReportUsageEventRequest } from './types';

export default function createClient(
addr: string,
Expand Down Expand Up @@ -655,6 +657,19 @@ export default function createClient(
});
});
},

reportUsageEvent(event: ReportUsageEventRequest) {
const req = mapUsageEvent(event);
return new Promise<void>((resolve, reject) => {
tshd.reportUsageEvent(req, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
},
};
return client;
}
Expand Down
1 change: 1 addition & 0 deletions packages/teleterm/src/services/tshd/fixtures/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export class MockTshClient implements TshClient {
) => Promise<undefined>;
logout: (clusterUri: string) => Promise<undefined>;
transferFile: () => undefined;
reportUsageEvent: () => undefined;
}

export const gateway: Gateway = {
Expand Down
93 changes: 93 additions & 0 deletions packages/teleterm/src/services/tshd/mapUsageEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';

import * as api from './v1/usage_events_pb';
import * as prehogApi from './prehog/v1alpha/connect_pb';

import * as types from './types';

/**
* Maps a plain JS object into a gRPC request object.
*/
export function mapUsageEvent(event: types.ReportUsageEventRequest) {
return new api.ReportUsageEventRequest()
.setAuthClusterId(event.authClusterId)
.setPrehogReq(mapPrehogBody(event.prehogReq));
}

function mapPrehogBody(
plainReq: types.ReportUsageEventRequest['prehogReq']
): prehogApi.SubmitConnectEventRequest {
const req = new prehogApi.SubmitConnectEventRequest()
.setTimestamp(Timestamp.fromDate(plainReq.timestamp))
.setDistinctId(plainReq.distinctId);

// Non-anonymized events.
if (plainReq.userJobRoleUpdate) {
const event = plainReq.userJobRoleUpdate;
const reqEvent = new prehogApi.ConnectUserJobRoleUpdateEvent().setJobRole(
event.jobRole
);

return req.setUserJobRoleUpdate(reqEvent);
}

// Anonymized events.
if (plainReq.clusterLogin) {
const event = plainReq.clusterLogin;
const reqEvent = new prehogApi.ConnectClusterLoginEvent()
.setClusterName(event.clusterName)
.setUserName(event.userName)
.setConnectorType(event.connectorType)
.setOs(event.os)
.setArch(event.arch)
.setOsVersion(event.osVersion)
.setAppVersion(event.appVersion);

return req.setClusterLogin(reqEvent);
}
if (plainReq.protocolUse) {
const event = plainReq.protocolUse;
const reqEvent = new prehogApi.ConnectProtocolUseEvent()
.setClusterName(event.clusterName)
.setUserName(event.userName)
.setProtocol(event.protocol);

return req.setProtocolUse(reqEvent);
}
if (plainReq.accessRequestCreate) {
const event = plainReq.accessRequestCreate;
const reqEvent = new prehogApi.ConnectAccessRequestCreateEvent()
.setClusterName(event.clusterName)
.setUserName(event.userName)
.setKind(event.kind);

return req.setAccessRequestCreate(reqEvent);
}
if (plainReq.accessRequestReview) {
const event = plainReq.accessRequestReview;
const reqEvent = new prehogApi.ConnectAccessRequestReviewEvent()
.setClusterName(event.clusterName)
.setUserName(event.userName);

return req.setAccessRequestReview(reqEvent);
}
if (plainReq.accessRequestAssumeRole) {
const event = plainReq.accessRequestAssumeRole;
const reqEvent = new prehogApi.ConnectAccessRequestAssumeRoleEvent()
.setClusterName(event.clusterName)
.setUserName(event.userName);

return req.setAccessRequestAssumeRole(reqEvent);
}
if (plainReq.fileTransferRun) {
const event = plainReq.fileTransferRun;
const reqEvent = new prehogApi.ConnectFileTransferRunEvent()
.setClusterName(event.clusterName)
.setUserName(event.userName)
.setIsUpload(event.isUpload);

return req.setFileTransferRun(reqEvent);
}

throw new Error(`Unrecognized event: ${JSON.stringify(plainReq)}`);
}

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

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

Loading