Support telemetry page (#2756)

* support telemetry page events

* add log level to FE settings

* add debug logging

* fix types

* state fix

* move call
This commit is contained in:
Mutasem Aldmour 2022-02-04 00:24:01 +02:00 committed by GitHub
parent 0bf554394a
commit 7bdb7e2a25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 51 additions and 23 deletions

View file

@ -409,6 +409,7 @@ export interface IN8nUISettings {
telemetry: ITelemetrySettings;
personalizationSurvey: IPersonalizationSurvey;
defaultLocale: string;
logLevel: 'info' | 'debug' | 'warn' | 'error' | 'verbose';
}
export interface IPersonalizationSurveyAnswers {

View file

@ -288,6 +288,7 @@ class App {
shouldShow: false,
},
defaultLocale: config.get('defaultLocale'),
logLevel: config.get('logs.level'),
};
}

View file

@ -22,6 +22,9 @@ export default Vue.extend({
components: {
Telemetry,
},
mounted() {
this.$telemetry.page('Editor', this.$route.name);
},
watch: {
'$route'(route) {
this.$telemetry.page('Editor', route.name);

View file

@ -536,6 +536,7 @@ export interface IN8nUISettings {
personalizationSurvey?: IPersonalizationSurvey;
telemetry: ITelemetrySettings;
defaultLocale: string;
logLevel: ILogLevel;
}
export interface IWorkflowSettings extends IWorkflowSettingsWorkflow {
@ -680,7 +681,6 @@ export interface IRootState {
workflow: IWorkflowDb;
sidebarMenuItems: IMenuItem[];
instanceId: string;
telemetry: ITelemetrySettings | null;
}
export interface ICredentialTypeMap {
@ -718,6 +718,8 @@ export interface IUiState {
isPageLoading: boolean;
}
export type ILogLevel = 'info' | 'debug' | 'warn' | 'error' | 'verbose';
export interface ISettingsState {
settings: IN8nUISettings;
promptsData: IN8nPrompts;

View file

@ -10,12 +10,12 @@ import { mapGetters } from 'vuex';
export default Vue.extend({
name: 'Telemetry',
computed: {
...mapGetters(['telemetry']),
...mapGetters('settings', ['telemetry']),
},
watch: {
telemetry(opts) {
if (opts.enabled) {
this.$telemetry.init(opts, this.$store.getters.instanceId);
if (opts && opts.enabled) {
this.$telemetry.init(opts, this.$store.getters.instanceId, this.$store.getters['settings/logLevel']);
}
},
},

View file

@ -1,5 +1,6 @@
import { ActionContext, Module } from 'vuex';
import {
ILogLevel,
IN8nPrompts,
IN8nUISettings,
IN8nValueSurveyData,
@ -11,6 +12,7 @@ import { getPromptsData, getSettings, submitValueSurvey, submitPersonalizationSu
import Vue from 'vue';
import { getPersonalizedNodeTypes } from './helper';
import { CONTACT_PROMPT_MODAL_KEY, PERSONALIZATION_MODAL_KEY, VALUE_SURVEY_MODAL_KEY } from '@/constants';
import { ITelemetrySettings } from 'n8n-workflow';
const module: Module<ISettingsState, IRootState> = {
namespaced: true,
@ -30,6 +32,15 @@ const module: Module<ISettingsState, IRootState> = {
getPromptsData(state: ISettingsState) {
return state.promptsData;
},
telemetry: (state): ITelemetrySettings => {
return state.settings.telemetry;
},
logLevel: (state): ILogLevel => {
return state.settings.logLevel;
},
isTelemetryEnabled: (state) => {
return state.settings.telemetry && state.settings.telemetry.enabled;
},
},
mutations: {
setSettings(state: ISettingsState, settings: IN8nUISettings) {
@ -66,7 +77,6 @@ const module: Module<ISettingsState, IRootState> = {
context.commit('setN8nMetadata', settings.n8nMetadata || {}, {root: true});
context.commit('setDefaultLocale', settings.defaultLocale, {root: true});
context.commit('versions/setVersionNotificationSettings', settings.versionNotifications, {root: true});
context.commit('setTelemetry', settings.telemetry, {root: true});
const showPersonalizationsModal = settings.personalizationSurvey && settings.personalizationSurvey.shouldShow && !settings.personalizationSurvey.answers;
@ -81,7 +91,7 @@ const module: Module<ISettingsState, IRootState> = {
context.commit('setPersonalizationAnswers', results);
},
async fetchPromptsData(context: ActionContext<ISettingsState, IRootState>) {
if (!context.rootGetters.isTelemetryEnabled) {
if (!context.getters.isTelemetryEnabled) {
return;
}

View file

@ -3,7 +3,7 @@ import {
ITelemetrySettings,
IDataObject,
} from 'n8n-workflow';
import { INodeCreateElement } from "@/Interface";
import { ILogLevel, INodeCreateElement } from "@/Interface";
declare module 'vue/types/vue' {
interface Vue {
@ -35,6 +35,8 @@ interface IUserNodesPanelSession {
class Telemetry {
private pageEventQueue: Array<{category?: string, name?: string | null}>;
private get telemetry() {
// @ts-ignore
return window.rudderanalytics;
@ -49,14 +51,20 @@ class Telemetry {
},
};
init(options: ITelemetrySettings, instanceId: string) {
constructor() {
this.pageEventQueue = [];
}
init(options: ITelemetrySettings, instanceId: string, logLevel?: ILogLevel) {
if (options.enabled && !this.telemetry) {
if(!options.config) {
return;
}
this.loadTelemetryLibrary(options.config.key, options.config.url, { integrations: { All: false }, loadIntegration: false });
const logging = logLevel === 'debug' ? { logLevel: 'DEBUG'} : {};
this.loadTelemetryLibrary(options.config.key, options.config.url, { integrations: { All: false }, loadIntegration: false, ...logging});
this.telemetry.identify(instanceId);
this.flushPageEvents();
}
}
@ -66,10 +74,26 @@ class Telemetry {
}
}
page(category?: string, name?: string | undefined | null) {
page(category?: string, name?: string | null) {
if (this.telemetry) {
this.telemetry.page(category, name);
}
else {
this.pageEventQueue.push({
category,
name,
});
}
}
flushPageEvents() {
const queue = this.pageEventQueue;
this.pageEventQueue = [];
queue.forEach(({category, name}) => {
if (this.telemetry) {
this.telemetry.page(category, name);
}
});
}
trackNodesPanel(event: string, properties: IDataObject = {}) {

View file

@ -12,7 +12,6 @@ import {
INodeIssueData,
INodeTypeDescription,
IRunData,
ITelemetrySettings,
ITaskData,
IWorkflowSettings,
} from 'n8n-workflow';
@ -89,7 +88,6 @@ const state: IRootState = {
},
sidebarMenuItems: [],
instanceId: '',
telemetry: null,
};
const modules = {
@ -545,9 +543,6 @@ export const store = new Vuex.Store({
setInstanceId(state, instanceId: string) {
Vue.set(state, 'instanceId', instanceId);
},
setTelemetry(state, telemetry: ITelemetrySettings) {
Vue.set(state, 'telemetry', telemetry);
},
setOauthCallbackUrls(state, urls: IDataObject) {
Vue.set(state, 'oauthCallbackUrls', urls);
},
@ -659,10 +654,6 @@ export const store = new Vuex.Store({
return state.workflow.id === PLACEHOLDER_EMPTY_WORKFLOW_ID;
},
isTelemetryEnabled: (state) => {
return state.telemetry && state.telemetry.enabled;
},
currentWorkflowHasWebhookNode: (state: IRootState): boolean => {
return !!state.workflow.nodes.find((node: INodeUi) => !!node.webhookId);
},
@ -730,9 +721,6 @@ export const store = new Vuex.Store({
versionCli: (state): string => {
return state.versionCli;
},
telemetry: (state): ITelemetrySettings | null => {
return state.telemetry;
},
oauthCallbackUrls: (state): object => {
return state.oauthCallbackUrls;
},

View file

@ -2752,7 +2752,6 @@ export default mixins(
});
this.$externalHooks().run('nodeView.mount');
this.$telemetry.page('Editor', this.$route.name);
},
destroyed () {