diff --git a/packages/core/src/features/telemetry/emit-telemetry-from-specific-function-calls.test.ts b/packages/core/src/features/telemetry/emit-telemetry-from-specific-function-calls.test.ts index cff5b183a8..ac57a7aa1e 100644 --- a/packages/core/src/features/telemetry/emit-telemetry-from-specific-function-calls.test.ts +++ b/packages/core/src/features/telemetry/emit-telemetry-from-specific-function-calls.test.ts @@ -22,6 +22,11 @@ describe("emit-telemetry-from-specific-function-calls", () => { beforeEach(() => { di.override(telemetryWhiteListForFunctionsInjectable, () => [ "some-white-listed-function", + + { + id: "some-white-listed-function-with-white-listed-argument", + getParams: (irrelevantArg, arg) => ({ someParam: arg }), + }, ]); emitEventMock = jest.fn(); @@ -32,6 +37,7 @@ describe("emit-telemetry-from-specific-function-calls", () => { let whiteListedFunctionMock: jest.Mock; let nonWhiteListedFunctionMock: jest.Mock; let injectedWhiteListedFunction: jest.Mock; + let injectedWhiteListedFunctionWithArgument: jest.Mock; let injectedNonWhiteListedFunction: jest.Mock; beforeEach(() => { @@ -43,16 +49,30 @@ describe("emit-telemetry-from-specific-function-calls", () => { instantiate: () => whiteListedFunctionMock, }); + const whiteListedInjectableWithArgument = getInjectable({ + id: "some-white-listed-function-with-white-listed-argument", + instantiate: () => whiteListedFunctionMock, + }); + const nonWhiteListedInjectable = getInjectable({ id: "some-non-white-listed-function", instantiate: () => nonWhiteListedFunctionMock, }); runInAction(() => { - di.register(whiteListedInjectable, nonWhiteListedInjectable); + di.register( + whiteListedInjectable, + whiteListedInjectableWithArgument, + nonWhiteListedInjectable + ); }); injectedWhiteListedFunction = di.inject(whiteListedInjectable); + + injectedWhiteListedFunctionWithArgument = di.inject( + whiteListedInjectableWithArgument + ); + injectedNonWhiteListedFunction = di.inject(nonWhiteListedInjectable); }); @@ -60,22 +80,51 @@ describe("emit-telemetry-from-specific-function-calls", () => { expect(emitEventMock).not.toHaveBeenCalled(); }); - describe("when the white-listed function is called with parameters", () => { + describe("when a normal white-listed function is called with arguments", () => { beforeEach(() => { injectedWhiteListedFunction("some-arg", "some-other-arg"); }); - it("telemetry is emitted in event bus", () => { + it("telemetry is emitted in event bus without the arguments", () => { expect(emitEventMock).toHaveBeenCalledWith({ destination: "auto-capture", action: "telemetry-from-business-action", name: "some-white-listed-function", - params: { args: ["some-arg", "some-other-arg"] }, }); }); }); - describe("when the white-listed function is called with MobX reactive content", () => { + describe("when a white-listed function with a white-listed argument is called with arguments", () => { + beforeEach(() => { + injectedWhiteListedFunctionWithArgument("some-arg", "some-other-arg"); + }); + + it("telemetry is emitted in event bus with the arguments as params", () => { + expect(emitEventMock).toHaveBeenCalledWith({ + action: "telemetry-from-business-action", + destination: "auto-capture", + name: "some-white-listed-function-with-white-listed-argument", + params: { someParam: "some-other-arg" }, + }); + }); + }); + + describe("when a white-listed function with a white-listed argument is called without arguments", () => { + beforeEach(() => { + injectedWhiteListedFunctionWithArgument(); + }); + + it("telemetry is emitted in event bus without params", () => { + expect(emitEventMock).toHaveBeenCalledWith({ + action: "telemetry-from-business-action", + destination: "auto-capture", + name: "some-white-listed-function-with-white-listed-argument", + params: { someParam: undefined }, + }); + }); + }); + + describe("when the white-listed function with a white-listed argument is called with MobX reactive content", () => { beforeEach(() => { const someComputedProperty = computed(() => "some-computed-value"); @@ -84,22 +133,23 @@ describe("emit-telemetry-from-specific-function-calls", () => { someComputedProperty, }; - injectedWhiteListedFunction(someObservable); + injectedWhiteListedFunctionWithArgument( + "irrelevant-argument", + someObservable + ); }); it("telemetry is emitted in event bus without MobX internals or computeds", () => { expect(emitEventMock).toHaveBeenCalledWith({ destination: "auto-capture", action: "telemetry-from-business-action", - name: "some-white-listed-function", + name: "some-white-listed-function-with-white-listed-argument", params: { - args: [ - { - someStaticProperty: "some-static-value", - someComputedProperty: "some-computed-value", - }, - ], + someParam: { + someStaticProperty: "some-static-value", + someComputedProperty: "some-computed-value", + }, }, }); }); diff --git a/packages/core/src/features/telemetry/renderer/emit-telemetry.injectable.ts b/packages/core/src/features/telemetry/renderer/emit-telemetry.injectable.ts index f543daf843..5fbc2f4b38 100644 --- a/packages/core/src/features/telemetry/renderer/emit-telemetry.injectable.ts +++ b/packages/core/src/features/telemetry/renderer/emit-telemetry.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import emitEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; -import { toJS, observable } from "mobx"; +import { observable, toJS } from "mobx"; const emitTelemetryInjectable = getInjectable({ id: "emit-telemetry", @@ -12,12 +12,12 @@ const emitTelemetryInjectable = getInjectable({ instantiate: (di) => { const emitEvent = di.inject(emitEventInjectable); - return ({ action, args }: { action: string; args: any[] }) => { + return ({ action, params }: { action: string; params?: object }) => { emitEvent({ destination: "auto-capture", action: "telemetry-from-business-action", name: action, - params: { args: toJS(observable(args)) }, + ...(params ? { params: toJS(observable(params)) } : {}), }); }; }, diff --git a/packages/core/src/features/telemetry/renderer/telemetry-decorator.injectable.ts b/packages/core/src/features/telemetry/renderer/telemetry-decorator.injectable.ts index 2c7e817918..ea6e4c2e5d 100644 --- a/packages/core/src/features/telemetry/renderer/telemetry-decorator.injectable.ts +++ b/packages/core/src/features/telemetry/renderer/telemetry-decorator.injectable.ts @@ -2,21 +2,21 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { - DiContainerForInjection, - Injectable, -} from "@ogre-tools/injectable"; +import type { DiContainerForInjection } from "@ogre-tools/injectable"; import { - lifecycleEnum, getInjectable, instantiationDecoratorToken, + lifecycleEnum, } from "@ogre-tools/injectable"; -import assert from "assert"; +import assert from "assert"; import { isFunction } from "lodash/fp"; import emitTelemetryInjectable from "./emit-telemetry.injectable"; -import telemetryWhiteListForFunctionsInjectable from "./telemetry-white-list-for-functions.injectable"; + +import telemetryWhiteListForFunctionsInjectable, { + WhiteListItem, +} from "./telemetry-white-list-for-functions.injectable"; const telemetryDecoratorInjectable = getInjectable({ id: "telemetry-decorator", @@ -25,33 +25,40 @@ const telemetryDecoratorInjectable = getInjectable({ const emitTelemetry = diForDecorator.inject(emitTelemetryInjectable); const whiteList = diForDecorator.inject( - telemetryWhiteListForFunctionsInjectable, + telemetryWhiteListForFunctionsInjectable ); - const shouldEmitTelemetry = shouldEmitTelemetryFor(whiteList); + const whitleListMap = getWhitleListMap(whiteList); return { decorate: (instantiateToBeDecorated: any) => - (di: DiContainerForInjection, instantiationParameter: any) => { - const instance = instantiateToBeDecorated(di, instantiationParameter); + (di: DiContainerForInjection, instantiationParameter: any) => { + const instance = instantiateToBeDecorated(di, instantiationParameter); - if (isFunction(instance)) { - return (...args: any[]) => { - const currentContext = di.context.at(-1); + if (isFunction(instance)) { + return (...args: any[]) => { + const currentContext = di.context.at(-1); - assert(currentContext); + assert(currentContext); - if (shouldEmitTelemetry(currentContext.injectable)) { - emitTelemetry({ action: currentContext.injectable.id, args }); - } + const whiteListed = whitleListMap.get( + currentContext.injectable.id + ); - return instance(...args); - }; - } + if (whiteListed) { + emitTelemetry({ + action: currentContext.injectable.id, + params: whiteListed.getParams(...args), + }); + } - return instance; - }, + return instance(...args); + }; + } + + return instance; + }, }; }, @@ -61,8 +68,23 @@ const telemetryDecoratorInjectable = getInjectable({ injectionToken: instantiationDecoratorToken, }); -const shouldEmitTelemetryFor = - (whiteList: string[]) => (injectable: Injectable) => - whiteList.includes(injectable.id); +const getWhitleListMap = (whiteList: WhiteListItem[]) => + new Map( + whiteList.map((item) => + typeof item === "string" + ? [ + item, + { + getParams: (...args: any[]) => undefined, + }, + ] + : [ + item.id, + { + getParams: item.getParams, + }, + ] + ) + ); export default telemetryDecoratorInjectable; diff --git a/packages/core/src/features/telemetry/renderer/telemetry-white-list-for-functions.injectable.ts b/packages/core/src/features/telemetry/renderer/telemetry-white-list-for-functions.injectable.ts index 38f0bb6ca6..0d2970f75e 100644 --- a/packages/core/src/features/telemetry/renderer/telemetry-white-list-for-functions.injectable.ts +++ b/packages/core/src/features/telemetry/renderer/telemetry-white-list-for-functions.injectable.ts @@ -3,6 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import type { AppEvent } from "../../../common/app-event-bus/event-bus"; const navigateTo = [ "navigate-to-preference-tab-id", @@ -88,21 +89,19 @@ const extensions = [ "uninstall-extension", ]; -const externalActions = [ - "open-link-in-browser", -]; +const externalActions = ["open-link-in-browser"]; -const uiInteraction = [ - "show-details", -]; +const uiInteraction = ["show-details"]; -const terminal = [ - "create-terminal-tab", -]; +const terminal = ["create-terminal-tab"]; + +export type WhiteListItem = + | string + | { id: string; getParams: (...args: unknown[]) => AppEvent["params"] }; const telemetryWhiteListForFunctionsInjectable = getInjectable({ id: "telemetry-white-list-for-functions", - instantiate: () => [ + instantiate: (): WhiteListItem[] => [ ...navigateTo, ...helmInjectableIds, ...kubeConfigActions,