Skip to content

Commit

Permalink
vscode: add TelemetryLogger support (eclipse-theia#12453)
Browse files Browse the repository at this point in the history
Closes: eclipse-theia#12232

The commit adds support for the `TelemetryLogger` VS Code API in addition to other related functionality.

Contributed on behalf of STMicroelectronics

Signed-off-by: Remi Schnekenburger <[email protected]>
  • Loading branch information
rschnekenbu authored and erezmus committed Sep 21, 2023
1 parent f57e94e commit 633db67
Show file tree
Hide file tree
Showing 16 changed files with 638 additions and 31 deletions.
1 change: 1 addition & 0 deletions packages/core/shared/reflect-metadata/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from 'reflect-metadata';
2 changes: 2 additions & 0 deletions packages/core/shared/reflect-metadata/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module.exports = require('reflect-metadata');

3 changes: 3 additions & 0 deletions packages/core/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export * from './contribution-filter';
export * from './nls';
export * from './numbers';
export * from './performance';
export * from './types';
export { default as URI } from './uri';
export * from './telemetry';

import { environment } from '@theia/application-package/lib/environment';
export { environment };
49 changes: 49 additions & 0 deletions packages/core/src/common/objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import { isObject, isUndefined } from './types';

export function deepClone<T>(obj: T): T {
if (!obj || typeof obj !== 'object') {
return obj;
Expand Down Expand Up @@ -69,3 +71,50 @@ export function notEmpty<T>(arg: T | undefined | null): arg is T {
export function isEmpty(arg: Object): boolean {
return Object.keys(arg).length === 0 && arg.constructor === Object;
}

// copied and modified from https://github.com/microsoft/vscode/blob/1.76.0/src/vs/base/common/objects.ts#L45-L83
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function cloneAndChange(obj: any, changer: (orig: any) => any, seen: Set<any>): any {
// impossible to clone an undefined or null object
// eslint-disable-next-line no-null/no-null
if (isUndefined(obj) || obj === null) {
return obj;
}

const changed = changer(obj);
if (!isUndefined(changed)) {
return changed;
}

if (Array.isArray(obj)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const r1: any[] = [];
for (const e of obj) {
r1.push(cloneAndChange(e, changer, seen));
}
return r1;
}

if (isObject(obj)) {
if (seen.has(obj)) {
throw new Error('Cannot clone recursive data-structure');
}
seen.add(obj);
const r2 = {};
for (const i2 in obj) {
if (_hasOwnProperty.call(obj, i2)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(r2 as any)[i2] = cloneAndChange(obj[i2], changer, seen);
}
}
seen.delete(obj);
return r2;
}

return obj;
}
45 changes: 45 additions & 0 deletions packages/core/src/common/telemetry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// *****************************************************************************
// Copyright (C) 2023 STMicroelectronics and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

export class TelemetryTrustedValue<T> {
readonly value: T;

constructor(value: T) {
this.value = value;
}
}

export interface TelemetryLogger {
readonly sender: TelemetrySender;
readonly options: TelemetryLoggerOptions | undefined;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
logUsage(eventName: string, data?: Record<string, any | TelemetryTrustedValue<any>>): void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
logError(eventNameOrException: string | Error, data?: Record<string, any | TelemetryTrustedValue<any>>): void;

dispose(): void;
}

interface TelemetrySender {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
sendEventData(eventName: string, data?: Record<string, any>): void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
sendErrorData(error: Error, data?: Record<string, any>): void;
flush?(): void | Thenable<void>;
}

interface TelemetryLoggerOptions {
}
11 changes: 11 additions & 0 deletions packages/core/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

type UnknownObject<T extends object> = Record<string | number | symbol, unknown> & { [K in keyof T]: unknown };

export type Mutable<T> = { -readonly [P in keyof T]: T[P] };
export type MaybeNull<T> = { [P in keyof T]: T[P] | null };
export type MaybeUndefined<T> = { [P in keyof T]: T[P] | undefined };
Expand Down Expand Up @@ -177,3 +179,12 @@ export namespace ArrayUtils {
export function unreachable(_never: never, message: string = 'unhandled case'): never {
throw new Error(message);
}

export function isUndefined(value: unknown): value is undefined {
return typeof value === 'undefined';
}

export function isObject<T extends object>(value: unknown): value is UnknownObject<T> {
// eslint-disable-next-line no-null/no-null
return typeof value === 'object' && value !== null;
}
2 changes: 1 addition & 1 deletion packages/monaco/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"idb": "^4.0.5",
"jsonc-parser": "^2.2.0",
"vscode-oniguruma": "1.6.1",
"vscode-textmate": "7.0.1"
"vscode-textmate": "7.0.4"
},
"publishConfig": {
"access": "public"
Expand Down
13 changes: 11 additions & 2 deletions packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1903,6 +1903,13 @@ export interface CommentsMain {
$onDidCommentThreadsChange(handle: number, event: CommentThreadChangedEvent): void;
}

export interface TelemetryMain {
}

export interface TelemetryExt {
}

// endregion
export const PLUGIN_RPC_CONTEXT = {
AUTHENTICATION_MAIN: <ProxyIdentifier<AuthenticationMain>>createProxyIdentifier<AuthenticationMain>('AuthenticationMain'),
COMMAND_REGISTRY_MAIN: <ProxyIdentifier<CommandRegistryMain>>createProxyIdentifier<CommandRegistryMain>('CommandRegistryMain'),
Expand Down Expand Up @@ -1937,7 +1944,8 @@ export const PLUGIN_RPC_CONTEXT = {
LABEL_SERVICE_MAIN: <ProxyIdentifier<LabelServiceMain>>createProxyIdentifier<LabelServiceMain>('LabelServiceMain'),
TIMELINE_MAIN: <ProxyIdentifier<TimelineMain>>createProxyIdentifier<TimelineMain>('TimelineMain'),
THEMING_MAIN: <ProxyIdentifier<ThemingMain>>createProxyIdentifier<ThemingMain>('ThemingMain'),
COMMENTS_MAIN: <ProxyIdentifier<CommentsMain>>createProxyIdentifier<CommentsMain>('CommentsMain')
COMMENTS_MAIN: <ProxyIdentifier<CommentsMain>>createProxyIdentifier<CommentsMain>('CommentsMain'),
TELEMETRY_MAIN: <ProxyIdentifier<TelemetryMain>>createProxyIdentifier<TelemetryMain>('TelemetryMain'),
};

export const MAIN_RPC_CONTEXT = {
Expand Down Expand Up @@ -1972,7 +1980,8 @@ export const MAIN_RPC_CONTEXT = {
LABEL_SERVICE_EXT: createProxyIdentifier<LabelServiceExt>('LabelServiceExt'),
TIMELINE_EXT: createProxyIdentifier<TimelineExt>('TimeLineExt'),
THEMING_EXT: createProxyIdentifier<ThemingExt>('ThemingExt'),
COMMENTS_EXT: createProxyIdentifier<CommentsExt>('CommentsExt')
COMMENTS_EXT: createProxyIdentifier<CommentsExt>('CommentsExt'),
TELEMETRY_EXT: createProxyIdentifier<TelemetryExt>('TelemetryExt)')
};

export interface TasksExt {
Expand Down
8 changes: 4 additions & 4 deletions packages/plugin-ext/src/hosted/browser/worker/worker-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import 'reflect-metadata';
import { Emitter } from '@theia/core/lib/common/event';
import { RPCProtocolImpl } from '../../../common/rpc-protocol';
import { PluginManagerExtImpl } from '../../../plugin/plugin-manager';
Expand Down Expand Up @@ -49,9 +49,9 @@ const rpc = new RPCProtocolImpl({
ctx.postMessage(m);
},
},
{
reviver: reviver
});
{
reviver: reviver
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
addEventListener('message', (message: any) => {
Expand Down
8 changes: 4 additions & 4 deletions packages/plugin-ext/src/hosted/node/plugin-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import '@theia/core/shared/reflect-metadata';
import { Emitter } from '@theia/core/lib/common/event';
import { RPCProtocolImpl, MessageType, ConnectionClosedError } from '../../common/rpc-protocol';
import { PluginHostRPC } from './plugin-host-rpc';
Expand Down Expand Up @@ -83,9 +83,9 @@ const rpc = new RPCProtocolImpl({
}
}
},
{
reviver: reviver
});
{
reviver: reviver
});

process.on('message', async (message: string) => {
if (terminating) {
Expand Down
13 changes: 0 additions & 13 deletions packages/plugin-ext/src/plugin/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import { Emitter, Event } from '@theia/core/lib/common/event';
import * as theia from '@theia/plugin';
import { RPCProtocol } from '../common/rpc-protocol';
import { EnvMain, PLUGIN_RPC_CONTEXT } from '../common/plugin-api-rpc';
Expand All @@ -31,16 +30,12 @@ export abstract class EnvExtImpl {
private envMachineId: string;
private envSessionId: string;
private host: string;
private _isTelemetryEnabled: boolean;
private _remoteName: string | undefined;
private onDidChangeTelemetryEnabledEmitter = new Emitter<boolean>();

constructor(rpc: RPCProtocol) {
this.proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.ENV_MAIN);
this.envSessionId = v4();
this.envMachineId = v4();
// we don't support telemetry at the moment
this._isTelemetryEnabled = false;
this._remoteName = undefined;
}

Expand Down Expand Up @@ -101,14 +96,6 @@ export abstract class EnvExtImpl {
return this.host;
}

get isTelemetryEnabled(): boolean {
return this._isTelemetryEnabled;
}

get onDidChangeTelemetryEnabled(): Event<boolean> {
return this.onDidChangeTelemetryEnabledEmitter.event;
}

get remoteName(): string | undefined {
return this._remoteName;
}
Expand Down
11 changes: 9 additions & 2 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ import {
InlayHint,
InlayHintKind,
InlayHintLabelPart,
TelemetryTrustedValue,
TestRunProfileKind,
TestTag,
TestRunRequest,
Expand Down Expand Up @@ -201,6 +202,7 @@ import { CustomEditorsExtImpl } from './custom-editors';
import { WebviewViewsExtImpl } from './webview-views';
import { PluginPackage } from '../common';
import { Endpoint } from '@theia/core/lib/browser/endpoint';
import { TelemetryExtImpl } from './telemetry-ext';

export function createAPIFactory(
rpc: RPCProtocol,
Expand Down Expand Up @@ -240,6 +242,7 @@ export function createAPIFactory(
const commentsExt = rpc.set(MAIN_RPC_CONTEXT.COMMENTS_EXT, new CommentsExtImpl(rpc, commandRegistry, documents));
const customEditorExt = rpc.set(MAIN_RPC_CONTEXT.CUSTOM_EDITORS_EXT, new CustomEditorsExtImpl(rpc, documents, webviewExt, workspaceExt));
const webviewViewsExt = rpc.set(MAIN_RPC_CONTEXT.WEBVIEW_VIEWS_EXT, new WebviewViewsExtImpl(rpc, webviewExt));
const telemetryExt = rpc.set(MAIN_RPC_CONTEXT.TELEMETRY_EXT, new TelemetryExtImpl());
rpc.set(MAIN_RPC_CONTEXT.DEBUG_EXT, debugExt);

return function (plugin: InternalPlugin): typeof theia {
Expand Down Expand Up @@ -634,9 +637,12 @@ export function createAPIFactory(
get appHost(): string { return envExt.appHost; },
get language(): string { return envExt.language; },
get isNewAppInstall(): boolean { return envExt.isNewAppInstall; },
get isTelemetryEnabled(): boolean { return envExt.isTelemetryEnabled; },
get isTelemetryEnabled(): boolean { return telemetryExt.isTelemetryEnabled; },
get onDidChangeTelemetryEnabled(): theia.Event<boolean> {
return envExt.onDidChangeTelemetryEnabled;
return telemetryExt.onDidChangeTelemetryEnabled;
},
createTelemetryLogger(sender: theia.TelemetrySender, options?: theia.TelemetryLoggerOptions): theia.TelemetryLogger {
return telemetryExt.createTelemetryLogger(sender, options);
},
get remoteName(): string | undefined { return envExt.remoteName; },
get machineId(): string { return envExt.machineId; },
Expand Down Expand Up @@ -1116,6 +1122,7 @@ export function createAPIFactory(
InlayHint,
InlayHintKind,
InlayHintLabelPart,
TelemetryTrustedValue,
TestRunProfileKind,
TestTag,
TestRunRequest,
Expand Down
Loading

0 comments on commit 633db67

Please sign in to comment.