Skip to content

Commit 0fc828d

Browse files
committed
NXT-4374: setup analytics service
NXT-4374 (Instrumentation abstraction in modern UI)
1 parent 50b8afd commit 0fc828d

File tree

14 files changed

+206
-29
lines changed

14 files changed

+206
-29
lines changed

org.knime.ui.js/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"@fontsource/roboto-condensed": "5.x",
4141
"@fontsource/roboto-mono": "5.x",
4242
"@knime/components": "1.45.0",
43-
"@knime/hub-features": "^1.17.0",
43+
"@knime/hub-features": "^1.18.1",
4444
"@knime/kds-components": "^0.6.1",
4545
"@knime/kds-styles": "^0.6.1",
4646
"@knime/knime-ui-table": "0.6.0",

org.knime.ui.js/pnpm-lock.yaml

Lines changed: 17 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { embeddingSDK } from "@knime/hub-features";
2+
3+
import { canvasRendererUtils } from "@/components/workflowEditor/util/canvasRenderer";
4+
5+
import type { AnalyticsService, TrackFn } from "./types";
6+
7+
const noop = (...args: any[]) => {
8+
if (import.meta.env.DEV) {
9+
consola.trace("Analytics::DEV", ...args);
10+
}
11+
};
12+
13+
const noopService: AnalyticsService = { track: noop };
14+
15+
let __analyticsService: AnalyticsService = noopService;
16+
17+
const track: TrackFn = (eventCategory, eventData) => {
18+
if (canvasRendererUtils.isSVGRenderer()) {
19+
return;
20+
}
21+
22+
const { via, ...otherData } = eventData;
23+
24+
embeddingSDK.guest.dispatchGenericEventToHost({
25+
kind: "analytics",
26+
payload: {
27+
category: eventCategory,
28+
name: via,
29+
data: otherData,
30+
},
31+
});
32+
};
33+
34+
export const setupAnalyticsService = () => {
35+
__analyticsService = { track };
36+
};
37+
38+
export const useAnalyticsService = () => ({ track: __analyticsService.track });
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./analytics-service";
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export type AnalyticEvents = {
2+
node_created: {
3+
via:
4+
| "noderepo_dragdrop_"
5+
| "noderepo_doubleclick_"
6+
| "explorer_dragdrop_"
7+
| "quickactionmenu_click_";
8+
nodeId: string;
9+
nodeType: string;
10+
nodeFactoryId: string;
11+
};
12+
13+
quickactionmenu_opened: {
14+
via:
15+
| "port_dragdrop_fwd"
16+
| "port_dragdrop_bwd"
17+
| "keyboard_shortcut_"
18+
| "canvas_doubleclick_"
19+
| "canvas_ctxmenu_quickaddnode";
20+
nodeId?: string;
21+
nodeType?: string;
22+
nodePortIndex?: number;
23+
connectionType?: string;
24+
};
25+
};
26+
27+
export type AnalyticEventNames = keyof AnalyticEvents;
28+
29+
export type TrackFn = <K extends AnalyticEventNames>(
30+
type: K,
31+
payload: AnalyticEvents[K],
32+
) => void;
33+
34+
export interface AnalyticsService {
35+
track: TrackFn;
36+
}

org.knime.ui.js/src/components/nodeSearch/quickAdd/QuickAddNodeMenu.vue

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { storeToRefs } from "pinia";
44
55
import { SearchInput } from "@knime/components";
66
7+
import { useAnalyticsService } from "@/analytics";
78
import type { AvailablePortTypes, NodeRelation } from "@/api/custom-types";
89
import {
910
AddNodeCommand,
@@ -129,7 +130,7 @@ const addNode = async (nodeTemplate: NodeTemplateWithExtendedPorts) => {
129130
130131
// add node
131132
const { x, y } = canvasPosition.value;
132-
await nodeInteractionsStore.addNativeNode({
133+
const { newNodeId } = await nodeInteractionsStore.addNativeNode({
133134
position: {
134135
x: x - offsetX,
135136
y: y - offsetY,
@@ -143,6 +144,17 @@ const addNode = async (nodeTemplate: NodeTemplateWithExtendedPorts) => {
143144
});
144145
145146
props.quickActionContext.closeMenu();
147+
148+
const node = useNodeInteractionsStore().getNodeById(newNodeId ?? "");
149+
150+
if (node) {
151+
useAnalyticsService().track("node_created", {
152+
via: "quickactionmenu_click_",
153+
nodeId: node.id,
154+
nodeType: node.kind,
155+
nodeFactoryId: nodeFactory.className,
156+
});
157+
}
146158
};
147159
148160
const searchEnterKey = () => {

org.knime.ui.js/src/components/nodeTemplates/NodeTemplate/DraggableNodeTemplate.vue

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
import { ref, useTemplateRef } from "vue";
33
import { storeToRefs } from "pinia";
44
5+
import { useAnalyticsService } from "@/analytics";
56
import { usePanelStore } from "@/store/panel";
67
import type { NodeRepositoryDisplayModesType } from "@/store/settings";
8+
import { useNodeInteractionsStore } from "@/store/workflow/nodeInteractions";
79
import type {
810
ComponentNodeTemplateWithExtendedPorts,
911
NodeTemplateWithExtendedPorts,
@@ -95,11 +97,25 @@ const onDragEnd = (event: DragEvent) => {
9597
}
9698
};
9799
98-
const autoAddNodeFromTemplate = (
100+
const autoAddNodeFromTemplate = async (
99101
nodeTemplate: NodeTemplateWithExtendedPorts,
100102
) => {
101103
if (nodeTemplate.nodeFactory) {
102-
addNodeWithAutoPositioning(nodeTemplate.nodeFactory);
104+
const { newNodeId } = await addNodeWithAutoPositioning(
105+
nodeTemplate.nodeFactory,
106+
);
107+
108+
const node = useNodeInteractionsStore().getNodeById(newNodeId ?? "");
109+
110+
if (node) {
111+
useAnalyticsService().track("node_created", {
112+
via: "noderepo_doubleclick_",
113+
nodeId: node.id,
114+
nodeType: node.kind,
115+
nodeFactoryId: nodeTemplate.nodeFactory.className,
116+
});
117+
}
118+
103119
return;
104120
}
105121

org.knime.ui.js/src/components/nodeTemplates/useDragNodeIntoCanvas.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { storeToRefs } from "pinia";
22

3+
import { useAnalyticsService } from "@/analytics";
34
import type { NodeFactoryKey, XY } from "@/api/gateway-api/generated-api";
45
import { useNodeReplacementOrInsertion } from "@/components/workflowEditor/WebGLKanvas/common/useNodeReplacementOrInsertion";
56
import { useDragNearEdgePanning } from "@/components/workflowEditor/WebGLKanvas/kanvas/useDragNearEdgePanning";
@@ -215,12 +216,26 @@ export const useDragNodeIntoCanvas = () => {
215216
return;
216217
}
217218

218-
const addNodeAction = () => {
219+
const addNodeAction = async () => {
219220
if (eventData.type === "node") {
220-
return nodeInteractionsStore.addNativeNode({
221+
const res = await nodeInteractionsStore.addNativeNode({
221222
position: dropPosition,
222223
nodeFactory: eventData.payload.nodeFactory,
223224
});
225+
226+
const node = nodeInteractionsStore.getNodeById(res.newNodeId ?? "");
227+
228+
if (node && res.newNodeId) {
229+
const { className } = nodeInteractionsStore.getNodeFactory(node.id);
230+
useAnalyticsService().track("node_created", {
231+
via: "noderepo_dragdrop_",
232+
nodeId: node.id,
233+
nodeType: node.kind,
234+
nodeFactoryId: className,
235+
});
236+
}
237+
238+
return res;
224239
}
225240

226241
return nodeInteractionsStore.addComponentNode({

org.knime.ui.js/src/components/spaces/useCustomDragPreview.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { useRoute } from "vue-router";
55

66
import type { FileExplorerItem } from "@knime/components";
77

8-
import { SpaceItem } from "@/api/gateway-api/generated-api";
8+
import { useAnalyticsService } from "@/analytics";
9+
import { Node, SpaceItem } from "@/api/gateway-api/generated-api";
910
import { APP_ROUTES } from "@/router/appRoutes";
1011
import { useApplicationStore } from "@/store/application/application";
1112
import { useCurrentCanvasStore } from "@/store/canvas/useCurrentCanvasStore";
@@ -163,7 +164,7 @@ export const useCustomDragPreview = (options: UseCustomDragPreviewOptions) => {
163164
]);
164165
const position = { x, y };
165166

166-
const addNode = () => {
167+
const addNode = async () => {
167168
const spaceItemReference = {
168169
providerId: activeSpacePath.value.spaceProviderId,
169170
spaceId: activeSpacePath.value.spaceId,
@@ -177,11 +178,24 @@ export const useCustomDragPreview = (options: UseCustomDragPreviewOptions) => {
177178
componentName: sourceItem.name,
178179
});
179180
} else {
180-
return nodeInteractionStore.addNativeNode({
181+
const { newNodeId } = await nodeInteractionStore.addNativeNode({
181182
position,
182183
spaceItemReference,
183184
nodeFactory: { className: nodeTemplateId },
184185
});
186+
187+
const node = nodeInteractionStore.getNodeById(newNodeId ?? "");
188+
189+
if (node) {
190+
useAnalyticsService().track("node_created", {
191+
via: "explorer_dragdrop_",
192+
nodeId: node.id,
193+
nodeFactoryId: nodeTemplateId,
194+
nodeType: Node.KindEnum.Node,
195+
});
196+
}
197+
198+
return { newNodeId };
185199
}
186200
};
187201

org.knime.ui.js/src/components/workflowEditor/WebGLKanvas/WorkflowCanvas.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { storeToRefs } from "pinia";
1111
1212
import { sleep } from "@knime/utils";
1313
14+
import { useAnalyticsService } from "@/analytics";
1415
import { useDragNodeIntoCanvas } from "@/components/nodeTemplates";
1516
import { useAiQuickActionsStore } from "@/store/ai/aiQuickActions";
1617
import { QuickActionId } from "@/store/ai/types";
@@ -69,6 +70,10 @@ const openQuickActionMenu = (event: PointerEvent) => {
6970
useCanvasAnchoredComponentsStore().openQuickActionMenu({
7071
props: { position: { x, y } },
7172
});
73+
74+
useAnalyticsService().track("quickactionmenu_opened", {
75+
via: "canvas_doubleclick_",
76+
});
7277
};
7378
7479
const { isPointerDownDoubleClick } = usePointerDownDoubleClick({

0 commit comments

Comments
 (0)