From 0f40914e4284deb059bc6304fa41360a42a061ec Mon Sep 17 00:00:00 2001 From: Juraj Majerik Date: Thu, 25 Jan 2024 16:36:41 +0100 Subject: [PATCH] show required events --- .../scenes/experiments/ExperimentResult.tsx | 28 ++++++-- .../scenes/experiments/experimentLogic.tsx | 65 ++++++++++++++++++- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/frontend/src/scenes/experiments/ExperimentResult.tsx b/frontend/src/scenes/experiments/ExperimentResult.tsx index 8ba87a58b5f89..1e93254b51e76 100644 --- a/frontend/src/scenes/experiments/ExperimentResult.tsx +++ b/frontend/src/scenes/experiments/ExperimentResult.tsx @@ -30,9 +30,9 @@ export function ExperimentResult(): JSX.Element { conversionRateForVariant, getIndexForVariant, areTrendResultsConfusing, - experimentResultCalculationError, sortedExperimentResultVariants, experimentMathAggregationForTrends, + requiredEventsBreakdown, } = useValues(experimentLogic) return ( @@ -183,13 +183,27 @@ export function ExperimentResult(): JSX.Element { <>
{!experimentResultsLoading && ( -
+
There are no results for this experiment yet. -
- {!!experimentResultCalculationError && `${experimentResultCalculationError}. `}{' '} - Wait a bit longer for your users to be exposed to the experiment. Double check - your feature flag implementation if you're still not seeing results. -
+ {requiredEventsBreakdown && requiredEventsBreakdown.missingEvents.length && ( + <> +
+ To be able to see the results, the following events must yet be + ingested. Allow some time for the users to generate them, or double + check your feature flag implementation. +
+
+ {requiredEventsBreakdown.missingEvents.map(({ event, variant }) => ( +
+ {event} + + {variant} + +
+ ))} +
+ + )}
)}
diff --git a/frontend/src/scenes/experiments/experimentLogic.tsx b/frontend/src/scenes/experiments/experimentLogic.tsx index 97ea3b7257abd..879ab4e6f030f 100644 --- a/frontend/src/scenes/experiments/experimentLogic.tsx +++ b/frontend/src/scenes/experiments/experimentLogic.tsx @@ -23,7 +23,7 @@ import { urls } from 'scenes/urls' import { groupsModel } from '~/models/groupsModel' import { filtersToQueryNode } from '~/queries/nodes/InsightQuery/utils/filtersToQueryNode' import { queryNodeToFilter } from '~/queries/nodes/InsightQuery/utils/queryNodeToFilter' -import { InsightVizNode } from '~/queries/schema' +import { HogQLQuery, InsightVizNode, NodeKind } from '~/queries/schema' import { ActionFilter as ActionFilterType, Breadcrumb, @@ -79,6 +79,11 @@ export interface TabularSecondaryMetricResults { results?: SecondaryMetricResult[] } +export interface RequiredEventsBreakdown { + presentEvents: { event: string; variant: string }[] + missingEvents: { event: string; variant: string }[] +} + export const experimentLogic = kea([ props({} as ExperimentLogicProps), key((props) => props.experimentId || 'new'), @@ -406,6 +411,7 @@ export const experimentLogic = kea([ } else { actions.loadExperimentResults() actions.loadSecondaryMetricResults() + actions.loadRequiredEventsBreakdown() } }, launchExperiment: async () => { @@ -616,6 +622,63 @@ export const experimentLogic = kea([ }, }, ], + requiredEventsBreakdown: [ + null as RequiredEventsBreakdown | null, + { + loadRequiredEventsBreakdown: async (): Promise => { + const output = { + presentEvents: [] as { event: string; variant: string }[], + missingEvents: [] as { event: string; variant: string }[], + } + + const { experiment } = values + const { feature_flag, feature_flag_key } = experiment + const events = experiment.filters.events?.map((e) => e.id) + const variants = feature_flag?.filters.multivariate?.variants.map((v) => v.key) + + if (!events?.length || !variants?.length) { + return output + } + + const query: HogQLQuery = { + kind: NodeKind.HogQLQuery, + query: ` + SELECT + event, + JSONExtractString(properties, '$feature/${feature_flag_key}') AS variant, + COUNT(*) AS count + FROM events + WHERE event IN (${events.map((e) => `'${e}'`).join(', ')}) + AND variant IN (${variants.map((v) => `'${v}'`).join(', ')}) + GROUP BY event, variant + `, + } + + const responseJSON = await api.query(query) + const { results } = responseJSON + const presentEvents = new Set() + if (results && results.length) { + for (const [event, variant, count] of results) { + if (count && count > 0) { + presentEvents.add(`${event}::${variant}`) + } + } + } + + for (const event of events) { + for (const variant of variants) { + if (presentEvents.has(`${event}::${variant}`)) { + output.presentEvents.push({ event, variant }) + } else { + output.missingEvents.push({ event, variant }) + } + } + } + + return output + }, + }, + ], })), selectors({ props: [() => [(_, props) => props], (props) => props],