Skip to content

Commit

Permalink
feat(hogql): Add actors query to live compare (#19999)
Browse files Browse the repository at this point in the history
  • Loading branch information
webjunkie authored and thmsobrmlr committed Feb 1, 2024
1 parent 69db47f commit aecc5c9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 23 deletions.
48 changes: 32 additions & 16 deletions frontend/src/queries/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ export async function query<N extends DataNode = DataNode>(
queryNode: N,
methodOptions?: ApiMethodOptions,
refresh?: boolean,
queryId?: string
queryId?: string,
legacyUrl?: string
): Promise<NonNullable<N['response']>> {
if (isTimeToSeeDataSessionsNode(queryNode)) {
return query(queryNode.source)
Expand Down Expand Up @@ -171,6 +172,11 @@ export async function query<N extends DataNode = DataNode>(
featureFlagLogic.findMounted()?.values.featureFlags?.[FEATURE_FLAGS.HOGQL_INSIGHT_LIVE_COMPARE]
)

async function fetchLegacyUrl(): Promise<Record<string, any>> {
const response = await api.getResponse(legacyUrl!)
return response.json()
}

async function fetchLegacyInsights(): Promise<Record<string, any>> {
if (!isInsightQueryNode(queryNode)) {
throw new Error('fetchLegacyInsights called with non-insight query. Should be unreachable.')
Expand Down Expand Up @@ -206,20 +212,22 @@ export async function query<N extends DataNode = DataNode>(
},
methodOptions
)
} else if (isInsightQueryNode(queryNode)) {
} else if (isInsightQueryNode(queryNode) || (isActorsQuery(queryNode) && !!legacyUrl)) {
if (
(hogQLInsightsLifecycleFlagEnabled && isLifecycleQuery(queryNode)) ||
(hogQLInsightsPathsFlagEnabled && isPathsQuery(queryNode)) ||
(hogQLInsightsPathsFlagEnabled &&
(isPathsQuery(queryNode) || (isActorsQuery(queryNode) && !!legacyUrl))) ||
(hogQLInsightsRetentionFlagEnabled && isRetentionQuery(queryNode)) ||
(hogQLInsightsTrendsFlagEnabled && isTrendsQuery(queryNode)) ||
(hogQLInsightsStickinessFlagEnabled && isStickinessQuery(queryNode)) ||
(hogQLInsightsFunnelsFlagEnabled && isFunnelsQuery(queryNode))
) {
if (hogQLInsightsLiveCompareEnabled) {
const legacyFunction = legacyUrl ? fetchLegacyUrl : fetchLegacyInsights
let legacyResponse: any
;[response, legacyResponse] = await Promise.all([
api.query(queryNode, methodOptions, queryId, refresh),
fetchLegacyInsights(),
legacyFunction(),
])

let res1 = response?.result || response?.results
Expand All @@ -243,6 +251,9 @@ export async function query<N extends DataNode = DataNode>(
action: undefined,
persons: undefined,
}))
} else if (res2.length > 0 && res2[0].people) {
res2 = res2[0]?.people.map((n: any) => n.id)
res1 = res1.map((n: any) => n[0].id)
}

const getTimingDiff = (): undefined | { diff: number; legacy: number; hogql: number } => {
Expand All @@ -265,6 +276,9 @@ export async function query<N extends DataNode = DataNode>(
}
}

const almostEqual = (n1: number, n2: number, epsilon: number = 1.0): boolean =>
Math.abs(n1 - n2) < epsilon

const timingDiff = getTimingDiff()

const results = flattenObject(res1)
Expand All @@ -276,17 +290,21 @@ export async function query<N extends DataNode = DataNode>(
let matchCount = 0
let mismatchCount = 0
for (const key of sortedKeys) {
if (results[key] === legacyResults[key]) {
let isMatch = false
if (
results[key] === legacyResults[key] ||
(key.includes('average_conversion_time') && almostEqual(results[key], legacyResults[key]))
) {
isMatch = true
}

if (isMatch) {
matchCount++
} else {
mismatchCount++
}
tableData.push([
results[key] === legacyResults[key] ? '✅' : '🚨',
key,
results[key],
legacyResults[key],
])

tableData.push([isMatch ? '✅' : '🚨', key, results[key], legacyResults[key]])
}

if (timingDiff) {
Expand All @@ -310,12 +328,10 @@ export async function query<N extends DataNode = DataNode>(
legacyResponse,
timingDiff,
})
const resultsLabel = mismatchCount === 0 ? '👏' : '⚠️'
const alertLabel = mismatchCount > 0 ? `🚨${mismatchCount}` : ''
// eslint-disable-next-line no-console
console.groupCollapsed(
`Results: ${mismatchCount === 0 ? '✅✅✅' : '✅'} ${matchCount}${
mismatchCount > 0 ? ` 🚨🚨🚨${mismatchCount}` : ''
}`
)
console.groupCollapsed(`Results: ${resultsLabel}${matchCount} ${alertLabel} ${queryNode.kind}`)
// eslint-disable-next-line no-console
console.table(tableData)
// eslint-disable-next-line no-console
Expand Down
1 change: 1 addition & 0 deletions frontend/src/scenes/paths/pathsDataLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export const pathsDataLogic = kea<pathsDataLogicType>([
},
}
openPersonsModal({
url: personsUrl,
query: pathsActorsQuery,
title: pathsTitle({
label: path_dropoff_key || path_start_key || path_end_key || 'Pageview',
Expand Down
22 changes: 15 additions & 7 deletions frontend/src/scenes/trends/persons-modal/personsModalLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,28 @@ export const personsModalLogic = kea<personsModalLogicType>([
if (values.searchTerm) {
url += `&search=${values.searchTerm}`
}

}
if (url && !query) {
const res = await api.get(url)
breakpoint()

if (clear) {
actions.resetActors()
}
return res
} else if (query) {
const response = await performQuery({
...values.actorsQuery,
limit: RESULTS_PER_PAGE + 1,
offset: offset || 0,
} as ActorsQuery)
}
if (query) {
const response = await performQuery(
{
...values.actorsQuery,
limit: RESULTS_PER_PAGE + 1,
offset: offset || 0,
} as ActorsQuery,
undefined,
undefined,
undefined,
url ?? undefined
)
breakpoint()

const assembledSelectFields = values.selectFields
Expand Down

0 comments on commit aecc5c9

Please sign in to comment.