mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Move tracker to telemetry extension (#1092)
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
1 parent
a478143423
commit
c566c85351
27 files changed
+472
-117
No files matched your search
@@ -0,0 +1,15 @@
|
||||
import { appEventBus, AppEvent } from "../event-bus"
|
||||
|
||||
describe("event bus tests", () => {
|
||||
describe("emit", () => {
|
||||
it("emits an event", () => {
|
||||
let event: AppEvent = null
|
||||
appEventBus.addListener((data) => {
|
||||
event = data
|
||||
})
|
||||
|
||||
appEventBus.emit({name: "foo", action: "bar"})
|
||||
expect(event.name).toBe("foo")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createIpcChannel } from "./ipc";
|
||||
import { ClusterId, clusterStore } from "./cluster-store";
|
||||
import { extensionLoader } from "../extensions/extension-loader"
|
||||
import { tracker } from "./tracker";
|
||||
import { appEventBus } from "./event-bus"
|
||||
|
||||
export const clusterIpc = {
|
||||
activate: createIpcChannel({
|
||||
@@ -37,7 +37,7 @@ export const clusterIpc = {
|
||||
disconnect: createIpcChannel({
|
||||
channel: "cluster:disconnect",
|
||||
handle: (clusterId: ClusterId) => {
|
||||
tracker.event("cluster", "stop");
|
||||
appEventBus.emit({name: "cluster", action: "stop"});
|
||||
return clusterStore.getById(clusterId)?.disconnect();
|
||||
},
|
||||
}),
|
||||
@@ -45,7 +45,7 @@ export const clusterIpc = {
|
||||
installFeature: createIpcChannel({
|
||||
channel: "cluster:install-feature",
|
||||
handle: async (clusterId: ClusterId, feature: string, config?: any) => {
|
||||
tracker.event("cluster", "install", feature);
|
||||
appEventBus.emit({name: "cluster", action: "install", params: { feature: feature}})
|
||||
const cluster = clusterStore.getById(clusterId);
|
||||
if (cluster) {
|
||||
await cluster.installFeature(feature, config)
|
||||
@@ -58,7 +58,7 @@ export const clusterIpc = {
|
||||
uninstallFeature: createIpcChannel({
|
||||
channel: "cluster:uninstall-feature",
|
||||
handle: (clusterId: ClusterId, feature: string) => {
|
||||
tracker.event("cluster", "uninstall", feature);
|
||||
appEventBus.emit({name: "cluster", action: "uninstall", params: { feature: feature}})
|
||||
return clusterStore.getById(clusterId)?.uninstallFeature(feature)
|
||||
}
|
||||
}),
|
||||
@@ -66,7 +66,7 @@ export const clusterIpc = {
|
||||
upgradeFeature: createIpcChannel({
|
||||
channel: "cluster:upgrade-feature",
|
||||
handle: (clusterId: ClusterId, feature: string, config?: any) => {
|
||||
tracker.event("cluster", "upgrade", feature);
|
||||
appEventBus.emit({name: "cluster", action: "upgrade", params: { feature: feature}})
|
||||
return clusterStore.getById(clusterId)?.upgradeFeature(feature, config)
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -7,7 +7,7 @@ import { BaseStore } from "./base-store";
|
||||
import { Cluster, ClusterState } from "../main/cluster";
|
||||
import migrations from "../migrations/cluster-store"
|
||||
import logger from "../main/logger";
|
||||
import { tracker } from "./tracker";
|
||||
import { appEventBus } from "./event-bus"
|
||||
import { dumpConfigYaml } from "./kube-helpers";
|
||||
import { saveToAppFiles } from "./utils/saveToAppFiles";
|
||||
import { KubeConfig } from "@kubernetes/client-node";
|
||||
@@ -142,7 +142,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
@action
|
||||
addCluster(...models: ClusterModel[]) {
|
||||
models.forEach(model => {
|
||||
tracker.event("cluster", "add");
|
||||
appEventBus.emit({name: "cluster", action: "add"})
|
||||
const cluster = new Cluster(model);
|
||||
this.clusters.set(model.id, cluster);
|
||||
})
|
||||
@@ -150,7 +150,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
|
||||
@action
|
||||
async removeById(clusterId: ClusterId) {
|
||||
tracker.event("cluster", "remove");
|
||||
appEventBus.emit({name: "cluster", action: "remove"})
|
||||
const cluster = this.getById(clusterId);
|
||||
if (cluster) {
|
||||
this.clusters.delete(clusterId);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { EventEmitter } from "./event-emitter"
|
||||
|
||||
export type AppEvent = {
|
||||
name: string;
|
||||
action: string;
|
||||
params?: object;
|
||||
}
|
||||
|
||||
export const appEventBus = new EventEmitter<[AppEvent]>()
|
||||
File renamed without changes.
@@ -1,49 +0,0 @@
|
||||
import { app, App, remote } from "electron"
|
||||
import ua from "universal-analytics"
|
||||
import { machineIdSync } from "node-machine-id"
|
||||
import Singleton from "./utils/singleton";
|
||||
import { userStore } from "./user-store"
|
||||
import logger from "../main/logger";
|
||||
|
||||
export class Tracker extends Singleton {
|
||||
static readonly GA_ID = "UA-159377374-1"
|
||||
|
||||
protected visitor: ua.Visitor
|
||||
protected machineId: string = null;
|
||||
protected ip: string = null;
|
||||
protected appVersion: string;
|
||||
protected locale: string;
|
||||
protected electronUA: string;
|
||||
|
||||
private constructor(app: App) {
|
||||
super();
|
||||
try {
|
||||
this.visitor = ua(Tracker.GA_ID, machineIdSync(), { strictCidFormat: false })
|
||||
} catch (error) {
|
||||
this.visitor = ua(Tracker.GA_ID)
|
||||
}
|
||||
this.visitor.set("dl", "https://telemetry.k8slens.dev")
|
||||
}
|
||||
|
||||
protected async isTelemetryAllowed(): Promise<boolean> {
|
||||
return userStore.preferences.allowTelemetry;
|
||||
}
|
||||
|
||||
async event(eventCategory: string, eventAction: string, otherParams = {}) {
|
||||
try {
|
||||
const allowed = await this.isTelemetryAllowed();
|
||||
if (!allowed) {
|
||||
return;
|
||||
}
|
||||
this.visitor.event({
|
||||
ec: eventCategory,
|
||||
ea: eventAction,
|
||||
...otherParams,
|
||||
}).send()
|
||||
} catch (err) {
|
||||
logger.error(`Failed to track "${eventCategory}:${eventAction}"`, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const tracker = Tracker.getInstance<Tracker>(app || remote.app);
|
||||
@@ -7,7 +7,7 @@ import { BaseStore } from "./base-store";
|
||||
import migrations from "../migrations/user-store"
|
||||
import { getAppVersion } from "./utils/app-version";
|
||||
import { kubeConfigDefaultPath, loadConfig } from "./kube-helpers";
|
||||
import { tracker } from "./tracker";
|
||||
import { appEventBus } from "./event-bus"
|
||||
import logger from "../main/logger";
|
||||
import path from 'path';
|
||||
|
||||
@@ -40,7 +40,7 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
|
||||
// track telemetry availability
|
||||
reaction(() => this.preferences.allowTelemetry, allowed => {
|
||||
tracker.event("telemetry", allowed ? "enabled" : "disabled");
|
||||
appEventBus.emit({name: "telemetry", action: allowed ? "enabled" : "disabled"})
|
||||
});
|
||||
|
||||
// refresh new contexts
|
||||
@@ -77,7 +77,7 @@ export class UserStore extends BaseStore<UserStoreModel> {
|
||||
|
||||
@action
|
||||
saveLastSeenAppVersion() {
|
||||
tracker.event("app", "whats-new-seen")
|
||||
appEventBus.emit({name: "app", action: "whats-new-seen"})
|
||||
this.lastSeenAppVersion = getAppVersion();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,3 +4,6 @@ export type { LensExtensionRuntimeEnv } from "./lens-runtime";
|
||||
// APIs
|
||||
export * from "./lens-main-extension"
|
||||
export { BaseStore } from "../common/base-store"
|
||||
export { appEventBus } from "../common/event-bus"
|
||||
export type { AppEvent } from "../common/event-bus"
|
||||
export { Singleton } from "../common/utils"
|
||||
@@ -6,6 +6,9 @@ export * from "./lens-extension"
|
||||
export * from "./lens-renderer-extension"
|
||||
export { DynamicPageType, PageRegistry } from "./page-registry"
|
||||
export { AppPreferenceRegistry } from "./app-preference-registry"
|
||||
export { appEventBus } from "../common/event-bus"
|
||||
export type { AppEvent } from "../common/event-bus"
|
||||
export { Singleton } from "../common/utils"
|
||||
|
||||
// TODO: add more common re-usable UI components + refactor interfaces (Props -> ComponentProps)
|
||||
export * from "../renderer/components/icon"
|
||||
|
||||
+5
-2
@@ -16,7 +16,7 @@ import { registerFileProtocol } from "../common/register-protocol";
|
||||
import { clusterStore } from "../common/cluster-store"
|
||||
import { userStore } from "../common/user-store";
|
||||
import { workspaceStore } from "../common/workspace-store";
|
||||
import { tracker } from "../common/tracker";
|
||||
import { appEventBus } from "../common/event-bus"
|
||||
import * as LensExtensions from "../extensions/extension-api";
|
||||
import { extensionManager } from "../extensions/extension-manager";
|
||||
import { extensionLoader } from "../extensions/extension-loader";
|
||||
@@ -48,7 +48,6 @@ async function main() {
|
||||
await shellSync();
|
||||
logger.info(`🚀 Starting Lens from "${workingDir}"`)
|
||||
|
||||
tracker.event("app", "start");
|
||||
const updater = new AppUpdater()
|
||||
updater.start();
|
||||
|
||||
@@ -89,6 +88,10 @@ async function main() {
|
||||
extensionLoader.loadOnMain(getLensRuntime)
|
||||
extensionLoader.extensions.replace(await extensionManager.load())
|
||||
extensionLoader.broadcastExtensions()
|
||||
|
||||
setTimeout(() => {
|
||||
appEventBus.emit({name: "app", action: "start"})
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
app.on("ready", main);
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as k8s from "@kubernetes/client-node"
|
||||
import { KubeConfig } from "@kubernetes/client-node"
|
||||
import { Cluster } from "./cluster"
|
||||
import logger from "./logger";
|
||||
import { tracker } from "../common/tracker";
|
||||
import { appEventBus } from "../common/event-bus"
|
||||
|
||||
export class NodeShellSession extends ShellSession {
|
||||
protected nodeName: string;
|
||||
@@ -44,7 +44,7 @@ export class NodeShellSession extends ShellSession {
|
||||
this.closeWebsocketOnProcessExit()
|
||||
this.exitProcessOnWebsocketClose()
|
||||
|
||||
tracker.event("node-shell", "open")
|
||||
appEventBus.emit({name: "node-shell", action: "open"})
|
||||
}
|
||||
|
||||
protected exit(code = 1000) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as yaml from "js-yaml";
|
||||
import path from "path";
|
||||
import * as tempy from "tempy";
|
||||
import logger from "./logger"
|
||||
import { tracker } from "../common/tracker";
|
||||
import { appEventBus } from "../common/event-bus"
|
||||
import { cloneJsonObject } from "../common/utils";
|
||||
|
||||
export class ResourceApplier {
|
||||
@@ -15,7 +15,7 @@ export class ResourceApplier {
|
||||
|
||||
async apply(resource: KubernetesObject | any): Promise<string> {
|
||||
resource = this.sanitizeObject(resource);
|
||||
tracker.event("resource", "apply")
|
||||
appEventBus.emit({name: "resource", action: "apply"})
|
||||
return await this.kubectlApply(yaml.safeDump(resource));
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Cluster } from "./cluster"
|
||||
import { ClusterPreferences } from "../common/cluster-store";
|
||||
import { helmCli } from "./helm/helm-cli"
|
||||
import { isWindows } from "../common/vars";
|
||||
import { tracker } from "../common/tracker";
|
||||
import { appEventBus } from "../common/event-bus"
|
||||
import { userStore } from "../common/user-store";
|
||||
|
||||
export class ShellSession extends EventEmitter {
|
||||
@@ -58,7 +58,7 @@ export class ShellSession extends EventEmitter {
|
||||
this.closeWebsocketOnProcessExit()
|
||||
this.exitProcessOnWebsocketClose()
|
||||
|
||||
tracker.event("shell", "open")
|
||||
appEventBus.emit({name: "shell", action: "open"})
|
||||
}
|
||||
|
||||
protected cwd(): string {
|
||||
|
||||
@@ -5,6 +5,7 @@ import windowStateKeeper from "electron-window-state"
|
||||
import { observable } from "mobx";
|
||||
import { initMenu } from "./menu";
|
||||
import { extensionLoader } from "../extensions/extension-loader";
|
||||
import { appEventBus } from "../common/event-bus"
|
||||
|
||||
export class WindowManager {
|
||||
protected mainView: BrowserWindow;
|
||||
@@ -44,6 +45,12 @@ export class WindowManager {
|
||||
this.mainView.webContents.on("dom-ready", () => {
|
||||
extensionLoader.broadcastExtensions()
|
||||
})
|
||||
this.mainView.on("focus", () => {
|
||||
appEventBus.emit({name: "app", action: "focus"})
|
||||
})
|
||||
this.mainView.on("blur", () => {
|
||||
appEventBus.emit({name: "app", action: "blur"})
|
||||
})
|
||||
|
||||
// track visible cluster from ui
|
||||
ipcMain.on("cluster-view:current-id", (event, clusterId: ClusterId) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Base http-service / json-api class
|
||||
|
||||
import { stringify } from "querystring";
|
||||
import { EventEmitter } from "../utils/eventEmitter";
|
||||
import { EventEmitter } from "../../common/event-emitter";
|
||||
import { cancelableFetch } from "../utils/cancelableFetch";
|
||||
|
||||
export interface JsonApiData {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { observable } from "mobx";
|
||||
import { EventEmitter } from "../utils/eventEmitter";
|
||||
import { EventEmitter } from "../../common/event-emitter";
|
||||
|
||||
interface IParams {
|
||||
url?: string; // connection url, starts with ws:// or wss://
|
||||
|
||||
@@ -39,6 +39,7 @@ import { pageRegistry } from "../../extensions/page-registry";
|
||||
import { DynamicPage } from "../../extensions/dynamic-page";
|
||||
import { extensionLoader } from "../../extensions/extension-loader";
|
||||
import { getLensRuntime } from "../../extensions/lens-runtime";
|
||||
import { appEventBus } from "../../common/event-bus"
|
||||
|
||||
@observer
|
||||
export class App extends React.Component {
|
||||
@@ -51,6 +52,9 @@ export class App extends React.Component {
|
||||
await clusterIpc.setFrameId.invokeFromRenderer(clusterId, frameId);
|
||||
await getHostedCluster().whenReady; // cluster.activate() is done at this point
|
||||
extensionLoader.loadOnClusterRenderer(getLensRuntime)
|
||||
appEventBus.emit({name: "cluster", action: "open", params: {
|
||||
clusterId: clusterId
|
||||
}})
|
||||
}
|
||||
|
||||
get startURL() {
|
||||
|
||||
@@ -7,7 +7,7 @@ export * from "../../common/utils"
|
||||
|
||||
export * from "./cssVar"
|
||||
export * from "./cssNames"
|
||||
export * from "./eventEmitter"
|
||||
export * from "../../common/event-emitter"
|
||||
export * from "./downloadFile"
|
||||
export * from "./prevDefault"
|
||||
export * from "./createStorage"
|
||||
|
||||
Reference in new issue
Block a user