Skip to content

Commit

Permalink
Merge branch 'master' into hogql-metadata-validation-per-table
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusandra committed Oct 4, 2023
2 parents 872cc5b + b82890e commit 0f12176
Show file tree
Hide file tree
Showing 52 changed files with 1,027 additions and 537 deletions.
2 changes: 1 addition & 1 deletion ee/clickhouse/views/test/test_clickhouse_experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ def test_experiment_flow_with_event_results_for_three_test_variants(self):
self.assertAlmostEqual(response_data["expected_loss"], 1, places=2)


# @flaky(max_runs=10, min_passes=1)
@flaky(max_runs=10, min_passes=1)
class ClickhouseTestTrendExperimentResults(ClickhouseTestMixin, APILicensedTest):
@snapshot_clickhouse_queries
def test_experiment_flow_with_event_results(self):
Expand Down
7 changes: 4 additions & 3 deletions ee/tasks/subscriptions/subscription_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import List, Tuple, Union
from django.conf import settings
import structlog
from celery import group
from celery import chain
from prometheus_client import Histogram

from posthog.models.dashboard_tile import get_tiles_ordered_by_position
Expand Down Expand Up @@ -45,8 +45,9 @@ def generate_assets(
ExportedAsset.objects.bulk_create(assets)

# Wait for all assets to be exported
tasks = [exporter.export_asset.s(asset.id) for asset in assets]
parallel_job = group(tasks).apply_async()
tasks = [exporter.export_asset.si(asset.id) for asset in assets]
# run them one after the other so we don't exhaust celery workers
parallel_job = chain(*tasks).apply_async()

wait_for_parallel_celery_group(
parallel_job, max_timeout=timedelta(minutes=settings.ASSET_GENERATION_MAX_TIMEOUT_MINUTES)
Expand Down
8 changes: 4 additions & 4 deletions ee/tasks/test/subscriptions/test_subscriptions_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from posthog.test.base import APIBaseTest


@patch("ee.tasks.subscriptions.subscription_utils.group")
@patch("ee.tasks.subscriptions.subscription_utils.chain")
@patch("ee.tasks.subscriptions.subscription_utils.exporter.export_asset")
class TestSubscriptionsTasksUtils(APIBaseTest):
dashboard: Dashboard
Expand All @@ -36,7 +36,7 @@ def test_generate_assets_for_insight(self, mock_export_task: MagicMock, _mock_gr

assert insights == [self.insight]
assert len(assets) == 1
assert mock_export_task.s.call_count == 1
assert mock_export_task.si.call_count == 1

def test_generate_assets_for_dashboard(self, mock_export_task: MagicMock, _mock_group: MagicMock) -> None:
subscription = create_subscription(team=self.team, dashboard=self.dashboard, created_by=self.user)
Expand All @@ -46,7 +46,7 @@ def test_generate_assets_for_dashboard(self, mock_export_task: MagicMock, _mock_

assert len(insights) == len(self.tiles)
assert len(assets) == DEFAULT_MAX_ASSET_COUNT
assert mock_export_task.s.call_count == DEFAULT_MAX_ASSET_COUNT
assert mock_export_task.si.call_count == DEFAULT_MAX_ASSET_COUNT

def test_raises_if_missing_resource(self, _mock_export_task: MagicMock, _mock_group: MagicMock) -> None:
subscription = create_subscription(team=self.team, created_by=self.user)
Expand All @@ -70,7 +70,7 @@ def test_excludes_deleted_insights_for_dashboard(self, mock_export_task: MagicMo

assert len(insights) == 1
assert len(assets) == 1
assert mock_export_task.s.call_count == 1
assert mock_export_task.si.call_count == 1

def test_cancels_children_if_timed_out(self, _mock_export_task: MagicMock, mock_group: MagicMock) -> None:
# mock the group so that its children are never ready,
Expand Down
Binary file modified frontend/__snapshots__/scenes-app-surveys--new-survey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export const commandPaletteLogic = kea<commandPaletteLogicType>({
display: `View person ${input}`,
executor: () => {
const { push } = router.actions
push(urls.person(person.distinct_ids[0]))
push(urls.personByDistinctId(person.distinct_ids[0]))
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function redirectOnSelectItems(
} else if (groupType === TaxonomicFilterGroupType.Cohorts) {
router.actions.push(urls.cohort(value))
} else if (groupType === TaxonomicFilterGroupType.Persons) {
router.actions.push(urls.person(String(value)))
router.actions.push(urls.personByDistinctId(String(value)))
} else if (groupType.startsWith(TaxonomicFilterGroupType.GroupNamesPrefix)) {
router.actions.push(urls.group((item as Group).group_type_index, String(value)))
} else if (groupType === TaxonomicFilterGroupType.Insights) {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ export const FEATURE_FLAGS = {
FF_DASHBOARD_TEMPLATES: 'ff-dashboard-templates', // owner: @EDsCODE
SHOW_PRODUCT_INTRO_EXISTING_PRODUCTS: 'show-product-intro-existing-products', // owner: @raquelmsmith
ARTIFICIAL_HOG: 'artificial-hog', // owner: @Twixes
SURVEYS_MULTIPLE_CHOICE: 'surveys-multiple-choice', // owner: @liyiy
CS_DASHBOARDS: 'cs-dashboards', // owner: @pauldambra
PRODUCT_SPECIFIC_ONBOARDING: 'product-specific-onboarding', // owner: @raquelmsmith
REDIRECT_SIGNUPS_TO_INSTANCE: 'redirect-signups-to-instance', // owner: @raquelmsmith
Expand All @@ -169,6 +168,7 @@ export const FEATURE_FLAGS = {
HOGQL_INSIGHTS: 'hogql-insights', // owner: @mariusandra
WEBHOOKS_DENYLIST: 'webhooks-denylist', // owner: #team-pipeline
SURVEYS_SITE_APP_DEPRECATION: 'surveys-site-app-deprecation', // owner: @neilkakkar
SURVEYS_MULTIPLE_QUESTIONS: 'surveys-multiple-questions', // owner: @liyiy
} as const
export type FeatureFlagKey = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS]

Expand Down
8 changes: 7 additions & 1 deletion frontend/src/queries/nodes/DataTable/queryFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
isEventsQuery,
isHogQLQuery,
isPersonsNode,
isWebOverviewStatsQuery,
isWebTopClicksQuery,
isWebTopPagesQuery,
isWebTopSourcesQuery,
Expand Down Expand Up @@ -47,7 +48,12 @@ export function getQueryFeatures(query: Node): Set<QueryFeature> {
features.add(QueryFeature.personsSearch)
}

if (isWebTopSourcesQuery(query) || isWebTopPagesQuery(query) || isWebTopClicksQuery(query)) {
if (
isWebOverviewStatsQuery(query) ||
isWebTopSourcesQuery(query) ||
isWebTopPagesQuery(query) ||
isWebTopClicksQuery(query)
) {
features.add(QueryFeature.columnsInResponse)
features.add(QueryFeature.resultIsArrayOfArrays)
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/queries/nodes/DataTable/renderColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export function renderColumn(
} else if (key === 'person' && isPersonsNode(query.source)) {
const personRecord = record as PersonType
return (
<Link to={urls.person(personRecord.distinct_ids[0])}>
<Link to={urls.personByDistinctId(personRecord.distinct_ids[0])}>
<PersonDisplay noLink withIcon person={personRecord} noPopover />
</Link>
)
Expand Down
64 changes: 64 additions & 0 deletions frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@
{
"$ref": "#/definitions/TimeToSeeDataSessionsQuery"
},
{
"$ref": "#/definitions/WebOverviewStatsQuery"
},
{
"$ref": "#/definitions/WebTopSourcesQuery"
},
Expand Down Expand Up @@ -399,6 +402,9 @@
{
"$ref": "#/definitions/TimeToSeeDataSessionsQuery"
},
{
"$ref": "#/definitions/WebOverviewStatsQuery"
},
{
"$ref": "#/definitions/WebTopSourcesQuery"
},
Expand Down Expand Up @@ -1207,6 +1213,10 @@
"response": {
"$ref": "#/definitions/HogQLQueryResponse",
"description": "Cached query response"
},
"values": {
"description": "Constant values that can be referenced with the {placeholder} syntax in the query",
"type": "object"
}
},
"required": ["kind", "query"],
Expand Down Expand Up @@ -2295,6 +2305,60 @@
"type": "object"
},
"WebAnalyticsFilters": {},
"WebOverviewStatsQuery": {
"additionalProperties": false,
"properties": {
"dateRange": {
"$ref": "#/definitions/DateRange"
},
"filters": {
"$ref": "#/definitions/WebAnalyticsFilters"
},
"kind": {
"const": "WebOverviewStatsQuery",
"type": "string"
},
"response": {
"$ref": "#/definitions/WebOverviewStatsQueryResponse"
}
},
"required": ["kind", "filters"],
"type": "object"
},
"WebOverviewStatsQueryResponse": {
"additionalProperties": false,
"properties": {
"columns": {
"items": {},
"type": "array"
},
"is_cached": {
"type": "boolean"
},
"last_refresh": {
"type": "string"
},
"next_allowed_client_refresh": {
"type": "string"
},
"result": {
"items": {},
"type": "array"
},
"timings": {
"items": {
"$ref": "#/definitions/QueryTiming"
},
"type": "array"
},
"types": {
"items": {},
"type": "array"
}
},
"required": ["result"],
"type": "object"
},
"WebTopClicksQuery": {
"additionalProperties": false,
"properties": {
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/queries/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export enum NodeKind {
LifecycleQuery = 'LifecycleQuery',

// Web analytics queries
WebOverviewStatsQuery = 'WebOverviewStatsQuery',
WebTopSourcesQuery = 'WebTopSourcesQuery',
WebTopPagesQuery = 'WebTopPagesQuery',
WebTopClicksQuery = 'WebTopClicksQuery',
Expand All @@ -80,6 +81,7 @@ export type AnyDataNode =
| HogQLQuery
| HogQLMetadata
| TimeToSeeDataSessionsQuery
| WebOverviewStatsQuery
| WebTopSourcesQuery
| WebTopClicksQuery
| WebTopPagesQuery
Expand Down Expand Up @@ -144,6 +146,8 @@ export interface HogQLQuery extends DataNode {
kind: NodeKind.HogQLQuery
query: string
filters?: HogQLFilters
/** Constant values that can be referenced with the {placeholder} syntax in the query */
values?: Record<string, any>
response?: HogQLQueryResponse
}

Expand Down Expand Up @@ -295,6 +299,7 @@ export interface DataTableNode extends Node, DataTableNodeViewProps {
| PersonsNode
| HogQLQuery
| TimeToSeeDataSessionsQuery
| WebOverviewStatsQuery
| WebTopSourcesQuery
| WebTopClicksQuery
| WebTopPagesQuery
Expand Down Expand Up @@ -509,6 +514,17 @@ export interface WebAnalyticsQueryBase {
dateRange?: DateRange
}

export interface WebOverviewStatsQuery extends WebAnalyticsQueryBase {
kind: NodeKind.WebOverviewStatsQuery
filters: WebAnalyticsFilters
response?: WebOverviewStatsQueryResponse
}

export interface WebOverviewStatsQueryResponse extends QueryResponse {
result: unknown[]
types?: unknown[]
columns?: unknown[]
}
export interface WebTopSourcesQuery extends WebAnalyticsQueryBase {
kind: NodeKind.WebTopSourcesQuery
filters: WebAnalyticsFilters
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/queries/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
WebTopSourcesQuery,
WebTopClicksQuery,
WebTopPagesQuery,
WebOverviewStatsQuery,
HogQLMetadata,
} from '~/queries/schema'
import { TaxonomicFilterGroupType, TaxonomicFilterValue } from 'lib/components/TaxonomicFilter/types'
Expand Down Expand Up @@ -106,6 +107,10 @@ export function isHogQLMetadata(node?: Node | null): node is HogQLMetadata {
return node?.kind === NodeKind.HogQLMetadata
}

export function isWebOverviewStatsQuery(node?: Node | null): node is WebOverviewStatsQuery {
return node?.kind === NodeKind.WebOverviewStatsQuery
}

export function isWebTopSourcesQuery(node?: Node | null): node is WebTopSourcesQuery {
return node?.kind === NodeKind.WebTopSourcesQuery
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/appScenes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const appScenes: Record<Scene, () => any> = {
[Scene.Replay]: () => import('./session-recordings/SessionRecordings'),
[Scene.ReplaySingle]: () => import('./session-recordings/detail/SessionRecordingDetail'),
[Scene.ReplayPlaylist]: () => import('./session-recordings/playlist/SessionRecordingsPlaylistScene'),
[Scene.Person]: () => import('./persons/Person'),
[Scene.Person]: () => import('./persons/PersonScene'),
[Scene.Persons]: () => import('./persons/PersonsScene'),
[Scene.Groups]: () => import('./groups/Groups'),
[Scene.Group]: () => import('./groups/Group'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ const WARNING_TYPE_RENDERER = {
return (
<>
Refused to merge already identified person{' '}
<Link to={urls.person(details.sourcePersonDistinctId)}>{details.sourcePersonDistinctId}</Link> into{' '}
<Link to={urls.person(details.targetPersonDistinctId)}>{details.targetPersonDistinctId}</Link> via an
$identify or $create_alias call (event uuid: <code>{details.eventUuid}</code>).
<Link to={urls.personByDistinctId(details.sourcePersonDistinctId)}>
{details.sourcePersonDistinctId}
</Link>{' '}
into{' '}
<Link to={urls.personByDistinctId(details.targetPersonDistinctId)}>
{details.targetPersonDistinctId}
</Link>{' '}
via an $identify or $create_alias call (event uuid: <code>{details.eventUuid}</code>).
</>
)
},
Expand All @@ -51,9 +56,9 @@ const WARNING_TYPE_RENDERER = {
return (
<>
Refused to merge an illegal distinct_id{' '}
<Link to={urls.person(details.illegalDistinctId)}>{details.illegalDistinctId}</Link> with{' '}
<Link to={urls.person(details.otherDistinctId)}>{details.otherDistinctId}</Link> via an $identify or
$create_alias call (event uuid: <code>{details.eventUuid}</code>).
<Link to={urls.personByDistinctId(details.illegalDistinctId)}>{details.illegalDistinctId}</Link> with{' '}
<Link to={urls.personByDistinctId(details.otherDistinctId)}>{details.otherDistinctId}</Link> via an
$identify or $create_alias call (event uuid: <code>{details.eventUuid}</code>).
</>
)
},
Expand Down Expand Up @@ -116,8 +121,8 @@ const WARNING_TYPE_RENDERER = {
return (
<>
Event ingestion has overflowed capacity for distinct_id{' '}
<Link to={urls.person(details.overflowDistinctId)}>{details.overflowDistinctId}</Link>. Events will
still be processed, but are likely to be delayed longer than usual.
<Link to={urls.personByDistinctId(details.overflowDistinctId)}>{details.overflowDistinctId}</Link>.
Events will still be processed, but are likely to be delayed longer than usual.
</>
)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function backlinkHref(id: string, type: TaxonomicFilterGroupType): string {
} else if (type === TaxonomicFilterGroupType.Cohorts) {
return urls.cohort(id)
} else if (type === TaxonomicFilterGroupType.Persons) {
return urls.person(id)
return urls.personByDistinctId(id)
} else if (type === TaxonomicFilterGroupType.Insights) {
return urls.insightView(id as InsightModel['short_id'])
} else if (type === TaxonomicFilterGroupType.FeatureFlags) {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/notebooks/Nodes/NotebookNodePerson.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ export const NotebookNodePerson = createPostHogWidgetNode<NotebookNodePersonAttr
Component,
heightEstimate: 300,
minHeight: 100,
href: (attrs) => urls.person(attrs.id),
href: (attrs) => urls.personByDistinctId(attrs.id),
resizeable: true,
attributes: {
id: {},
},
pasteOptions: {
find: urls.person('(.+)', false),
find: urls.personByDistinctId('(.+)', false),
getAttributes: async (match) => {
return { id: match[1] }
},
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/scenes/persons/PersonPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function PersonPreview(props: PersonPreviewProps): JSX.Element | null {
}

const display = asDisplay(person)
const url = urls.person(person?.distinct_ids[0])
const url = urls.personByDistinctId(person?.distinct_ids[0])

return (
<div className="flex flex-col overflow-hidden max-h-80 max-w-160 gap-2">
Expand All @@ -51,7 +51,11 @@ export function PersonPreview(props: PersonPreviewProps): JSX.Element | null {
onNotebookOpened={() => props.onClose?.()}
size="small"
/>
<LemonButton size="small" icon={<IconOpenInNew />} to={urls.person(person?.distinct_ids[0])} />
<LemonButton
size="small"
icon={<IconOpenInNew />}
to={urls.personByDistinctId(person?.distinct_ids[0])}
/>
</div>

<div className="flex-1 overflow-y-auto border-t">
Expand Down
Loading

0 comments on commit 0f12176

Please sign in to comment.