Skip to content

Commit 0d799b2

Browse files
authored
fix(experiments): fix retention metric recent activity query. (#42265)
1 parent 0c8186d commit 0d799b2

File tree

2 files changed

+77
-53
lines changed

2 files changed

+77
-53
lines changed

frontend/src/scenes/experiments/ExperimentMetricForm.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,22 @@ export function ExperimentMetricForm({
243243
const funnelSeries = isExperimentFunnelMetric(metric) ? metric.series : null
244244
const ratioNumerator = isExperimentRatioMetric(metric) ? metric.numerator : null
245245
const ratioDenominator = isExperimentRatioMetric(metric) ? metric.denominator : null
246+
const retentionStartEvent = isExperimentRetentionMetric(metric) ? metric.start_event : null
247+
const retentionCompletionEvent = isExperimentRetentionMetric(metric) ? metric.completion_event : null
246248

247249
useEffect(() => {
248250
loadEventCount(metric, filterTestAccounts, setEventCount, setIsLoading)
249251
// eslint-disable-next-line react-hooks/exhaustive-deps
250-
}, [metric.metric_type, meanSource, funnelSeries, ratioNumerator, ratioDenominator, filterTestAccounts])
252+
}, [
253+
metric.metric_type,
254+
meanSource,
255+
funnelSeries,
256+
ratioNumerator,
257+
ratioDenominator,
258+
retentionStartEvent,
259+
retentionCompletionEvent,
260+
filterTestAccounts,
261+
])
251262

252263
const hideDeleteBtn = (_: any, index: number): boolean => index === 0
253264

frontend/src/scenes/experiments/utils.ts

Lines changed: 65 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { match } from 'ts-pattern'
2+
13
import { getSeriesColor } from 'lib/colors'
24
import { EXPERIMENT_DEFAULT_DURATION, FunnelLayout } from 'lib/constants'
35
import { dayjs } from 'lib/dayjs'
@@ -21,6 +23,7 @@ import {
2123
isExperimentFunnelMetric,
2224
isExperimentMeanMetric,
2325
isExperimentRatioMetric,
26+
isExperimentRetentionMetric,
2427
} from '~/queries/schema/schema-general'
2528
import { isFunnelsQuery, isNodeWithSource, isTrendsQuery, isValidQueryForExperiment } from '~/queries/utils'
2629
import {
@@ -703,60 +706,15 @@ export const isLegacyExperiment = ({ metrics, metrics_secondary, saved_metrics }
703706

704707
export const isLegacySharedMetric = ({ query }: SharedMetric): boolean => isLegacyExperimentQuery(query)
705708

706-
/**
707-
* Builds a TrendsQuery for counting events in the last 14 days for experiment metric preview
708-
*/
709-
export function getEventCountQuery(metric: ExperimentMetric, filterTestAccounts: boolean): TrendsQuery | null {
710-
let series: AnyEntityNode[] = []
711-
712-
if (isExperimentMeanMetric(metric) || isExperimentRatioMetric(metric)) {
713-
let source: ExperimentMetricSource
714-
// For now, we simplify things by just showing the number of numerator events for ratio metrics
715-
if (isExperimentRatioMetric(metric)) {
716-
source = metric.numerator
717-
} else {
718-
source = metric.source
719-
}
720-
if (source.kind === NodeKind.EventsNode) {
721-
series = [
722-
{
723-
kind: NodeKind.EventsNode,
724-
name: source.event || undefined,
725-
event: source.event || undefined,
726-
math: ExperimentMetricMathType.TotalCount,
727-
...(source.properties && source.properties.length > 0 && { properties: source.properties }),
728-
},
729-
]
730-
} else if (source.kind === NodeKind.ActionsNode) {
731-
series = [
732-
{
733-
kind: NodeKind.ActionsNode,
734-
id: source.id,
735-
name: source.name,
736-
math: ExperimentMetricMathType.TotalCount,
737-
...(source.properties && source.properties.length > 0 && { properties: source.properties }),
738-
},
739-
]
740-
} else if (source.kind === NodeKind.ExperimentDataWarehouseNode) {
741-
series = [
742-
{
743-
kind: NodeKind.DataWarehouseNode,
744-
id: source.table_name,
745-
id_field: source.data_warehouse_join_key,
746-
table_name: source.table_name,
747-
timestamp_field: source.timestamp_field,
748-
distinct_id_field: source.events_join_key,
749-
name: source.name,
750-
math: ExperimentMetricMathType.TotalCount,
751-
...(source.properties && source.properties.length > 0 && { properties: source.properties }),
752-
},
753-
]
754-
}
755-
} else if (isExperimentFunnelMetric(metric)) {
709+
const getEventCountSeries = (metric: ExperimentMetric): AnyEntityNode[] => {
710+
/**
711+
* we short circuit for funnel metrics
712+
*/
713+
if (isExperimentFunnelMetric(metric)) {
756714
const lastStep = metric.series[metric.series.length - 1]
757715
if (lastStep) {
758716
if (lastStep.kind === NodeKind.EventsNode) {
759-
series = [
717+
return [
760718
{
761719
kind: NodeKind.EventsNode,
762720
name: lastStep.event || undefined,
@@ -767,7 +725,7 @@ export function getEventCountQuery(metric: ExperimentMetric, filterTestAccounts:
767725
},
768726
]
769727
} else if (lastStep.kind === NodeKind.ActionsNode) {
770-
series = [
728+
return [
771729
{
772730
kind: NodeKind.ActionsNode,
773731
id: lastStep.id,
@@ -781,6 +739,61 @@ export function getEventCountQuery(metric: ExperimentMetric, filterTestAccounts:
781739
}
782740
}
783741

742+
const source: ExperimentMetricSource | null = match(metric)
743+
.when(isExperimentRatioMetric, (ratioMetric) => ratioMetric.numerator)
744+
.when(isExperimentRetentionMetric, (retentionMetric) => retentionMetric.start_event)
745+
.when(isExperimentMeanMetric, (meanMetric) => meanMetric.source)
746+
.otherwise(() => null)
747+
748+
if (!source) {
749+
return []
750+
}
751+
752+
const series: AnyEntityNode[] = match(source)
753+
.with({ kind: NodeKind.EventsNode }, (eventsNode) => [
754+
{
755+
kind: NodeKind.EventsNode as const,
756+
name: eventsNode.event || undefined,
757+
event: eventsNode.event || undefined,
758+
math: ExperimentMetricMathType.TotalCount,
759+
...(eventsNode.properties && eventsNode.properties.length > 0 && { properties: eventsNode.properties }),
760+
},
761+
])
762+
.with({ kind: NodeKind.ActionsNode }, (actionsNode) => [
763+
{
764+
kind: NodeKind.ActionsNode as const,
765+
id: actionsNode.id,
766+
name: actionsNode.name,
767+
math: ExperimentMetricMathType.TotalCount,
768+
...(actionsNode.properties &&
769+
actionsNode.properties.length > 0 && { properties: actionsNode.properties }),
770+
},
771+
])
772+
.with({ kind: NodeKind.ExperimentDataWarehouseNode }, (dataWarehouseNode) => [
773+
{
774+
kind: NodeKind.DataWarehouseNode as const,
775+
id: dataWarehouseNode.table_name,
776+
id_field: dataWarehouseNode.data_warehouse_join_key,
777+
table_name: dataWarehouseNode.table_name,
778+
timestamp_field: dataWarehouseNode.timestamp_field,
779+
distinct_id_field: dataWarehouseNode.events_join_key,
780+
name: dataWarehouseNode.name,
781+
math: ExperimentMetricMathType.TotalCount,
782+
...(dataWarehouseNode.properties &&
783+
dataWarehouseNode.properties.length > 0 && { properties: dataWarehouseNode.properties }),
784+
},
785+
])
786+
.exhaustive()
787+
788+
return series
789+
}
790+
791+
/**
792+
* Builds a TrendsQuery for counting events in the last 14 days for experiment metric preview
793+
*/
794+
export function getEventCountQuery(metric: ExperimentMetric, filterTestAccounts: boolean): TrendsQuery | null {
795+
const series = getEventCountSeries(metric)
796+
784797
if (series.length === 0) {
785798
return null
786799
}

0 commit comments

Comments
 (0)