Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(experiments): Apply correct filters to "View recordings" #27849

Merged
merged 5 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"kind": "ExperimentFunnelsQuery",
"funnels_query": {
"kind": "FunnelsQuery",
"series": [
{
"kind": "EventsNode",
"name": "[jan-16-running] seen",
"event": "[jan-16-running] seen"
},
{
"kind": "EventsNode",
"name": "[jan-16-running] payment",
"event": "[jan-16-running] payment"
}
],
"dateRange": {
"date_to": "2025-01-16T23:59",
"date_from": "2025-01-02T13:54",
"explicitDate": true
},
"funnelsFilter": {
"layout": "horizontal",
"funnelVizType": "steps",
"funnelWindowInterval": 14,
"funnelWindowIntervalUnit": "day"
},
"filterTestAccounts": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"kind": "ExperimentTrendsQuery",
"count_query": {
"kind": "TrendsQuery",
"series": [
{
"kind": "ActionsNode",
"id": 8,
"name": "jan-16-running payment action",
"math": "total"
}
],
"interval": "day",
"dateRange": {
"date_to": "2025-01-16T23:59",
"date_from": "2025-01-02T13:54",
"explicitDate": true
},
"trendsFilter": {
"display": "ActionsLineGraph"
},
"filterTestAccounts": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"kind": "ExperimentTrendsQuery",
"count_query": {
"kind": "TrendsQuery",
"series": [
{
"kind": "EventsNode",
"math": "total",
"name": "[jan-16-running] event one",
"event": "[jan-16-running] event one"
}
],
"interval": "day",
"dateRange": {
"date_to": "2025-01-16T23:59",
"date_from": "2025-01-02T13:54",
"explicitDate": true
},
"trendsFilter": {
"display": "ActionsLineGraph"
},
"filterTestAccounts": true
},
"exposure_query": {
"kind": "TrendsQuery",
"series": [
{
"kind": "EventsNode",
"math": "dau",
"name": "[jan-16-running] event zero",
"event": "[jan-16-running] event zero"
}
],
"interval": "day",
"dateRange": {
"date_to": "2025-01-23T23:59",
"date_from": "2025-01-09T15:10",
"explicitDate": true
},
"trendsFilter": {
"display": "ActionsLineGraph"
},
"filterTestAccounts": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"kind": "ExperimentTrendsQuery",
"count_query": {
"kind": "TrendsQuery",
"series": [
{
"kind": "EventsNode",
"math": "total",
"name": "[jan-16-running] event one",
"event": "[jan-16-running] event one"
}
],
"interval": "day",
"dateRange": {
"date_to": "2025-01-16T23:59",
"date_from": "2025-01-02T13:54",
"explicitDate": true
},
"trendsFilter": {
"display": "ActionsLineGraph"
},
"filterTestAccounts": true
}
}
41 changes: 4 additions & 37 deletions frontend/src/scenes/experiments/ExperimentView/SummaryTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ import { ExperimentFunnelsQuery, ExperimentTrendsQuery } from '~/queries/schema'
import {
FilterLogicalOperator,
InsightType,
PropertyFilterType,
PropertyOperator,
RecordingUniversalFilters,
ReplayTabs,
TrendExperimentVariant,
UniversalFiltersGroupValue,
} from '~/types'

import { experimentLogic } from '../experimentLogic'
import { getViewRecordingFilters } from '../utils'
import { VariantTag } from './components'

export function SummaryTable({
Expand Down Expand Up @@ -309,47 +307,16 @@ export function SummaryTable({
title: '',
render: function Key(_, item): JSX.Element {
const variantKey = item.key

const filters = getViewRecordingFilters(metric, experiment.feature_flag_key, variantKey)
return (
<LemonButton
size="xsmall"
icon={<IconRewindPlay />}
tooltip="Watch recordings of people who were exposed to this variant."
disabledReason={filters.length === 0 ? 'Unable to identify recordings for this metric' : undefined}
type="secondary"
onClick={() => {
const filters: UniversalFiltersGroupValue[] = [
{
id: '$feature_flag_called',
name: '$feature_flag_called',
type: 'events',
properties: [
{
key: `$feature/${experiment.feature_flag_key}`,
type: PropertyFilterType.Event,
value: [variantKey],
operator: PropertyOperator.Exact,
},
{
key: `$feature/${experiment.feature_flag_key}`,
type: PropertyFilterType.Event,
value: 'is_set',
operator: PropertyOperator.IsSet,
},
{
key: '$feature_flag',
type: PropertyFilterType.Event,
value: experiment.feature_flag_key,
operator: PropertyOperator.Exact,
},
],
},
]
if (experiment.filters.insight === InsightType.FUNNELS) {
if (experiment.filters?.events?.[0]) {
filters.push(experiment.filters.events[0])
} else if (experiment.filters?.actions?.[0]) {
filters.push(experiment.filters.actions[0])
}
}
const filterGroup: Partial<RecordingUniversalFilters> = {
filter_group: {
type: FilterLogicalOperator.And,
Expand Down
154 changes: 152 additions & 2 deletions frontend/src/scenes/experiments/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { EntityType, FeatureFlagFilters, InsightType } from '~/types'
import metricFunnelEventsJson from '~/mocks/fixtures/api/experiments/_metric_funnel_events.json'
import metricTrendActionJson from '~/mocks/fixtures/api/experiments/_metric_trend_action.json'
import metricTrendCustomExposureJson from '~/mocks/fixtures/api/experiments/_metric_trend_custom_exposure.json'
import metricTrendFeatureFlagCalledJson from '~/mocks/fixtures/api/experiments/_metric_trend_feature_flag_called.json'
import { ExperimentFunnelsQuery, ExperimentTrendsQuery } from '~/queries/schema/schema-general'
import { EntityType, FeatureFlagFilters, InsightType, PropertyFilterType, PropertyOperator } from '~/types'

import { getNiceTickValues } from './MetricsView/MetricsView'
import { getMinimumDetectableEffect, transformFiltersForWinningVariant } from './utils'
import { getMinimumDetectableEffect, getViewRecordingFilters, transformFiltersForWinningVariant } from './utils'

describe('utils', () => {
it('Funnel experiment returns correct MDE', async () => {
Expand Down Expand Up @@ -235,3 +240,148 @@ describe('getNiceTickValues', () => {
expect(getNiceTickValues(8.5)).toEqual([-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10])
})
})

describe('getViewRecordingFilters', () => {
const featureFlagKey = 'jan-16-running'

it('returns the correct filters for a funnel metric', () => {
const filters = getViewRecordingFilters(
metricFunnelEventsJson as ExperimentFunnelsQuery,
featureFlagKey,
'control'
)
expect(filters).toEqual([
{
id: '[jan-16-running] seen',
name: '[jan-16-running] seen',
type: 'events',
properties: [
{
key: `$feature/${featureFlagKey}`,
type: PropertyFilterType.Event,
value: ['control'],
operator: PropertyOperator.Exact,
},
],
},
{
id: '[jan-16-running] payment',
name: '[jan-16-running] payment',
type: 'events',
properties: [
{
key: `$feature/${featureFlagKey}`,
type: PropertyFilterType.Event,
value: ['control'],
operator: PropertyOperator.Exact,
},
],
},
])
})
it('returns the correct filters for a trend metric', () => {
const filters = getViewRecordingFilters(
metricTrendFeatureFlagCalledJson as ExperimentTrendsQuery,
featureFlagKey,
'test'
)
expect(filters).toEqual([
{
id: '$feature_flag_called',
name: '$feature_flag_called',
type: 'events',
properties: [
{
key: '$feature_flag_response',
type: PropertyFilterType.Event,
value: ['test'],
operator: PropertyOperator.Exact,
},
{
key: '$feature_flag',
type: PropertyFilterType.Event,
value: 'jan-16-running',
operator: PropertyOperator.Exact,
},
],
},
{
id: '[jan-16-running] event one',
name: '[jan-16-running] event one',
type: 'events',
properties: [
{
key: `$feature/${featureFlagKey}`,
type: PropertyFilterType.Event,
value: ['test'],
operator: PropertyOperator.Exact,
},
],
},
])
})
it('returns the correct filters for a trend metric with custom exposure', () => {
const filters = getViewRecordingFilters(
metricTrendCustomExposureJson as ExperimentTrendsQuery,
featureFlagKey,
'test'
)
expect(filters).toEqual([
{
id: '[jan-16-running] event zero',
name: '[jan-16-running] event zero',
type: 'events',
properties: [
{
key: `$feature/${featureFlagKey}`,
type: PropertyFilterType.Event,
value: ['test'],
operator: PropertyOperator.Exact,
},
],
},
{
id: '[jan-16-running] event one',
name: '[jan-16-running] event one',
type: 'events',
properties: [
{
key: `$feature/${featureFlagKey}`,
type: PropertyFilterType.Event,
value: ['test'],
operator: PropertyOperator.Exact,
},
],
},
])
})
it('returns the correct filters for a trend metric with an action', () => {
const filters = getViewRecordingFilters(metricTrendActionJson as ExperimentTrendsQuery, featureFlagKey, 'test')
expect(filters).toEqual([
{
id: '$feature_flag_called',
name: '$feature_flag_called',
type: 'events',
properties: [
{
key: '$feature_flag_response',
type: PropertyFilterType.Event,
value: ['test'],
operator: PropertyOperator.Exact,
},
{
key: '$feature_flag',
type: PropertyFilterType.Event,
value: 'jan-16-running',
operator: PropertyOperator.Exact,
},
],
},
{
id: 8,
name: 'jan-16-running payment action',
type: 'actions',
},
])
})
})
Loading
Loading