feat: Support feature flag evaluation server side (#5511)

* feat(editor): roll out schema view

* feat(editor): add posthog tracking

* refactor: use composables

* refactor: clean up console log

* refactor: clean up impl

* chore: clean up impl

* fix: fix demo var

* chore: add comment

* refactor: clean up

* chore: wrap error func

* refactor: clean up import

* refactor: make store

* feat: enable rudderstack usebeacon, move event to unload

* chore: clean up alert

* refactor: move tracking from hooks

* fix: reload flags on login

* fix: add func to setup

* fix: clear duplicate import

* chore: add console to tesT

* chore: add console to tesT

* fix: try reload

* chore: randomize instnace id for testing

* chore: randomize instnace id for testing

* chore: add console logs for testing

* chore: move random id to fe

* chore: use query param for testing

* feat: update PostHog api endpoint

* feat: update rs host

* feat: update rs host

* feat: update rs endpoints

* refactor: use api host for BE events as well

* refactor: refactor out posthog client

* feat: add feature flags to login

* feat: add feature flags to login

* feat: get feature flags to work

* feat: add created at to be events

* chore: add todos

* chore: clean up store

* chore: add created at to identify

* feat: add posthog config to settings

* feat: add bootstrapping

* chore: clean up

* chore: fix build

* fix: get dates to work

* fix: get posthog to recognize dates

* chore: refactor

* fix: update back to number

* fix: update key

* fix: get experiment evals to work

* feat: add posthog to signup router

* feat: add feature flags on sign up

* chore: clean up

* fix: fix import

* chore: clean up loading script

* feat: add timeout, fix: script loader

* fix: test timeout and get working on 8080

* refactor: move out posthog

* feat: add experiment tracking

* fix: clear tracked on reset

* fix: fix signup bug

* fix: handle errors when telmetry is disabled

* refactor: remove redundant await

* fix: add back posthog to telemetry

* test: fix test

* test: fix test

* test: add tests for posthog client

* lint: fix

* fix: fix issue with slow decide endpoint

* lint: fix

* lint: fix

* lint: fix

* lint: fix

* chore: address PR feedback

* chore: address PR feedback

* feat: add onboarding experiment
This commit is contained in:
Mutasem Aldmour
2023-02-21 11:35:35 +03:00
committed by GitHub
parent ee21b7a1cf
commit 26a20ed47e
29 changed files with 513 additions and 122 deletions

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import type RudderStack from '@rudderstack/rudder-sdk-node';
import type { PostHog } from 'posthog-node';
import type { PostHogClient } from '../posthog';
import type { ITelemetryTrackProperties } from 'n8n-workflow';
import { LoggerProxy } from 'n8n-workflow';
import config from '@/config';
@@ -31,13 +31,11 @@ interface IExecutionsBuffer {
export class Telemetry {
private rudderStack?: RudderStack;
private postHog?: PostHog;
private pulseIntervalReference: NodeJS.Timeout;
private executionCountsBuffer: IExecutionsBuffer = {};
constructor(private instanceId: string) {}
constructor(private instanceId: string, private postHog: PostHogClient) {}
async init() {
const enabled = config.getEnv('diagnostics.enabled');
@@ -58,12 +56,6 @@ export class Telemetry {
const { default: RudderStack } = await import('@rudderstack/rudder-sdk-node');
this.rudderStack = new RudderStack(key, url, { logLevel });
// eslint-disable-next-line @typescript-eslint/naming-convention
const { PostHog } = await import('posthog-node');
this.postHog = new PostHog(config.getEnv('diagnostics.config.posthog.apiKey'), {
host: config.getEnv('diagnostics.config.posthog.apiHost'),
});
this.startPulse();
}
}
@@ -137,10 +129,8 @@ export class Telemetry {
async trackN8nStop(): Promise<void> {
clearInterval(this.pulseIntervalReference);
void this.track('User instance stopped');
return new Promise<void>((resolve) => {
if (this.postHog) {
this.postHog.shutdown();
}
return new Promise<void>(async (resolve) => {
await this.postHog.stop();
if (this.rudderStack) {
this.rudderStack.flush(resolve);
@@ -192,11 +182,7 @@ export class Telemetry {
};
if (withPostHog) {
this.postHog?.capture({
distinctId: payload.userId,
sendFeatureFlags: true,
...payload,
});
this.postHog?.track(payload);
}
return this.rudderStack.track(payload, resolve);
@@ -206,19 +192,7 @@ export class Telemetry {
});
}
async isFeatureFlagEnabled(
featureFlagName: string,
{ user_id: userId }: ITelemetryTrackProperties = {},
): Promise<boolean | undefined> {
if (!this.postHog) return Promise.resolve(false);
const fullId = [this.instanceId, userId].join('#');
return this.postHog.isFeatureEnabled(featureFlagName, fullId);
}
// test helpers
getCountsBuffer(): IExecutionsBuffer {
return this.executionCountsBuffer;
}

View File

@@ -1,17 +0,0 @@
/**
* Create a script to init PostHog, for embedding before the Vue bundle in `<head>` in `index.html`.
*/
export const createPostHogLoadingScript = ({
apiKey,
apiHost,
autocapture,
disableSessionRecording,
debug,
}: {
apiKey: string;
apiHost: string;
autocapture: boolean;
disableSessionRecording: boolean;
debug: boolean;
}) =>
`<script>!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);posthog.init('${apiKey}',{api_host:'${apiHost}', autocapture: ${autocapture.toString()}, disable_session_recording: ${disableSessionRecording.toString()}, debug:${debug.toString()}})</script>`;