From 56f27168025ef53e975c2a508fd87e06a0d86786 Mon Sep 17 00:00:00 2001 From: Ady <121881917+ctrl-alter-ego@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:54:05 +0100 Subject: [PATCH 01/32] fix: #24114 prevent person being clicked on twice if deleted (#24776) Co-authored-by: ctrl-alter-ego --- frontend/src/scenes/persons/PersonDisplay.tsx | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/frontend/src/scenes/persons/PersonDisplay.tsx b/frontend/src/scenes/persons/PersonDisplay.tsx index b37d51fba17de..ce0593f9eb6bb 100644 --- a/frontend/src/scenes/persons/PersonDisplay.tsx +++ b/frontend/src/scenes/persons/PersonDisplay.tsx @@ -64,6 +64,17 @@ export function PersonDisplay({ const notebookNode = useNotebookNode() + const handleClick = (e: React.MouseEvent): void => { + if (visible && href && !noLink && person?.properties) { + router.actions.push(href) + } else if (visible && !person?.properties) { + e.preventDefault() + } else { + setVisible(true) + } + return + } + let content = ( {withIcon && } @@ -72,26 +83,13 @@ export function PersonDisplay({ ) content = ( - { - if (visible && href && !noLink) { - router.actions.push(href) - } else { - setVisible(true) - } - } - : undefined - } - > - {noLink || !href ? ( + + {noLink || !href || (visible && !person?.properties) ? ( content ) : ( { + onClick={(e: React.MouseEvent): void => { if (!noPopover && !notebookNode) { e.preventDefault() return From 43555bfc5eeb9c37e1f6a1616810cf7c4c4062be Mon Sep 17 00:00:00 2001 From: Ady <121881917+ctrl-alter-ego@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:55:35 +0100 Subject: [PATCH 02/32] fix: #24553 gives header buttons more room when editing titles (#24755) Co-authored-by: adyh Co-authored-by: Michael Matloka --- .../navigation-3000/components/TopBar.scss | 21 ++++++++++++++++--- .../navigation-3000/components/TopBar.tsx | 16 ++++++-------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/frontend/src/layout/navigation-3000/components/TopBar.scss b/frontend/src/layout/navigation-3000/components/TopBar.scss index 1628b3135ea86..3f05046fa8599 100644 --- a/frontend/src/layout/navigation-3000/components/TopBar.scss +++ b/frontend/src/layout/navigation-3000/components/TopBar.scss @@ -49,9 +49,14 @@ .TopBar3000__trail { display: flex; align-items: center; - height: 1rem; margin-top: calc(0.25rem * (1 - var(--breadcrumbs-compaction-rate))); overflow: visible; + + .TopBar3000:not(.TopBar3000--compact) & { + // 1rem of trail height ensures nice tight spacing in the full or transitioning state, + // but we don't want it in the compact state, as it causes title edit buttons to be cut off at top&bottom + height: 1rem; + } } .TopBar3000__here { @@ -65,7 +70,12 @@ font-size: 1rem; font-weight: 700; line-height: 1.2; - visibility: var(--breadcrumbs-title-large-visibility); + + .TopBar3000--compact & { + // It wouldn't be necessary to set visibility, but for some reason without this positioning + // of breadcrumbs becomes borked when entering title editing mode + visibility: hidden; + } > * { position: absolute; @@ -90,7 +100,12 @@ &.TopBar3000__breadcrumb--here { flex-shrink: 1; cursor: default; - visibility: var(--breadcrumbs-title-small-visibility); + + .TopBar3000--full & { + // It wouldn't be necessary to set visibility, but for some reason without this positioning + // of breadcrumbs becomes borked when entering title editing mode + visibility: hidden; + } > * { opacity: 1; diff --git a/frontend/src/layout/navigation-3000/components/TopBar.tsx b/frontend/src/layout/navigation-3000/components/TopBar.tsx index 805e52ad04e74..705f3d155bdc4 100644 --- a/frontend/src/layout/navigation-3000/components/TopBar.tsx +++ b/frontend/src/layout/navigation-3000/components/TopBar.tsx @@ -66,17 +66,13 @@ export function TopBar(): JSX.Element | null { return breadcrumbs.length ? (
{mobileLayout && ( From 74420aa016dd1ccfcc9ba7c0ba37d4aa9290e0de Mon Sep 17 00:00:00 2001 From: Oliver Browne Date: Wed, 4 Sep 2024 15:19:31 +0300 Subject: [PATCH 03/32] fix(capture-replay): try using jemalloc (#24778) --- rust/Cargo.lock | 21 +++++++++++++++++++++ rust/capture/Cargo.toml | 4 ++++ rust/capture/src/main.rs | 7 +++++++ 3 files changed, 32 insertions(+) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 55c64258d5ec2..8b577220c3ae0 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -639,6 +639,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "thiserror", + "tikv-jemallocator", "time", "tokio", "tower", @@ -3980,6 +3981,26 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tikv-jemalloc-sys" +version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "tikv-jemallocator" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865" +dependencies = [ + "libc", + "tikv-jemalloc-sys", +] + [[package]] name = "time" version = "0.3.36" diff --git a/rust/capture/Cargo.toml b/rust/capture/Cargo.toml index 55ccddd3a0311..cc551cdac99a1 100644 --- a/rust/capture/Cargo.toml +++ b/rust/capture/Cargo.toml @@ -7,6 +7,10 @@ edition = "2021" workspace = true [dependencies] + +[target.'cfg(not(target_env = "msvc"))'.dependencies] +tikv-jemallocator = "0.6" + anyhow = { workspace = true } async-trait = { workspace = true } axum = { workspace = true } diff --git a/rust/capture/src/main.rs b/rust/capture/src/main.rs index 12b91941c7f6c..14868f059f02b 100644 --- a/rust/capture/src/main.rs +++ b/rust/capture/src/main.rs @@ -16,6 +16,13 @@ use tracing_subscriber::{EnvFilter, Layer}; use capture::config::Config; use capture::server::serve; +#[cfg(not(target_env = "msvc"))] +use tikv_jemallocator::Jemalloc; + +#[cfg(not(target_env = "msvc"))] +#[global_allocator] +static GLOBAL: Jemalloc = Jemalloc; + async fn shutdown() { let mut term = signal::unix::signal(signal::unix::SignalKind::terminate()) .expect("failed to register SIGTERM handler"); From e26da47efa726abfea83c3a15f5de47636c72d07 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Wed, 4 Sep 2024 15:32:10 +0200 Subject: [PATCH 04/32] fix(frontend): Don't crash on color retrieval error (#24780) --- frontend/src/lib/colors.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/lib/colors.ts b/frontend/src/lib/colors.ts index 1413b241800a0..cc9530b5bc524 100644 --- a/frontend/src/lib/colors.ts +++ b/frontend/src/lib/colors.ts @@ -1,3 +1,5 @@ +import { captureException } from '@sentry/react' + import { LifecycleToggle } from '~/types' import { LemonTagType } from './lemon-ui/LemonTag' @@ -39,7 +41,9 @@ export const tagColors: LemonTagType[] = [ export function getColorVar(variable: string): string { const colorValue = getComputedStyle(document.body).getPropertyValue('--' + variable) if (!colorValue) { - throw new Error(`Couldn't find color variable --${variable}`) + captureException(new Error(`Couldn't find color variable --${variable}`)) + // Fall back to black or white depending on the theme + return document.body.getAttribute('theme') === 'light' ? '#000' : '#fff' } return colorValue.trim() } From 9842e97b587ae1378831f817d3445915f1f1fbb3 Mon Sep 17 00:00:00 2001 From: Tom Owers Date: Wed, 4 Sep 2024 15:21:00 +0100 Subject: [PATCH 05/32] chore(data-warehouse): Updated billing limits to work per sync (#24752) --- ee/billing/quota_limiting.py | 26 ++--- ee/billing/test/test_quota_limiting.py | 6 +- .../DataWarehouseManagedSourcesTable.tsx | 1 + .../settings/source/Schemas.tsx | 1 + .../data-warehouse/settings/source/Syncs.tsx | 2 +- frontend/src/types.ts | 2 +- mypy-baseline.txt | 67 +++++------ posthog/tasks/scheduled.py | 7 -- posthog/tasks/tasks.py | 10 -- posthog/tasks/test/test_warehouse.py | 104 +---------------- posthog/tasks/warehouse.py | 92 +-------------- posthog/temporal/data_imports/__init__.py | 2 + .../data_imports/external_data_job.py | 43 ++++--- .../data_imports/pipelines/helpers.py | 9 -- .../pipelines/rest_source/__init__.py | 7 -- .../check_billing_limits.py | 41 +++++++ .../workflow_activities/create_job_model.py | 4 +- .../tests/data_imports/test_end_to_end.py | 43 +++++++ .../external_data/test_external_data_job.py | 109 +----------------- posthog/warehouse/api/external_data_schema.py | 7 ++ posthog/warehouse/api/external_data_source.py | 9 +- .../warehouse/external_data_source/jobs.py | 13 ++- 22 files changed, 190 insertions(+), 415 deletions(-) create mode 100644 posthog/temporal/data_imports/workflow_activities/check_billing_limits.py diff --git a/ee/billing/quota_limiting.py b/ee/billing/quota_limiting.py index fbf35a09e2dd3..f91811d866a40 100644 --- a/ee/billing/quota_limiting.py +++ b/ee/billing/quota_limiting.py @@ -122,7 +122,7 @@ def org_quota_limited_until( if organization.never_drop_data or trust_score == 15: return None - team_tokens = get_team_attribute_by_quota_resource(organization, resource) + team_tokens = get_team_attribute_by_quota_resource(organization) team_being_limited = any(x in previously_quota_limited_team_tokens for x in team_tokens) if team_being_limited: @@ -237,7 +237,7 @@ def sync_org_quota_limits(organization: Organization): previously_quota_limited_team_tokens = list_limited_team_attributes( resource, QuotaLimitingCaches.QUOTA_LIMITER_CACHE_KEY ) - team_attributes = get_team_attribute_by_quota_resource(organization, resource) + team_attributes = get_team_attribute_by_quota_resource(organization) result = org_quota_limited_until(organization, resource, previously_quota_limited_team_tokens) if result: @@ -264,24 +264,14 @@ def sync_org_quota_limits(organization: Organization): remove_limited_team_tokens(resource, team_attributes, QuotaLimitingCaches.QUOTA_LIMITING_SUSPENDED_KEY) -def get_team_attribute_by_quota_resource(organization: Organization, resource: QuotaResource): - if resource in [QuotaResource.EVENTS, QuotaResource.RECORDINGS]: - team_tokens: list[str] = [x for x in list(organization.teams.values_list("api_token", flat=True)) if x] +def get_team_attribute_by_quota_resource(organization: Organization): + team_tokens: list[str] = [x for x in list(organization.teams.values_list("api_token", flat=True)) if x] - if not team_tokens: - capture_exception(Exception(f"quota_limiting: No team tokens found for organization: {organization.id}")) - return + if not team_tokens: + capture_exception(Exception(f"quota_limiting: No team tokens found for organization: {organization.id}")) + return - return team_tokens - - if resource == QuotaResource.ROWS_SYNCED: - team_ids: list[str] = [x for x in list(organization.teams.values_list("id", flat=True)) if x] - - if not team_ids: - capture_exception(Exception(f"quota_limiting: No team ids found for organization: {organization.id}")) - return - - return team_ids + return team_tokens def set_org_usage_summary( diff --git a/ee/billing/test/test_quota_limiting.py b/ee/billing/test/test_quota_limiting.py index 3e8b5105767d3..926e3441c4f73 100644 --- a/ee/billing/test/test_quota_limiting.py +++ b/ee/billing/test/test_quota_limiting.py @@ -92,7 +92,7 @@ def test_quota_limiting_feature_flag_enabled(self, patch_feature_enabled, patch_ patch_capture.reset_mock() # Add this org to the redis cache. - team_tokens = get_team_attribute_by_quota_resource(self.organization, QuotaResource.EVENTS) + team_tokens = get_team_attribute_by_quota_resource(self.organization) add_limited_team_tokens( QuotaResource.EVENTS, {x: 1612137599 for x in team_tokens}, @@ -715,7 +715,7 @@ def test_sync_org_quota_limits(self): # rows_synced uses teams, not tokens assert sorted( list_limited_team_attributes(QuotaResource.ROWS_SYNCED, QuotaLimitingCaches.QUOTA_LIMITER_CACHE_KEY) - ) == sorted(["1337", str(self.team.pk), str(other_team.pk)]) + ) == sorted(["1337", str(self.team.api_token), str(other_team.api_token)]) self.organization.usage["events"]["usage"] = 80 self.organization.usage["rows_synced"]["usage"] = 36 @@ -748,7 +748,7 @@ def test_sync_org_quota_limits(self): list_limited_team_attributes( QuotaResource.ROWS_SYNCED, QuotaLimitingCaches.QUOTA_LIMITING_SUSPENDED_KEY ) - ) == sorted([str(self.team.pk), str(other_team.pk)]) + ) == sorted([str(self.team.api_token), str(other_team.api_token)]) self.organization.usage["events"]["usage"] = 80 self.organization.usage["rows_synced"]["usage"] = 36 diff --git a/frontend/src/scenes/data-warehouse/settings/DataWarehouseManagedSourcesTable.tsx b/frontend/src/scenes/data-warehouse/settings/DataWarehouseManagedSourcesTable.tsx index e983ce363bd95..d18657892fd22 100644 --- a/frontend/src/scenes/data-warehouse/settings/DataWarehouseManagedSourcesTable.tsx +++ b/frontend/src/scenes/data-warehouse/settings/DataWarehouseManagedSourcesTable.tsx @@ -27,6 +27,7 @@ const StatusTagSetting = { Completed: 'success', Error: 'danger', Failed: 'danger', + 'Billing limits': 'danger', } export function DataWarehouseManagedSourcesTable(): JSX.Element { diff --git a/frontend/src/scenes/data-warehouse/settings/source/Schemas.tsx b/frontend/src/scenes/data-warehouse/settings/source/Schemas.tsx index 2a3fa469ac658..56c5e12963dd8 100644 --- a/frontend/src/scenes/data-warehouse/settings/source/Schemas.tsx +++ b/frontend/src/scenes/data-warehouse/settings/source/Schemas.tsx @@ -47,6 +47,7 @@ const StatusTagSetting = { Completed: 'success', Error: 'danger', Failed: 'danger', + 'Billing limits': 'danger', } export const SchemaTable = ({ schemas, isLoading }: SchemaTableProps): JSX.Element => { diff --git a/frontend/src/scenes/data-warehouse/settings/source/Syncs.tsx b/frontend/src/scenes/data-warehouse/settings/source/Syncs.tsx index a86a41ec867ae..c283e32c7b54b 100644 --- a/frontend/src/scenes/data-warehouse/settings/source/Syncs.tsx +++ b/frontend/src/scenes/data-warehouse/settings/source/Syncs.tsx @@ -11,7 +11,7 @@ const StatusTagSetting: Record = { Running: 'primary', Completed: 'success', Failed: 'danger', - Cancelled: 'default', + 'Billing limits': 'danger', } interface SyncsProps { diff --git a/frontend/src/types.ts b/frontend/src/types.ts index cbc91482a2bae..a4e8187d755de 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -3924,7 +3924,7 @@ export interface ExternalDataSourceSchema extends SimpleExternalDataSourceSchema export interface ExternalDataJob { id: string created_at: string - status: 'Running' | 'Failed' | 'Completed' | 'Cancelled' + status: 'Running' | 'Failed' | 'Completed' | 'Billing limits' schema: SimpleExternalDataSourceSchema rows_synced: number latest_error: string diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 2a1b0092f3f1b..9e25498b357dd 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -27,6 +27,21 @@ posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Un posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unpacked dict entry 1 has incompatible type "dict[str, Any] | None"; expected "SupportsKeysAndGetItem[str, Any]" [dict-item] posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unpacked dict entry 0 has incompatible type "dict[str, Any] | None"; expected "SupportsKeysAndGetItem[str, ResolveParamConfig | IncrementalParamConfig | Any]" [dict-item] posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unpacked dict entry 1 has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "SupportsKeysAndGetItem[str, ResolveParamConfig | IncrementalParamConfig | Any]" [dict-item] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Not all union combinations were tried because there are too many unions [misc] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 2 to "source" has incompatible type "str | None"; expected "str" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 3 to "source" has incompatible type "str | None"; expected "str" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 4 to "source" has incompatible type "int | None"; expected "int" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 6 to "source" has incompatible type "Schema | None"; expected "Schema" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 7 to "source" has incompatible type "Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | None"; expected "Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 8 to "source" has incompatible type "type[BaseConfiguration] | None"; expected "type[BaseConfiguration]" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "build_resource_dependency_graph" has incompatible type "EndpointResourceBase | None"; expected "EndpointResourceBase" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible types in assignment (expression has type "list[str] | None", variable has type "list[str]") [assignment] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "setup_incremental_object" has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "dict[str, Any]" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument "base_url" to "RESTClient" has incompatible type "str | None"; expected "str" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "exclude_keys" has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "Mapping[str, Any]" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible default for argument "resolved_param" (default has type "ResolvedParam | None", argument has type "ResolvedParam") [assignment] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument "module" to "SourceInfo" has incompatible type Module | None; expected Module [arg-type] posthog/utils.py:0: error: No overload variant of "asdict" matches argument type "type[DataclassInstance]" [call-overload] posthog/utils.py:0: note: Possible overload variants: posthog/utils.py:0: note: def asdict(obj: DataclassInstance) -> dict[str, Any] @@ -239,7 +254,6 @@ posthog/user_permissions.py:0: error: Key expression in dictionary comprehension posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "Level | None") [return-value] posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "Level | None") [return-value] posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "RestrictionLevel") [return-value] -posthog/tasks/warehouse.py:0: error: Argument 1 to "cancel_external_data_workflow" has incompatible type "str | None"; expected "str" [arg-type] posthog/tasks/update_survey_iteration.py:0: error: Incompatible types in assignment (expression has type "ForeignKey[Any, _ST] | Any", variable has type "FeatureFlag | Combinable | None") [assignment] posthog/tasks/update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] posthog/tasks/update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] @@ -266,7 +280,6 @@ posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] posthog/api/shared.py:0: error: Incompatible return value type (got "int | None", expected "Level | None") [return-value] ee/billing/quota_limiting.py:0: error: Argument 2 to "feature_enabled" has incompatible type "UUID"; expected "str" [arg-type] -ee/billing/quota_limiting.py:0: error: List comprehension has incompatible type List[int]; expected List[str] [misc] ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] ee/billing/quota_limiting.py:0: error: "object" has no attribute "get" [attr-defined] ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] @@ -412,7 +425,6 @@ posthog/api/user.py:0: error: "User" has no attribute "social_auth" [attr-defin ee/clickhouse/queries/related_actors_query.py:0: error: Argument 1 to "_query_related_groups" of "RelatedActorsQuery" has incompatible type "int"; expected "Literal[0, 1, 2, 3, 4]" [arg-type] ee/api/test/base.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "License") [assignment] ee/api/test/base.py:0: error: "setUpTestData" undefined in superclass [misc] -posthog/warehouse/external_data_source/jobs.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "Status") [assignment] posthog/warehouse/external_data_source/jobs.py:0: error: Incompatible type for lookup 'id': (got "UUID | None", expected "UUID | str") [misc] posthog/warehouse/api/test/test_table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_key" [union-attr] posthog/warehouse/api/test/test_table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_secret" [union-attr] @@ -436,6 +448,23 @@ posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/tasks/test/test_update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] posthog/tasks/test/test_stop_surveys_reached_target.py:0: error: No overload variant of "__sub__" of "datetime" matches argument type "None" [operator] posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: Possible overload variants: @@ -591,21 +620,6 @@ posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: note: d posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: note: def get(self, Type, Sequence[str], /) -> Sequence[str] posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: note: def [_T] get(self, Type, _T, /) -> Sequence[str] | _T posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: error: Argument 1 has incompatible type "dict[str, list[tuple[str, str]]]"; expected "list[Any]" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Not all union combinations were tried because there are too many unions [misc] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 2 to "source" has incompatible type "str | None"; expected "str" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 3 to "source" has incompatible type "str | None"; expected "str" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 4 to "source" has incompatible type "int | None"; expected "int" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 6 to "source" has incompatible type "Schema | None"; expected "Schema" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 7 to "source" has incompatible type "Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | None"; expected "Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 8 to "source" has incompatible type "type[BaseConfiguration] | None"; expected "type[BaseConfiguration]" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "build_resource_dependency_graph" has incompatible type "EndpointResourceBase | None"; expected "EndpointResourceBase" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible types in assignment (expression has type "list[str] | None", variable has type "list[str]") [assignment] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "setup_incremental_object" has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "dict[str, Any]" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument "base_url" to "RESTClient" has incompatible type "str | None"; expected "str" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "exclude_keys" has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "Mapping[str, Any]" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible default for argument "resolved_param" (default has type "ResolvedParam | None", argument has type "ResolvedParam") [assignment] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument "module" to "SourceInfo" has incompatible type Module | None; expected Module [arg-type] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a return type annotation [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] @@ -764,23 +778,6 @@ posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/tests/batch_exports/test_batch_exports.py:0: error: TypedDict key must be a string literal; expected one of ("_timestamp", "created_at", "distinct_id", "elements", "elements_chain", ...) [literal-required] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] diff --git a/posthog/tasks/scheduled.py b/posthog/tasks/scheduled.py index df765689fb362..149a00eb11831 100644 --- a/posthog/tasks/scheduled.py +++ b/posthog/tasks/scheduled.py @@ -15,7 +15,6 @@ calculate_decide_usage, calculate_replay_embeddings, check_async_migration_health, - check_data_import_row_limits, check_flags_to_rollback, clean_stale_partials, clear_clickhouse_deleted_person, @@ -315,13 +314,7 @@ def setup_periodic_tasks(sender: Celery, **kwargs: Any) -> None: name="delete expired exported assets", ) - sender.add_periodic_task( - crontab(minute="*/20"), - check_data_import_row_limits.s(), - name="check external data rows synced", - ) # Every 20 minutes try to retrieve and calculate total rows synced in period - sender.add_periodic_task( crontab(minute="*/20"), calculate_external_data_rows_synced.s(), diff --git a/posthog/tasks/tasks.py b/posthog/tasks/tasks.py index 5c4b085072287..f2bf138177a35 100644 --- a/posthog/tasks/tasks.py +++ b/posthog/tasks/tasks.py @@ -890,16 +890,6 @@ def ee_persist_finished_recordings() -> None: persist_finished_recordings() -@shared_task(ignore_result=True) -def check_data_import_row_limits() -> None: - try: - from posthog.tasks.warehouse import check_synced_row_limits - except ImportError: - pass - else: - check_synced_row_limits() - - # this task runs a CH query and triggers other tasks # it can run on the default queue @shared_task(ignore_result=True) diff --git a/posthog/tasks/test/test_warehouse.py b/posthog/tasks/test/test_warehouse.py index 8a83cad234d88..c6150ef565336 100644 --- a/posthog/tasks/test/test_warehouse.py +++ b/posthog/tasks/test/test_warehouse.py @@ -1,12 +1,11 @@ from posthog.test.base import APIBaseTest from unittest.mock import patch, MagicMock from posthog.tasks.warehouse import ( - check_synced_row_limits_of_team, capture_workspace_rows_synced_by_team, validate_data_warehouse_table_columns, capture_external_data_rows_synced, ) -from posthog.warehouse.models import ExternalDataSource, ExternalDataJob, ExternalDataSchema +from posthog.warehouse.models import ExternalDataSource, ExternalDataJob from freezegun import freeze_time import datetime @@ -14,107 +13,6 @@ class TestWarehouse(APIBaseTest): - @patch("posthog.tasks.warehouse.MONTHLY_LIMIT", 100) - @patch("posthog.tasks.warehouse.cancel_external_data_workflow") - @patch("posthog.tasks.warehouse.pause_external_data_schedule") - @patch("ee.billing.quota_limiting.list_limited_team_attributes") - def test_check_synced_row_limits_of_team_monthly_limit( - self, - list_limited_team_attributes_mock: MagicMock, - pause_schedule_mock: MagicMock, - cancel_workflow_mock: MagicMock, - ) -> None: - list_limited_team_attributes_mock.return_value = [] - - source = ExternalDataSource.objects.create( - source_id="test_id", - connection_id="fake connectino_id", - destination_id="fake destination_id", - team=self.team, - status="Running", - source_type="Stripe", - ) - - schema = ExternalDataSchema.objects.create( - source=source, - name="test_schema", - team=self.team, - status="Running", - ) - - job = ExternalDataJob.objects.create( - pipeline=source, - workflow_id="fake_workflow_id", - team=self.team, - status="Running", - rows_synced=100000, - schema=schema, - ) - - check_synced_row_limits_of_team(self.team.pk) - - source.refresh_from_db() - self.assertEqual(source.status, ExternalDataSource.Status.PAUSED) - - schema.refresh_from_db() - self.assertEqual(schema.status, ExternalDataSchema.Status.PAUSED) - - job.refresh_from_db() - self.assertEqual(job.status, ExternalDataJob.Status.CANCELLED) - - self.assertEqual(pause_schedule_mock.call_count, 1) - self.assertEqual(cancel_workflow_mock.call_count, 1) - - @patch("posthog.tasks.warehouse.cancel_external_data_workflow") - @patch("posthog.tasks.warehouse.pause_external_data_schedule") - @patch("ee.billing.quota_limiting.list_limited_team_attributes") - def test_check_synced_row_limits_of_team( - self, - list_limited_team_attributes_mock: MagicMock, - pause_schedule_mock: MagicMock, - cancel_workflow_mock: MagicMock, - ) -> None: - list_limited_team_attributes_mock.return_value = [self.team.api_token] - - source = ExternalDataSource.objects.create( - source_id="test_id", - connection_id="fake connectino_id", - destination_id="fake destination_id", - team=self.team, - status="Running", - source_type="Stripe", - ) - - schema = ExternalDataSchema.objects.create( - source=source, - name="test_schema", - team=self.team, - status="Running", - ) - - job = ExternalDataJob.objects.create( - pipeline=source, - workflow_id="fake_workflow_id", - team=self.team, - status="Running", - rows_synced=100000, - schema=schema, - ) - - check_synced_row_limits_of_team(self.team.pk) - - source.refresh_from_db() - self.assertEqual(source.status, ExternalDataSource.Status.PAUSED) - - schema.refresh_from_db() - self.assertEqual(schema.status, ExternalDataSchema.Status.PAUSED) - - job.refresh_from_db() - self.assertEqual(job.status, ExternalDataJob.Status.CANCELLED) - - self.assertEqual(pause_schedule_mock.call_count, 1) - self.assertEqual(cancel_workflow_mock.call_count, 1) - @patch("posthog.tasks.warehouse.get_ph_client") @patch( "posthog.tasks.warehouse.DEFAULT_DATE_TIME", diff --git a/posthog/tasks/warehouse.py b/posthog/tasks/warehouse.py index 518d4fc3027c4..3e75017ca81b4 100644 --- a/posthog/tasks/warehouse.py +++ b/posthog/tasks/warehouse.py @@ -3,20 +3,13 @@ import structlog from celery import shared_task -from posthog.warehouse.data_load.service import ( - cancel_external_data_workflow, - pause_external_data_schedule, - unpause_external_data_schedule, -) -from posthog.warehouse.models import ExternalDataJob, ExternalDataSource, ExternalDataSchema +from posthog.warehouse.models import ExternalDataJob, ExternalDataSource from posthog.ph_client import get_ph_client from posthog.models import Team from django.db.models import Q logger = structlog.get_logger(__name__) -MONTHLY_LIMIT = 500_000_000 - # TODO: adjust to whenever billing officially starts DEFAULT_DATE_TIME = datetime.datetime(2024, 6, 1, tzinfo=datetime.UTC) @@ -32,89 +25,6 @@ def capture_external_data_rows_synced() -> None: capture_workspace_rows_synced_by_team.delay(team_id) -def check_synced_row_limits() -> None: - team_ids = ExternalDataSource.objects.values_list("team", flat=True) - for team_id in team_ids: - check_synced_row_limits_of_team.delay(team_id) - - -@shared_task(ignore_result=True) -def check_synced_row_limits_of_team(team_id: int) -> None: - logger.info("Checking synced row limits of team", team_id=team_id) - team_model = Team.objects.get(pk=team_id) - - from ee.billing.quota_limiting import list_limited_team_attributes, QuotaResource, QuotaLimitingCaches - - # TODO: temp workaround. Should use team ids directly instead of tokens - limited_team_tokens_rows_synced = list_limited_team_attributes( - QuotaResource.ROWS_SYNCED, QuotaLimitingCaches.QUOTA_LIMITER_CACHE_KEY - ) - - # TODO: Remove once billing logic is fully through - start_of_month = datetime.datetime.now().replace(day=1, hour=0, minute=0, second=0, microsecond=0) - rows_synced_list = [ - x - for x in ExternalDataJob.objects.filter(team_id=team_id, created_at__gte=start_of_month).values_list( - "rows_synced", flat=True - ) - if x - ] - total_rows_synced = sum(rows_synced_list) - - if team_model.api_token in limited_team_tokens_rows_synced or total_rows_synced > MONTHLY_LIMIT: - # stop active jobs - running_jobs = ExternalDataJob.objects.filter(team_id=team_id, status=ExternalDataJob.Status.RUNNING) - for job in running_jobs: - try: - cancel_external_data_workflow(job.workflow_id) - except Exception as e: - logger.exception("Could not cancel external data workflow", exc_info=e) - - try: - pause_external_data_schedule(str(job.pipeline.id)) - except Exception as e: - logger.exception("Could not pause external data schedule", exc_info=e) - - job.status = ExternalDataJob.Status.CANCELLED - job.save() - - job.pipeline.status = ExternalDataSource.Status.PAUSED - job.pipeline.save() - - if job.schema: - job.schema.status = ExternalDataSchema.Status.PAUSED - job.schema.save() - - # pause active schemas - all_schemas = ExternalDataSchema.objects.filter( - team_id=team_id, status__in=[ExternalDataSchema.Status.COMPLETED, ExternalDataSchema.Status.RUNNING] - ) - for schema in all_schemas: - try: - pause_external_data_schedule(str(schema.id)) - except Exception as e: - logger.exception("Could not pause external data schedule", exc_info=e) - - schema.status = ExternalDataSchema.Status.PAUSED - schema.save() - - schema.source.status = ExternalDataSource.Status.PAUSED - schema.source.save() - else: - all_schemas = ExternalDataSchema.objects.filter(team_id=team_id, status=ExternalDataSchema.Status.PAUSED) - for schema in all_schemas: - try: - unpause_external_data_schedule(str(schema.id)) - except Exception as e: - logger.exception("Could not unpause external data schedule", exc_info=e) - - schema.status = ExternalDataSchema.Status.COMPLETED - schema.save() - - schema.source.status = ExternalDataSource.Status.RUNNING - schema.source.save() - - @shared_task(ignore_result=True) def capture_workspace_rows_synced_by_team(team_id: int) -> None: ph_client = get_ph_client() diff --git a/posthog/temporal/data_imports/__init__.py b/posthog/temporal/data_imports/__init__.py index 2b162efa4c538..e945b483d8e95 100644 --- a/posthog/temporal/data_imports/__init__.py +++ b/posthog/temporal/data_imports/__init__.py @@ -5,6 +5,7 @@ import_data_activity, update_external_data_job_model, check_schedule_activity, + check_billing_limits_activity, ) WORKFLOWS = [ExternalDataJobWorkflow] @@ -15,4 +16,5 @@ import_data_activity, create_source_templates, check_schedule_activity, + check_billing_limits_activity, ] diff --git a/posthog/temporal/data_imports/external_data_job.py b/posthog/temporal/data_imports/external_data_job.py index 76ca85db9be5f..15b0e6a08db1c 100644 --- a/posthog/temporal/data_imports/external_data_job.py +++ b/posthog/temporal/data_imports/external_data_job.py @@ -1,14 +1,16 @@ import dataclasses import datetime as dt import json -import uuid -from asgiref.sync import sync_to_async from temporalio import activity, exceptions, workflow from temporalio.common import RetryPolicy # TODO: remove dependency from posthog.temporal.batch_exports.base import PostHogWorkflow +from posthog.temporal.data_imports.workflow_activities.check_billing_limits import ( + CheckBillingLimitsActivityInputs, + check_billing_limits_activity, +) from posthog.temporal.utils import ExternalDataWorkflowInputs from posthog.temporal.data_imports.workflow_activities.create_job_model import ( CreateExternalDataJobModelActivityInputs, @@ -24,7 +26,7 @@ from posthog.warehouse.data_load.source_templates import create_warehouse_templates_for_source from posthog.warehouse.external_data_source.jobs import ( - update_external_job_status, + aupdate_external_job_status, ) from posthog.warehouse.models import ( ExternalDataJob, @@ -67,8 +69,8 @@ async def update_external_data_job_model(inputs: UpdateExternalDataJobStatusInpu logger.info("Schema has a non-retryable error - turning off syncing") await aupdate_should_sync(schema_id=inputs.schema_id, team_id=inputs.team_id, should_sync=False) - await sync_to_async(update_external_job_status)( - run_id=uuid.UUID(inputs.id), + await aupdate_external_job_status( + job_id=inputs.id, status=inputs.status, latest_error=inputs.latest_error, team_id=inputs.team_id, @@ -151,7 +153,7 @@ async def run(self, inputs: ExternalDataWorkflowInputs): ) # TODO: split out the creation of the external data job model from schema getting to seperate out exception handling - run_id, incremental = await workflow.execute_activity( + job_id, incremental = await workflow.execute_activity( create_external_data_job_model_activity, create_external_data_job_inputs, start_to_close_timeout=dt.timedelta(minutes=1), @@ -163,9 +165,24 @@ async def run(self, inputs: ExternalDataWorkflowInputs): ), ) + # Check billing limits + hit_billing_limit = await workflow.execute_activity( + check_billing_limits_activity, + CheckBillingLimitsActivityInputs(job_id=job_id, team_id=inputs.team_id), + start_to_close_timeout=dt.timedelta(minutes=1), + retry_policy=RetryPolicy( + initial_interval=dt.timedelta(seconds=10), + maximum_interval=dt.timedelta(seconds=60), + maximum_attempts=3, + ), + ) + + if hit_billing_limit: + return + update_inputs = UpdateExternalDataJobStatusInputs( - id=run_id, - run_id=run_id, + id=job_id, + run_id=job_id, status=ExternalDataJob.Status.COMPLETED, latest_error=None, internal_error=None, @@ -176,7 +193,7 @@ async def run(self, inputs: ExternalDataWorkflowInputs): try: job_inputs = ImportDataActivityInputs( team_id=inputs.team_id, - run_id=run_id, + run_id=job_id, schema_id=inputs.external_data_schema_id, source_id=inputs.external_data_source_id, ) @@ -197,17 +214,13 @@ async def run(self, inputs: ExternalDataWorkflowInputs): # Create source templates await workflow.execute_activity( create_source_templates, - CreateSourceTemplateInputs(team_id=inputs.team_id, run_id=run_id), + CreateSourceTemplateInputs(team_id=inputs.team_id, run_id=job_id), start_to_close_timeout=dt.timedelta(minutes=10), retry_policy=RetryPolicy(maximum_attempts=2), ) except exceptions.ActivityError as e: - if isinstance(e.cause, exceptions.CancelledError): - update_inputs.status = ExternalDataJob.Status.CANCELLED - else: - update_inputs.status = ExternalDataJob.Status.FAILED - + update_inputs.status = ExternalDataJob.Status.FAILED update_inputs.internal_error = str(e.cause) update_inputs.latest_error = str(e.cause) raise diff --git a/posthog/temporal/data_imports/pipelines/helpers.py b/posthog/temporal/data_imports/pipelines/helpers.py index 776b7f8dd0582..d0cc153f4e11d 100644 --- a/posthog/temporal/data_imports/pipelines/helpers.py +++ b/posthog/temporal/data_imports/pipelines/helpers.py @@ -5,15 +5,6 @@ from posthog.warehouse.util import database_sync_to_async -async def is_job_cancelled( - team_id: int, - job_id: str, -) -> bool: - model = await aget_external_data_job(team_id, job_id) - - return model.status == ExternalDataJob.Status.CANCELLED - - @database_sync_to_async def aget_external_data_job(team_id, job_id): return ExternalDataJob.objects.get(id=job_id, team_id=team_id) diff --git a/posthog/temporal/data_imports/pipelines/rest_source/__init__.py b/posthog/temporal/data_imports/pipelines/rest_source/__init__.py index 5a5d8e8d09ab0..5dceafd1d2aec 100644 --- a/posthog/temporal/data_imports/pipelines/rest_source/__init__.py +++ b/posthog/temporal/data_imports/pipelines/rest_source/__init__.py @@ -23,7 +23,6 @@ from dlt.sources.helpers.rest_client.paginators import BasePaginator from dlt.sources.helpers.rest_client.typing import HTTPMethodBasic -from posthog.temporal.data_imports.pipelines.helpers import is_job_cancelled from .typing import ( ClientConfig, ResolvedParam, @@ -259,9 +258,6 @@ async def paginate_resource( ) -> AsyncGenerator[Iterator[Any], Any]: yield dlt.mark.materialize_table_schema() # type: ignore - if await is_job_cancelled(team_id=team_id, job_id=job_id): - return - if incremental_object: params = _set_incremental_params( params, @@ -315,9 +311,6 @@ async def paginate_dependent_resource( ) -> AsyncGenerator[Any, Any]: yield dlt.mark.materialize_table_schema() # type: ignore - if await is_job_cancelled(team_id=team_id, job_id=job_id): - return - if incremental_object: params = _set_incremental_params( params, diff --git a/posthog/temporal/data_imports/workflow_activities/check_billing_limits.py b/posthog/temporal/data_imports/workflow_activities/check_billing_limits.py new file mode 100644 index 0000000000000..3bce57ef74891 --- /dev/null +++ b/posthog/temporal/data_imports/workflow_activities/check_billing_limits.py @@ -0,0 +1,41 @@ +import dataclasses +from temporalio import activity + +from asgiref.sync import sync_to_async + +from ee.billing.quota_limiting import QuotaLimitingCaches, QuotaResource, list_limited_team_attributes +from posthog.models.team.team import Team +from posthog.temporal.common.logger import bind_temporal_worker_logger +from posthog.warehouse.external_data_source.jobs import aupdate_external_job_status +from posthog.warehouse.models.external_data_job import ExternalDataJob + + +@dataclasses.dataclass +class CheckBillingLimitsActivityInputs: + team_id: int + job_id: str + + +@activity.defn +async def check_billing_limits_activity(inputs: CheckBillingLimitsActivityInputs) -> bool: + logger = await bind_temporal_worker_logger(team_id=inputs.team_id) + + team: Team = await sync_to_async(Team.objects.get)(id=inputs.team_id) + + limited_team_tokens_rows_synced = list_limited_team_attributes( + QuotaResource.ROWS_SYNCED, QuotaLimitingCaches.QUOTA_LIMITER_CACHE_KEY + ) + + if team.api_token in limited_team_tokens_rows_synced: + logger.info("Billing limits hit. Canceling sync") + + await aupdate_external_job_status( + job_id=inputs.job_id, + status=ExternalDataJob.Status.CANCELLED, + latest_error=None, + team_id=inputs.team_id, + ) + + return True + + return False diff --git a/posthog/temporal/data_imports/workflow_activities/create_job_model.py b/posthog/temporal/data_imports/workflow_activities/create_job_model.py index 21f5e046d1a28..5ddcf16160a2c 100644 --- a/posthog/temporal/data_imports/workflow_activities/create_job_model.py +++ b/posthog/temporal/data_imports/workflow_activities/create_job_model.py @@ -32,7 +32,7 @@ async def create_external_data_job_model_activity(inputs: CreateExternalDataJobM logger = await bind_temporal_worker_logger(team_id=inputs.team_id) try: - run = await sync_to_async(create_external_data_job)( + job = await sync_to_async(create_external_data_job)( team_id=inputs.team_id, external_data_source_id=inputs.source_id, external_data_schema_id=inputs.schema_id, @@ -108,7 +108,7 @@ async def create_external_data_job_model_activity(inputs: CreateExternalDataJobM if schema_model is None: raise ValueError(f"Schema with ID {inputs.schema_id} not found") - return str(run.id), schema_model.is_incremental + return str(job.id), schema_model.is_incremental except Exception as e: logger.exception( f"External data job failed on create_external_data_job_model_activity for {str(inputs.source_id)} with error: {e}" diff --git a/posthog/temporal/tests/data_imports/test_end_to_end.py b/posthog/temporal/tests/data_imports/test_end_to_end.py index 0292fe2d83f52..054f5f4a3c471 100644 --- a/posthog/temporal/tests/data_imports/test_end_to_end.py +++ b/posthog/temporal/tests/data_imports/test_end_to_end.py @@ -685,3 +685,46 @@ async def test_postgres_schema_evolution(team, postgres_config, postgres_connect assert any(x == "new_col" for x in columns) assert any(x == "_dlt_id" for x in columns) assert any(x == "_dlt_load_id" for x in columns) + + +@pytest.mark.django_db(transaction=True) +@pytest.mark.asyncio +async def test_billing_limits(team, stripe_customer): + source = await sync_to_async(ExternalDataSource.objects.create)( + source_id=uuid.uuid4(), + connection_id=uuid.uuid4(), + destination_id=uuid.uuid4(), + team=team, + status="running", + source_type="Stripe", + job_inputs={"stripe_secret_key": "test-key", "stripe_account_id": "acct_id"}, + ) + + schema = await sync_to_async(ExternalDataSchema.objects.create)( + name="Customer", + team_id=team.pk, + source_id=source.pk, + sync_type=ExternalDataSchema.SyncType.FULL_REFRESH, + sync_type_config={}, + ) + + workflow_id = str(uuid.uuid4()) + inputs = ExternalDataWorkflowInputs( + team_id=team.id, + external_data_source_id=source.pk, + external_data_schema_id=schema.id, + ) + + with mock.patch( + "posthog.temporal.data_imports.workflow_activities.check_billing_limits.list_limited_team_attributes", + ) as mock_list_limited_team_attributes: + mock_list_limited_team_attributes.return_value = [team.api_token] + + await _execute_run(workflow_id, inputs, stripe_customer["data"]) + + job: ExternalDataJob = await sync_to_async(ExternalDataJob.objects.get)(team_id=team.id, schema_id=schema.pk) + + assert job.status == ExternalDataJob.Status.CANCELLED + + with pytest.raises(Exception): + await sync_to_async(execute_hogql_query)("SELECT * FROM stripe_customer", team) diff --git a/posthog/temporal/tests/external_data/test_external_data_job.py b/posthog/temporal/tests/external_data/test_external_data_job.py index 0c3e1b0001e57..93630571c3a7a 100644 --- a/posthog/temporal/tests/external_data/test_external_data_job.py +++ b/posthog/temporal/tests/external_data/test_external_data_job.py @@ -15,12 +15,12 @@ ExternalDataJobWorkflow, ExternalDataWorkflowInputs, ) +from posthog.temporal.data_imports.workflow_activities.check_billing_limits import check_billing_limits_activity from posthog.temporal.data_imports.workflow_activities.create_job_model import ( CreateExternalDataJobModelActivityInputs, create_external_data_job_model_activity, ) from posthog.temporal.data_imports.workflow_activities.import_data import ImportDataActivityInputs, import_data_activity -from posthog.temporal.tests.data_imports.conftest import stripe_customer from posthog.warehouse.external_data_source.jobs import create_external_data_job from posthog.warehouse.models import ( get_latest_run_if_exists, @@ -539,112 +539,6 @@ def mock_to_object_store_rs_credentials(class_self): assert len(job_2_charge_objects["Contents"]) == 2 -@pytest.mark.django_db(transaction=True) -@pytest.mark.asyncio -async def test_run_stripe_job_cancelled(activity_environment, team, minio_client, **kwargs): - async def setup_job_1(): - new_source = await sync_to_async(ExternalDataSource.objects.create)( - source_id=uuid.uuid4(), - connection_id=uuid.uuid4(), - destination_id=uuid.uuid4(), - team=team, - status="running", - source_type="Stripe", - job_inputs={"stripe_secret_key": "test-key", "stripe_account_id": "acct_id"}, - ) - - customer_schema = await _create_schema("Customer", new_source, team) - - # Already canceled so it should only run once - # This imitates if the job was canceled mid run - new_job: ExternalDataJob = await sync_to_async(ExternalDataJob.objects.create)( - team_id=team.id, - pipeline_id=new_source.pk, - status=ExternalDataJob.Status.CANCELLED, - rows_synced=0, - schema=customer_schema, - ) - - new_job = await sync_to_async( - ExternalDataJob.objects.filter(id=new_job.id).prefetch_related("pipeline").prefetch_related("schema").get - )() - - inputs = ImportDataActivityInputs( - team_id=team.id, - run_id=str(new_job.pk), - source_id=new_source.pk, - schema_id=customer_schema.id, - ) - - return new_job, inputs - - job_1, job_1_inputs = await setup_job_1() - - def mock_customers_paginate( - class_self, - path: str = "", - method: Any = "GET", - params: Optional[dict[str, Any]] = None, - json: Optional[dict[str, Any]] = None, - auth: Optional[Any] = None, - paginator: Optional[Any] = None, - data_selector: Optional[Any] = None, - hooks: Optional[Any] = None, - ): - return iter(stripe_customer()["data"]) - - def mock_to_session_credentials(class_self): - return { - "aws_access_key_id": settings.OBJECT_STORAGE_ACCESS_KEY_ID, - "aws_secret_access_key": settings.OBJECT_STORAGE_SECRET_ACCESS_KEY, - "endpoint_url": settings.OBJECT_STORAGE_ENDPOINT, - "aws_session_token": None, - "AWS_ALLOW_HTTP": "true", - "AWS_S3_ALLOW_UNSAFE_RENAME": "true", - } - - def mock_to_object_store_rs_credentials(class_self): - return { - "aws_access_key_id": settings.OBJECT_STORAGE_ACCESS_KEY_ID, - "aws_secret_access_key": settings.OBJECT_STORAGE_SECRET_ACCESS_KEY, - "endpoint_url": settings.OBJECT_STORAGE_ENDPOINT, - "region": "us-east-1", - "AWS_ALLOW_HTTP": "true", - "AWS_S3_ALLOW_UNSAFE_RENAME": "true", - } - - with ( - mock.patch.object(RESTClient, "paginate", mock_customers_paginate), - override_settings( - BUCKET_URL=f"s3://{BUCKET_NAME}", - AIRBYTE_BUCKET_KEY=settings.OBJECT_STORAGE_ACCESS_KEY_ID, - AIRBYTE_BUCKET_SECRET=settings.OBJECT_STORAGE_SECRET_ACCESS_KEY, - AIRBYTE_BUCKET_REGION="us-east-1", - BUCKET_NAME=BUCKET_NAME, - ), - mock.patch( - "posthog.warehouse.models.table.DataWarehouseTable.get_columns", - return_value={"clickhouse": {"id": "string", "name": "string"}}, - ), - mock.patch.object(AwsCredentials, "to_session_credentials", mock_to_session_credentials), - mock.patch.object(AwsCredentials, "to_object_store_rs_credentials", mock_to_object_store_rs_credentials), - ): - await asyncio.gather( - activity_environment.run(import_data_activity, job_1_inputs), - ) - - folder_path = await sync_to_async(job_1.folder_path)() - job_1_customer_objects = await minio_client.list_objects_v2( - Bucket=BUCKET_NAME, Prefix=f"{folder_path}/customer/" - ) - - # if job was not canceled, this job would run indefinitely - assert len(job_1_customer_objects.get("Contents", [])) == 1 - - await sync_to_async(job_1.refresh_from_db)() - assert job_1.rows_synced == 0 - - @pytest.mark.django_db(transaction=True) @pytest.mark.asyncio async def test_run_stripe_job_row_count_update(activity_environment, team, minio_client, **kwargs): @@ -803,6 +697,7 @@ async def mock_async_func(inputs): update_external_data_job_model, import_data_activity, create_source_templates, + check_billing_limits_activity, ], workflow_runner=UnsandboxedWorkflowRunner(), ): diff --git a/posthog/warehouse/api/external_data_schema.py b/posthog/warehouse/api/external_data_schema.py index 154fd848ff524..3f98702db64f7 100644 --- a/posthog/warehouse/api/external_data_schema.py +++ b/posthog/warehouse/api/external_data_schema.py @@ -46,6 +46,7 @@ class ExternalDataSchemaSerializer(serializers.ModelSerializer): incremental_field = serializers.SerializerMethodField(read_only=True) incremental_field_type = serializers.SerializerMethodField(read_only=True) sync_frequency = serializers.SerializerMethodField(read_only=True) + status = serializers.SerializerMethodField(read_only=True) class Meta: model = ExternalDataSchema @@ -74,6 +75,12 @@ class Meta: "status", ] + def get_status(self, schema: ExternalDataSchema) -> str | None: + if schema.status == ExternalDataSchema.Status.CANCELLED: + return "Billing limits" + + return schema.status + def get_incremental(self, schema: ExternalDataSchema) -> bool: return schema.is_incremental diff --git a/posthog/warehouse/api/external_data_source.py b/posthog/warehouse/api/external_data_source.py index 54a3960f0960a..2e3f66de9c630 100644 --- a/posthog/warehouse/api/external_data_source.py +++ b/posthog/warehouse/api/external_data_source.py @@ -89,6 +89,7 @@ def get_generic_sql_error(source_type: ExternalDataSource.Type): class ExternalDataJobSerializers(serializers.ModelSerializer): schema = serializers.SerializerMethodField(read_only=True) + status = serializers.SerializerMethodField(read_only=True) class Meta: model = ExternalDataJob @@ -113,6 +114,12 @@ class Meta: "workflow_run_id", ] + def get_status(self, instance: ExternalDataJob): + if instance.status == ExternalDataJob.Status.CANCELLED: + return "Billing limits" + + return instance.status + def get_schema(self, instance: ExternalDataJob): return SimpleExternalDataSchemaSerializer( instance.schema, many=False, read_only=True, context=self.context @@ -167,7 +174,7 @@ def get_status(self, instance: ExternalDataSource) -> str: if any_failures: return ExternalDataSchema.Status.ERROR elif any_cancelled: - return ExternalDataSchema.Status.CANCELLED + return "Billing limits" elif any_paused: return ExternalDataSchema.Status.PAUSED elif any_running: diff --git a/posthog/warehouse/external_data_source/jobs.py b/posthog/warehouse/external_data_source/jobs.py index 0bfbd95760391..27d2ae22b6b8d 100644 --- a/posthog/warehouse/external_data_source/jobs.py +++ b/posthog/warehouse/external_data_source/jobs.py @@ -1,5 +1,5 @@ from uuid import UUID - +from posthog.warehouse.util import database_sync_to_async from posthog.warehouse.models.external_data_job import ExternalDataJob from posthog.warehouse.models.external_data_schema import ExternalDataSchema from posthog.warehouse.models.external_data_source import ExternalDataSource @@ -29,16 +29,19 @@ def create_external_data_job( return job -def update_external_job_status(run_id: UUID, team_id: int, status: str, latest_error: str | None) -> ExternalDataJob: - model = ExternalDataJob.objects.get(id=run_id, team_id=team_id) +@database_sync_to_async +def aupdate_external_job_status( + job_id: str, team_id: int, status: ExternalDataJob.Status, latest_error: str | None +) -> ExternalDataJob: + model = ExternalDataJob.objects.get(id=job_id, team_id=team_id) model.status = status model.latest_error = latest_error model.save() if status == ExternalDataJob.Status.FAILED: - schema_status = ExternalDataSchema.Status.ERROR + schema_status: ExternalDataSchema.Status = ExternalDataSchema.Status.ERROR else: - schema_status = status + schema_status = status # type: ignore schema = ExternalDataSchema.objects.get(id=model.schema_id, team_id=team_id) schema.status = schema_status From 11ea6b690d27373cf592af72779e5a4b93c9254b Mon Sep 17 00:00:00 2001 From: Ben White Date: Wed, 4 Sep 2024 16:26:43 +0200 Subject: [PATCH 06/32] fix(cdp): Check for error status before enqueueing (#24783) --- plugin-server/src/cdp/cdp-consumers.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/plugin-server/src/cdp/cdp-consumers.ts b/plugin-server/src/cdp/cdp-consumers.ts index 984cd03a23cfd..16eff91ceeb0f 100644 --- a/plugin-server/src/cdp/cdp-consumers.ts +++ b/plugin-server/src/cdp/cdp-consumers.ts @@ -246,15 +246,6 @@ abstract class CdpConsumerBase { await Promise.all( results.map(async (result) => { // Tricky: We want to pull all the logs out as we don't want them to be passed around to any subsequent functions - if (result.finished || result.error) { - this.produceAppMetric({ - team_id: result.invocation.teamId, - app_source_id: result.invocation.hogFunction.id, - metric_kind: result.error ? 'failure' : 'success', - metric_name: result.error ? 'failed' : 'succeeded', - count: 1, - }) - } this.produceLogs(result) @@ -274,8 +265,16 @@ abstract class CdpConsumerBase { }) } - if (!result.finished) { - // If it isn't finished then we need to put it back on the queue + if (result.finished || result.error) { + this.produceAppMetric({ + team_id: result.invocation.teamId, + app_source_id: result.invocation.hogFunction.id, + metric_kind: result.error ? 'failure' : 'success', + metric_name: result.error ? 'failed' : 'succeeded', + count: 1, + }) + } else { + // Means there is follow up so we enqueue it await this.queueInvocation(result.invocation) } }) From 27438d6d6d4e24d3428b02fe026e89ff00387a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Far=C3=ADas=20Santana?= Date: Wed, 4 Sep 2024 17:23:53 +0200 Subject: [PATCH 07/32] refactor(data-modeling): Ancestors and descendants API changes (#24781) --- posthog/warehouse/api/saved_query.py | 34 +++++----- .../warehouse/api/test/test_saved_query.py | 67 +++++++++++++++++-- 2 files changed, 78 insertions(+), 23 deletions(-) diff --git a/posthog/warehouse/api/saved_query.py b/posthog/warehouse/api/saved_query.py index db437861f967a..0c233001af365 100644 --- a/posthog/warehouse/api/saved_query.py +++ b/posthog/warehouse/api/saved_query.py @@ -160,25 +160,25 @@ def ancestors(self, request: request.Request, *args, **kwargs) -> response.Respo look further back into the ancestor tree. If `level` overshoots (i.e. points to only ancestors beyond the root), we return an empty list. """ - level = request.data.get("level", 1) + up_to_level = request.data.get("level", None) saved_query = self.get_object() saved_query_id = saved_query.id.hex - lquery = f"*{{{level},}}.{saved_query_id}" + lquery = f"*{{1,}}.{saved_query_id}" paths = DataWarehouseModelPath.objects.filter(team=saved_query.team, path__lquery=lquery) if not paths: return response.Response({"ancestors": []}) - ancestors = set() + ancestors: set[str] = set() for model_path in paths: - offset = len(model_path.path) - level - 1 # -1 corrects for level being 1-indexed + if up_to_level is None: + start = 0 + else: + start = (int(up_to_level) * -1) - 1 - if offset < 0: - continue - - ancestors.add(model_path.path[offset]) + ancestors = ancestors.union(model_path.path[start:-1]) return response.Response({"ancestors": ancestors}) @@ -190,25 +190,25 @@ def descendants(self, request: request.Request, *args, **kwargs) -> response.Res look further ahead into the descendants tree. If `level` overshoots (i.e. points to only descendants further than a leaf), we return an empty list. """ - level = request.data.get("level", 1) + up_to_level = request.data.get("level", None) saved_query = self.get_object() saved_query_id = saved_query.id.hex - lquery = f"*.{saved_query_id}.*{{{level},}}" + lquery = f"*.{saved_query_id}.*{{1,}}" paths = DataWarehouseModelPath.objects.filter(team=saved_query.team, path__lquery=lquery) if not paths: return response.Response({"descendants": []}) - descendants = set() - + descendants: set[str] = set() for model_path in paths: - offset = model_path.path.index(saved_query_id) + level - - if offset > len(model_path.path): - continue + start = model_path.path.index(saved_query_id) + 1 + if up_to_level is None: + end = len(model_path.path) + else: + end = start + up_to_level - descendants.add(model_path.path[offset]) + descendants = descendants.union(model_path.path[start:end]) return response.Response({"descendants": descendants}) diff --git a/posthog/warehouse/api/test/test_saved_query.py b/posthog/warehouse/api/test/test_saved_query.py index 80deaad72ca3a..a0abdf02c5e98 100644 --- a/posthog/warehouse/api/test/test_saved_query.py +++ b/posthog/warehouse/api/test/test_saved_query.py @@ -230,24 +230,33 @@ def test_ancestors(self): self.assertEqual(response.status_code, 200, response.content) child_ancestors = response.json()["ancestors"] - self.assertEqual(child_ancestors, [uuid.UUID(saved_query_parent_id).hex]) + child_ancestors.sort() + self.assertEqual(child_ancestors, sorted([uuid.UUID(saved_query_parent_id).hex, "events", "persons"])) response = self.client.post( - f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_child_id}/ancestors", {"level": 2} + f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_child_id}/ancestors", {"level": 1} ) + self.assertEqual(response.status_code, 200, response.content) + child_ancestors_level_1 = response.json()["ancestors"] + child_ancestors_level_1.sort() + self.assertEqual(child_ancestors_level_1, [uuid.UUID(saved_query_parent_id).hex]) + + response = self.client.post( + f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_child_id}/ancestors", {"level": 2} + ) self.assertEqual(response.status_code, 200, response.content) child_ancestors_level_2 = response.json()["ancestors"] child_ancestors_level_2.sort() - self.assertEqual(child_ancestors_level_2, ["events", "persons"]) + self.assertEqual(child_ancestors_level_2, sorted([uuid.UUID(saved_query_parent_id).hex, "events", "persons"])) response = self.client.post( f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_child_id}/ancestors", {"level": 10} ) - self.assertEqual(response.status_code, 200, response.content) child_ancestors_level_10 = response.json()["ancestors"] - self.assertEqual(child_ancestors_level_10, []) + child_ancestors_level_10.sort() + self.assertEqual(child_ancestors_level_2, sorted([uuid.UUID(saved_query_parent_id).hex, "events", "persons"])) def test_descendants(self): query = """\ @@ -281,23 +290,69 @@ def test_descendants(self): }, ) + response_grand_child = self.client.post( + f"/api/projects/{self.team.id}/warehouse_saved_queries/", + { + "name": "event_view_3", + "query": { + "kind": "HogQLQuery", + "query": "select event as event from event_view_2", + }, + }, + ) + self.assertEqual(response_parent.status_code, 201, response_parent.content) self.assertEqual(response_child.status_code, 201, response_child.content) + self.assertEqual(response_grand_child.status_code, 201, response_grand_child.content) saved_query_parent_id = response_parent.json()["id"] saved_query_child_id = response_child.json()["id"] + saved_query_grand_child_id = response_grand_child.json()["id"] response = self.client.post( f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_parent_id}/descendants", ) self.assertEqual(response.status_code, 200, response.content) parent_descendants = response.json()["descendants"] - self.assertEqual(parent_descendants, [uuid.UUID(saved_query_child_id).hex]) + self.assertEqual( + sorted(parent_descendants), + sorted([uuid.UUID(saved_query_child_id).hex, uuid.UUID(saved_query_grand_child_id).hex]), + ) + + response = self.client.post( + f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_parent_id}/descendants", {"level": 1} + ) + + self.assertEqual(response.status_code, 200, response.content) + parent_descendants_level_1 = response.json()["descendants"] + self.assertEqual( + parent_descendants_level_1, + [uuid.UUID(saved_query_child_id).hex], + ) + + response = self.client.post( + f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_parent_id}/descendants", {"level": 2} + ) + + self.assertEqual(response.status_code, 200, response.content) + parent_descendants_level_2 = response.json()["descendants"] + self.assertEqual( + sorted(parent_descendants_level_2), + sorted([uuid.UUID(saved_query_child_id).hex, uuid.UUID(saved_query_grand_child_id).hex]), + ) response = self.client.post( f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_child_id}/descendants", ) + self.assertEqual(response.status_code, 200, response.content) + child_ancestors = response.json()["descendants"] + self.assertEqual(child_ancestors, [uuid.UUID(saved_query_grand_child_id).hex]) + + response = self.client.post( + f"/api/projects/{self.team.id}/warehouse_saved_queries/{saved_query_grand_child_id}/descendants", + ) + self.assertEqual(response.status_code, 200, response.content) child_ancestors = response.json()["descendants"] self.assertEqual(child_ancestors, []) From a5f1deb3f1bf247b04a70c6e0aa06cdca34d7968 Mon Sep 17 00:00:00 2001 From: Tom Owers Date: Wed, 4 Sep 2024 16:25:21 +0100 Subject: [PATCH 08/32] chore(data-warehouse): Added error messages on components other than table (#24779) --- .../DataVisualization/DataVisualization.tsx | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/frontend/src/queries/nodes/DataVisualization/DataVisualization.tsx b/frontend/src/queries/nodes/DataVisualization/DataVisualization.tsx index c1d66c0d78583..8bbce53ef67ed 100644 --- a/frontend/src/queries/nodes/DataVisualization/DataVisualization.tsx +++ b/frontend/src/queries/nodes/DataVisualization/DataVisualization.tsx @@ -9,6 +9,7 @@ import { AnimationType } from 'lib/animations/animations' import { Animation } from 'lib/components/Animation/Animation' import { useCallback, useState } from 'react' import { DatabaseTableTreeWithItems } from 'scenes/data-warehouse/external/DataWarehouseTables' +import { InsightErrorState } from 'scenes/insights/EmptyStates' import { HogQLBoldNumber } from 'scenes/insights/views/BoldNumber/BoldNumber' import { urls } from 'scenes/urls' @@ -104,6 +105,8 @@ function InternalDataTableVisualization(props: DataTableVisualizationProps): JSX sourceFeatures, response, responseLoading, + responseError, + queryCancelled, isChartSettingsPanelOpen, } = useValues(dataVisualizationLogic) @@ -202,7 +205,27 @@ function InternalDataTableVisualization(props: DataTableVisualizationProps): JSX 'pt-[46px]': showEditingUI, })} > - {component} + {visualizationType !== ChartDisplayType.ActionsTable && responseError ? ( +
+ +
+ ) : ( + component + )}
From 049f4cadbada589888a2a697c8ca17f03c558ff7 Mon Sep 17 00:00:00 2001 From: Arthur Silber Date: Wed, 4 Sep 2024 17:37:01 +0200 Subject: [PATCH 09/32] chore: fix hobby plugin server, again (#24750) (#24777) --- docker-compose.hobby.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.hobby.yml b/docker-compose.hobby.yml index 0b00d510ad754..7df84ca8035cd 100644 --- a/docker-compose.hobby.yml +++ b/docker-compose.hobby.yml @@ -121,6 +121,7 @@ services: OBJECT_STORAGE_ENDPOINT: http://objectstorage:19000 OBJECT_STORAGE_ENABLED: true CDP_REDIS_HOST: redis7 + CDP_REDIS_PORT: 6379 depends_on: - db - redis From 04ef4039cbb863e9aa2be5c6b6036e078970833f Mon Sep 17 00:00:00 2001 From: Ben White Date: Wed, 4 Sep 2024 17:47:09 +0200 Subject: [PATCH 10/32] fix(cdp): Fixed serialization to not include the hog function (#24785) --- plugin-server/src/cdp/cdp-consumers.ts | 31 ++++++++++++++----------- plugin-server/src/cdp/fetch-executor.ts | 4 ++-- plugin-server/src/cdp/utils.ts | 11 +++++++++ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/plugin-server/src/cdp/cdp-consumers.ts b/plugin-server/src/cdp/cdp-consumers.ts index 16eff91ceeb0f..499b030e61564 100644 --- a/plugin-server/src/cdp/cdp-consumers.ts +++ b/plugin-server/src/cdp/cdp-consumers.ts @@ -44,6 +44,7 @@ import { createInvocation, gzipObject, prepareLogEntriesForClickhouse, + serializeInvocation, unGzipObject, } from './utils' @@ -217,12 +218,7 @@ abstract class CdpConsumerBase { // For now we just enqueue to kafka // For kafka style this is overkill to enqueue this way but it simplifies migrating to the new system - const serializedInvocation: HogFunctionInvocationSerialized = { - ...invocation, - hogFunctionId: invocation.hogFunction.id, - } - - delete (serializedInvocation as any).hogFunction + const serializedInvocation = serializeInvocation(invocation) const request: HogFunctionInvocationSerializedCompressed = { state: await gzipObject(serializedInvocation), @@ -233,7 +229,7 @@ abstract class CdpConsumerBase { this.messagesToProduce.push({ topic: KAFKA_CDP_FUNCTION_CALLBACKS, value: request, - key: invocation.hogFunction.id, + key: `${invocation.hogFunction.id}:${invocation.id}`, }) } @@ -552,8 +548,15 @@ export class CdpFunctionCallbackConsumer extends CdpConsumerBase { // NOTE: In the future this service will never do fetching (unless we decide we want to do it in node at some point) // This is just "for now" to support the transition to cyclotron const fetchQueue = invocations.filter((item) => item.queue === 'fetch') - const fetchResults = await this.runManyWithHeartbeat(fetchQueue, (item) => - this.fetchExecutor.execute(item) + + const fetchResults = await Promise.all( + fetchQueue.map((item) => { + return runInstrumentedFunction({ + statsKey: `cdpConsumer.handleEachBatch.fetchExecutor.execute`, + func: () => this.fetchExecutor.execute(item), + timeout: 1000, + }) + }) ) const hogQueue = invocations.filter((item) => item.queue === 'hog') @@ -604,11 +607,11 @@ export class CdpFunctionCallbackConsumer extends CdpConsumerBase { invocationSerialized.queueParameters = item.asyncFunctionResponse } - const hogFunction = - invocationSerialized.hogFunction ?? - (invocationSerialized.hogFunctionId - ? this.hogFunctionManager.getHogFunction(invocationSerialized.hogFunctionId) - : undefined) + const hogFunctionId = + invocationSerialized.hogFunctionId ?? invocationSerialized.hogFunction?.id + const hogFunction = hogFunctionId + ? this.hogFunctionManager.getHogFunction(hogFunctionId) + : undefined if (!hogFunction) { status.error('Error finding hog function', { diff --git a/plugin-server/src/cdp/fetch-executor.ts b/plugin-server/src/cdp/fetch-executor.ts index b2e99ef0a1836..89900215ec1fd 100644 --- a/plugin-server/src/cdp/fetch-executor.ts +++ b/plugin-server/src/cdp/fetch-executor.ts @@ -12,7 +12,7 @@ import { HogFunctionQueueParametersFetchRequest, HogFunctionQueueParametersFetchResponse, } from './types' -import { gzipObject } from './utils' +import { gzipObject, serializeInvocation } from './utils' export const BUCKETS_KB_WRITTEN = [0, 128, 512, 1024, 2024, 4096, 10240, Infinity] @@ -52,7 +52,7 @@ export class FetchExecutor { if (this.hogHookEnabledForTeams(invocation.teamId)) { // This is very temporary until we are commited to Cyclotron const payload: HogFunctionInvocationAsyncRequest = { - state: await gzipObject(invocation), + state: await gzipObject(serializeInvocation(invocation)), teamId: invocation.teamId, hogFunctionId: invocation.hogFunction.id, asyncFunctionRequest: { diff --git a/plugin-server/src/cdp/utils.ts b/plugin-server/src/cdp/utils.ts index da1d64273f7aa..158814718dc0a 100644 --- a/plugin-server/src/cdp/utils.ts +++ b/plugin-server/src/cdp/utils.ts @@ -12,6 +12,7 @@ import { HogFunctionInvocation, HogFunctionInvocationGlobals, HogFunctionInvocationResult, + HogFunctionInvocationSerialized, HogFunctionLogEntrySerialized, HogFunctionType, ParsedClickhouseEvent, @@ -224,3 +225,13 @@ export function createInvocation( timings: [], } } + +export function serializeInvocation(invocation: HogFunctionInvocation): HogFunctionInvocationSerialized { + const serializedInvocation: HogFunctionInvocationSerialized = { + ...invocation, + hogFunctionId: invocation.hogFunction.id, + } + + delete (serializedInvocation as any).hogFunction + return invocation +} From 8b3aeb236eb37c99db72389c10af36f03cd5d023 Mon Sep 17 00:00:00 2001 From: Tom Owers Date: Wed, 4 Sep 2024 17:06:29 +0100 Subject: [PATCH 11/32] fix(data-warehouse): Exclude rows missing the cursor path of incremental value (#24782) --- .../pipelines/sql_database/__init__.py | 38 ++++---- .../pipelines/sql_database/helpers.py | 10 ++- .../tests/data_imports/test_end_to_end.py | 90 +++++++++++++++++++ posthog/warehouse/types.py | 4 +- 4 files changed, 120 insertions(+), 22 deletions(-) diff --git a/posthog/temporal/data_imports/pipelines/sql_database/__init__.py b/posthog/temporal/data_imports/pipelines/sql_database/__init__.py index 0fc7f7394b6ad..900c70d3b56c6 100644 --- a/posthog/temporal/data_imports/pipelines/sql_database/__init__.py +++ b/posthog/temporal/data_imports/pipelines/sql_database/__init__.py @@ -173,24 +173,26 @@ def sql_database( # and pass them in here to get empty table materialization binary_columns_to_drop = get_binary_columns(engine, schema or "", table.name) - yield dlt.resource( - table_rows, - name=table.name, - primary_key=get_primary_key(table), - merge_key=get_primary_key(table), - write_disposition={ - "disposition": "merge", - "strategy": "upsert", - } - if incremental - else "replace", - spec=SqlDatabaseTableConfiguration, - table_format="delta", - columns=get_column_hints(engine, schema or "", table.name), - ).add_map(remove_columns(binary_columns_to_drop, team_id))( - engine=engine, - table=table, - incremental=incremental, + yield ( + dlt.resource( + table_rows, + name=table.name, + primary_key=get_primary_key(table), + merge_key=get_primary_key(table), + write_disposition={ + "disposition": "merge", + "strategy": "upsert", + } + if incremental + else "replace", + spec=SqlDatabaseTableConfiguration, + table_format="delta", + columns=get_column_hints(engine, schema or "", table.name), + ).add_map(remove_columns(binary_columns_to_drop, team_id))( + engine=engine, + table=table, + incremental=incremental, + ) ) diff --git a/posthog/temporal/data_imports/pipelines/sql_database/helpers.py b/posthog/temporal/data_imports/pipelines/sql_database/helpers.py index 894407beda8a0..d877effb3e374 100644 --- a/posthog/temporal/data_imports/pipelines/sql_database/helpers.py +++ b/posthog/temporal/data_imports/pipelines/sql_database/helpers.py @@ -54,10 +54,16 @@ def make_query(self) -> Select[Any]: last_value_func = self.incremental.last_value_func if last_value_func is max: # Query ordered and filtered according to last_value function order_by = self.cursor_column.asc() # type: ignore - filter_op = operator.gt + if self.last_value == self.incremental.initial_value: + filter_op = operator.ge + else: + filter_op = operator.gt elif last_value_func is min: order_by = self.cursor_column.desc() # type: ignore - filter_op = operator.lt + if self.last_value == self.incremental.initial_value: + filter_op = operator.le + else: + filter_op = operator.lt else: # Custom last_value, load everything and let incremental handle filtering return query query = query.order_by(order_by) diff --git a/posthog/temporal/tests/data_imports/test_end_to_end.py b/posthog/temporal/tests/data_imports/test_end_to_end.py index 054f5f4a3c471..8556ff7bf1c5c 100644 --- a/posthog/temporal/tests/data_imports/test_end_to_end.py +++ b/posthog/temporal/tests/data_imports/test_end_to_end.py @@ -687,6 +687,96 @@ async def test_postgres_schema_evolution(team, postgres_config, postgres_connect assert any(x == "_dlt_load_id" for x in columns) +@pytest.mark.django_db(transaction=True) +@pytest.mark.asyncio +async def test_sql_database_missing_incremental_values(team, postgres_config, postgres_connection): + await postgres_connection.execute( + "CREATE TABLE IF NOT EXISTS {schema}.test_table (id integer)".format(schema=postgres_config["schema"]) + ) + await postgres_connection.execute( + "INSERT INTO {schema}.test_table (id) VALUES (1)".format(schema=postgres_config["schema"]) + ) + await postgres_connection.execute( + "INSERT INTO {schema}.test_table (id) VALUES (null)".format(schema=postgres_config["schema"]) + ) + await postgres_connection.commit() + + await _run( + team=team, + schema_name="test_table", + table_name="postgres_test_table", + source_type="Postgres", + job_inputs={ + "host": postgres_config["host"], + "port": postgres_config["port"], + "database": postgres_config["database"], + "user": postgres_config["user"], + "password": postgres_config["password"], + "schema": postgres_config["schema"], + "ssh_tunnel_enabled": "False", + }, + mock_data_response=[], + sync_type=ExternalDataSchema.SyncType.INCREMENTAL, + sync_type_config={"incremental_field": "id", "incremental_field_type": "integer"}, + ) + + res = await sync_to_async(execute_hogql_query)("SELECT * FROM postgres_test_table", team) + columns = res.columns + + assert columns is not None + assert len(columns) == 3 + assert any(x == "id" for x in columns) + assert any(x == "_dlt_id" for x in columns) + assert any(x == "_dlt_load_id" for x in columns) + + # Exclude rows that don't have the incremental cursor key set + assert len(res.results) == 1 + + +@pytest.mark.django_db(transaction=True) +@pytest.mark.asyncio +async def test_sql_database_incremental_initual_value(team, postgres_config, postgres_connection): + await postgres_connection.execute( + "CREATE TABLE IF NOT EXISTS {schema}.test_table (id integer)".format(schema=postgres_config["schema"]) + ) + # Setting `id` to `0` - the same as an `integer` incremental initial value + await postgres_connection.execute( + "INSERT INTO {schema}.test_table (id) VALUES (0)".format(schema=postgres_config["schema"]) + ) + await postgres_connection.commit() + + await _run( + team=team, + schema_name="test_table", + table_name="postgres_test_table", + source_type="Postgres", + job_inputs={ + "host": postgres_config["host"], + "port": postgres_config["port"], + "database": postgres_config["database"], + "user": postgres_config["user"], + "password": postgres_config["password"], + "schema": postgres_config["schema"], + "ssh_tunnel_enabled": "False", + }, + mock_data_response=[], + sync_type=ExternalDataSchema.SyncType.INCREMENTAL, + sync_type_config={"incremental_field": "id", "incremental_field_type": "integer"}, + ) + + res = await sync_to_async(execute_hogql_query)("SELECT * FROM postgres_test_table", team) + columns = res.columns + + assert columns is not None + assert len(columns) == 3 + assert any(x == "id" for x in columns) + assert any(x == "_dlt_id" for x in columns) + assert any(x == "_dlt_load_id" for x in columns) + + # Include rows that have the same incremental value as the `initial_value` + assert len(res.results) == 1 + + @pytest.mark.django_db(transaction=True) @pytest.mark.asyncio async def test_billing_limits(team, stripe_customer): diff --git a/posthog/warehouse/types.py b/posthog/warehouse/types.py index 57455ac361232..910367854f23c 100644 --- a/posthog/warehouse/types.py +++ b/posthog/warehouse/types.py @@ -1,8 +1,8 @@ -from enum import Enum +from enum import StrEnum from typing import TypedDict -class IncrementalFieldType(Enum): +class IncrementalFieldType(StrEnum): Integer = "integer" Numeric = "numeric" # For snowflake DateTime = "datetime" From 025f01929458c3e11ac81761fd5f3a2036a0467d Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Wed, 4 Sep 2024 18:33:11 +0200 Subject: [PATCH 12/32] feat(insights): generate trends using GenAI (#24463) Co-authored-by: Georgiy Tarasov Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Anirudh Pillai --- .github/workflows/rust-docker-build.yml | 4 +- ee/hogai/__init__.py | 0 ee/hogai/generate_trends_agent.py | 55 + ee/hogai/hardcoded_definitions.py | 1027 +++++++++++++++++ ee/hogai/system_prompt.py | 77 ++ ee/hogai/team_prompt.py | 137 +++ ee/hogai/trends_function.py | 71 ++ .../components-command-bar--actions--dark.png | Bin 21064 -> 19746 bytes ...components-command-bar--actions--light.png | Bin 20858 -> 19508 bytes .../components-command-bar--search--dark.png | Bin 54278 -> 54363 bytes .../components-command-bar--search--light.png | Bin 53449 -> 53477 bytes ...es-other-settings--settings-user--dark.png | Bin 228232 -> 234745 bytes ...s-other-settings--settings-user--light.png | Bin 228680 -> 235142 bytes .../navigation-3000/navigationLogic.tsx | 10 + frontend/src/lib/api.ts | 13 + .../components/CommandBar/ActionResult.tsx | 2 +- .../components/CommandBar/ActionResults.tsx | 2 +- .../components/CommandBar/SearchResult.tsx | 2 +- .../src/lib/components/CommandBar/index.scss | 6 +- .../HedgehogBuddy/HedgehogBuddy.tsx | 8 +- .../HedgehogBuddy/HedgehogBuddyRender.tsx | 58 +- .../HedgehogBuddy/sprites/sprites.tsx | 2 +- .../lib/lemon-ui/LemonInput/LemonInput.scss | 8 + .../lib/lemon-ui/LemonInput/LemonInput.tsx | 2 +- frontend/src/lib/lemon-ui/icons/categories.ts | 1 + frontend/src/queries/schema.json | 214 ++++ frontend/src/queries/schema.ts | 76 ++ frontend/src/scenes/appScenes.ts | 1 + frontend/src/scenes/max/Max.scss | 3 + frontend/src/scenes/max/Max.tsx | 157 +++ frontend/src/scenes/max/maxLogic.ts | 164 +++ frontend/src/scenes/sceneTypes.ts | 1 + frontend/src/scenes/scenes.ts | 9 +- frontend/src/scenes/urls.ts | 1 + package.json | 2 +- pnpm-lock.yaml | 14 +- posthog/api/query.py | 49 +- .../api/test/__snapshots__/test_api_docs.ambr | 1 + posthog/schema.py | 125 ++ requirements-dev.in | 2 +- requirements-dev.txt | 18 +- requirements.in | 9 +- requirements.txt | 51 +- 43 files changed, 2328 insertions(+), 54 deletions(-) create mode 100644 ee/hogai/__init__.py create mode 100644 ee/hogai/generate_trends_agent.py create mode 100644 ee/hogai/hardcoded_definitions.py create mode 100644 ee/hogai/system_prompt.py create mode 100644 ee/hogai/team_prompt.py create mode 100644 ee/hogai/trends_function.py create mode 100644 frontend/src/scenes/max/Max.scss create mode 100644 frontend/src/scenes/max/Max.tsx create mode 100644 frontend/src/scenes/max/maxLogic.ts diff --git a/.github/workflows/rust-docker-build.yml b/.github/workflows/rust-docker-build.yml index 3a4104b02ff2a..a677ed818f3a5 100644 --- a/.github/workflows/rust-docker-build.yml +++ b/.github/workflows/rust-docker-build.yml @@ -95,8 +95,8 @@ jobs: - name: Container image digest id: digest run: | - echo ${{ steps.docker_build.outputs.digest }} - echo "${{matrix.image}}_digest=${{ steps.docker_build.outputs.digest }}" >> $GITHUB_OUTPUT + echo ${{ steps.docker_build.outputs.digest }} + echo "${{matrix.image}}_digest=${{ steps.docker_build.outputs.digest }}" >> $GITHUB_OUTPUT deploy: name: Deploy capture-replay diff --git a/ee/hogai/__init__.py b/ee/hogai/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ee/hogai/generate_trends_agent.py b/ee/hogai/generate_trends_agent.py new file mode 100644 index 0000000000000..9980ff82dbeba --- /dev/null +++ b/ee/hogai/generate_trends_agent.py @@ -0,0 +1,55 @@ +from typing import Literal, Optional + +from langchain_core.output_parsers.openai_tools import PydanticToolsParser +from langchain_core.prompts import ChatPromptTemplate +from langchain_openai import ChatOpenAI +from pydantic import BaseModel, Field + +from ee.hogai.system_prompt import trends_system_prompt +from ee.hogai.team_prompt import TeamPrompt +from ee.hogai.trends_function import TrendsFunction +from posthog.models.team.team import Team +from posthog.schema import ExperimentalAITrendsQuery + + +class output_insight_schema(BaseModel): + reasoning_steps: Optional[list[str]] = None + answer: ExperimentalAITrendsQuery + + +class ChatMessage(BaseModel): + role: Literal["user", "assistant"] + content: str = Field(..., max_length=2500) + + +class Conversation(BaseModel): + messages: list[ChatMessage] = Field(..., max_length=20) + session_id: str + + +class GenerateTrendsAgent: + _team: Team + + def __init__(self, team: Team): + self._team = team + + def bootstrap(self, messages: list[ChatMessage], user_prompt: str | None = None): + llm = ChatOpenAI(model="gpt-4o-2024-08-06", stream_usage=True).bind_tools( + [TrendsFunction().generate_function()], tool_choice="output_insight_schema" + ) + user_prompt = ( + user_prompt + or "Answer to my question:\n{{question}}\n" + TeamPrompt(self._team).generate_prompt() + ) + + prompts = ChatPromptTemplate.from_messages( + [ + ("system", trends_system_prompt), + ("user", user_prompt), + *[(message.role, message.content) for message in messages[1:]], + ], + template_format="mustache", + ) + + chain = prompts | llm | PydanticToolsParser(tools=[output_insight_schema]) # type: ignore + return chain diff --git a/ee/hogai/hardcoded_definitions.py b/ee/hogai/hardcoded_definitions.py new file mode 100644 index 0000000000000..ee13c49c3ca63 --- /dev/null +++ b/ee/hogai/hardcoded_definitions.py @@ -0,0 +1,1027 @@ +hardcoded_prop_defs: dict = { + "events": { + "": { + "label": "All events", + "description": "This is a wildcard that matches all events.", + }, + "$pageview": { + "label": "Pageview", + "description": "When a user loads (or reloads) a page.", + }, + "$pageleave": { + "label": "Pageleave", + "description": "When a user leaves a page.", + }, + "$autocapture": { + "label": "Autocapture", + "description": "User interactions that were automatically captured.", + "examples": ["clicked button"], + }, + "$copy_autocapture": { + "label": "Clipboard autocapture", + "description": "Selected text automatically captured when a user copies or cuts.", + }, + "$screen": { + "label": "Screen", + "description": "When a user loads a screen in a mobile app.", + }, + "$set": { + "label": "Set", + "description": "Setting person properties.", + }, + "$opt_in": { + "label": "Opt In", + "description": "When a user opts into analytics.", + }, + "$feature_flag_called": { + "label": "Feature Flag Called", + "description": ( + 'The feature flag that was called.\n\nWarning! This only works in combination with the $feature_flag event. If you want to filter other events, try "Active Feature Flags".' + ), + "examples": ["beta-feature"], + }, + "$feature_view": { + "label": "Feature View", + "description": "When a user views a feature.", + }, + "$feature_interaction": { + "label": "Feature Interaction", + "description": "When a user interacts with a feature.", + }, + "$capture_metrics": { + "label": "Capture Metrics", + "description": "Metrics captured with values pertaining to your systems at a specific point in time", + }, + "$identify": { + "label": "Identify", + "description": "A user has been identified with properties", + }, + "$create_alias": { + "label": "Alias", + "description": "An alias ID has been added to a user", + }, + "$merge_dangerously": { + "label": "Merge", + "description": "An alias ID has been added to a user", + }, + "$groupidentify": { + "label": "Group Identify", + "description": "A group has been identified with properties", + }, + "$rageclick": { + "label": "Rageclick", + "description": "A user has rapidly and repeatedly clicked in a single place", + }, + "$exception": { + "label": "Exception", + "description": "Automatically captured exceptions from the client Sentry integration", + }, + "$web_vitals": { + "label": "Web vitals", + "description": "Automatically captured web vitals data", + }, + "Application Opened": { + "label": "Application Opened", + "description": "When a user opens the app either for the first time or from the foreground.", + }, + "Application Backgrounded": { + "label": "Application Backgrounded", + "description": "When a user puts the app in the background.", + }, + "Application Updated": { + "label": "Application Updated", + "description": "When a user upgrades the app.", + }, + "Application Installed": { + "label": "Application Installed", + "description": "When a user installs the app.", + }, + "Application Became Active": { + "label": "Application Became Active", + "description": "When a user puts the app in the foreground.", + }, + "Deep Link Opened": { + "label": "Deep Link Opened", + "description": "When a user opens the app via a deep link.", + }, + }, + "elements": { + "tag_name": { + "label": "Tag Name", + "description": "HTML tag name of the element which you want to filter.", + "examples": ["a", "button", "input"], + }, + "selector": { + "label": "CSS Selector", + "description": "Select any element by CSS selector.", + "examples": ["div > a", "table td:nth-child(2)", ".my-class"], + }, + "text": { + "label": "Text", + "description": "Filter on the inner text of the HTML element.", + }, + "href": { + "label": "Target (href)", + "description": "Filter on the href attribute of the element.", + "examples": ["https://posthog.com/about"], + }, + }, + "metadata": { + "distinct_id": { + "label": "Distinct ID", + "description": "The current distinct ID of the user", + "examples": ["16ff262c4301e5-0aa346c03894bc-39667c0e-1aeaa0-16ff262c431767"], + }, + }, + "event_properties": { + "distinct_id": {}, + "$session_duration": {}, + "$copy_type": { + "label": "Copy Type", + "description": "Type of copy event.", + "examples": ["copy", "cut"], + }, + "$selected_content": { + "label": "Copied content", + "description": "The content that was selected when the user copied or cut.", + }, + "$set": { + "label": "Set", + "description": "Person properties to be set", + }, + "$set_once": { + "label": "Set Once", + "description": "Person properties to be set if not set already (i.e. first-touch)", + }, + "$pageview_id": { + "label": "Pageview ID", + "description": "PostHog's internal ID for matching events to a pageview.", + "system": True, + }, + "$autocapture_disabled_server_side": { + "label": "Autocapture Disabled Server-Side", + "description": "If autocapture has been disabled server-side.", + "system": True, + }, + "$console_log_recording_enabled_server_side": { + "label": "Console Log Recording Enabled Server-Side", + "description": "If console log recording has been enabled server-side.", + "system": True, + }, + "$session_recording_recorder_version_server_side": { + "label": "Session Recording Recorder Version Server-Side", + "description": "The version of the session recording recorder that is enabled server-side.", + "examples": ["v2"], + "system": True, + }, + "$feature_flag_payloads": { + "label": "Feature Flag Payloads", + "description": "Feature flag payloads active in the environment.", + }, + "$capture_failed_request": { + "label": "Capture Failed Request", + "description": "", + }, + "$sentry_exception": { + "label": "Sentry exception", + "description": "Raw Sentry exception data", + "system": True, + }, + "$sentry_exception_message": { + "label": "Sentry exception message", + }, + "$sentry_exception_type": { + "label": "Sentry exception type", + "description": "Class name of the exception object", + }, + "$sentry_tags": { + "label": "Sentry tags", + "description": "Tags sent to Sentry along with the exception", + }, + "$exception_type": { + "label": "Exception type", + "description": 'Exception categorized into types. E.g. "Error"', + }, + "$exception_message": { + "label": "Exception Message", + "description": "The message detected on the error.", + }, + "$exception_source": { + "label": "Exception source", + "description": "The source of the exception. E.g. JS file.", + }, + "$exception_lineno": { + "label": "Exception source line number", + "description": "Which line in the exception source that caused the exception.", + }, + "$exception_colno": { + "label": "Exception source column number", + "description": "Which column of the line in the exception source that caused the exception.", + }, + "$exception_DOMException_code": { + "label": "DOMException code", + "description": "If a DOMException was thrown, it also has a DOMException code.", + }, + "$exception_is_synthetic": { + "label": "Exception is synthetic", + "description": "Whether this was detected as a synthetic exception", + }, + "$exception_stack_trace_raw": { + "label": "Exception raw stack trace", + "description": "The exception's stack trace, as a string.", + }, + "$exception_handled": { + "label": "Exception was handled", + "description": "Whether this was a handled or unhandled exception", + }, + "$exception_personURL": { + "label": "Exception person URL", + "description": "The PostHog person that experienced the exception", + }, + "$ce_version": { + "label": "$ce_version", + "description": "", + "system": True, + }, + "$anon_distinct_id": { + "label": "Anon Distinct ID", + "description": "If the user was previously anonymous, their anonymous ID will be set here.", + "examples": ["16ff262c4301e5-0aa346c03894bc-39667c0e-1aeaa0-16ff262c431767"], + "system": True, + }, + "$event_type": { + "label": "Event Type", + "description": "When the event is an $autocapture event, this specifies what the action was against the element.", + "examples": ["click", "submit", "change"], + }, + "$insert_id": { + "label": "Insert ID", + "description": "Unique insert ID for the event.", + "system": True, + }, + "$time": { + "label": "$time (deprecated)", + "description": "Use the HogQL field `timestamp` instead. This field was previously set on some client side events.", + "system": True, + "examples": ["1681211521.345"], + }, + "$device_id": { + "label": "Device ID", + "description": "Unique ID for that device, consistent even if users are logging in/out.", + "examples": ["16ff262c4301e5-0aa346c03894bc-39667c0e-1aeaa0-16ff262c431767"], + "system": True, + }, + "$geoip_city_name": { + "label": "City Name", + "description": "Name of the city matched to this event's IP address.", + "examples": ["Sydney", "Chennai", "Brooklyn"], + }, + "$geoip_country_name": { + "label": "Country Name", + "description": "Name of the country matched to this event's IP address.", + "examples": ["Australia", "India", "United States"], + }, + "$geoip_country_code": { + "label": "Country Code", + "description": "Code of the country matched to this event's IP address.", + "examples": ["AU", "IN", "US"], + }, + "$geoip_continent_name": { + "label": "Continent Name", + "description": "Name of the continent matched to this event's IP address.", + "examples": ["Oceania", "Asia", "North America"], + }, + "$geoip_continent_code": { + "label": "Continent Code", + "description": "Code of the continent matched to this event's IP address.", + "examples": ["OC", "AS", "NA"], + }, + "$geoip_postal_code": { + "label": "Postal Code", + "description": "Approximated postal code matched to this event's IP address.", + "examples": ["2000", "600004", "11211"], + }, + "$geoip_latitude": { + "label": "Latitude", + "description": "Approximated latitude matched to this event's IP address.", + "examples": ["-33.8591", "13.1337", "40.7"], + }, + "$geoip_longitude": { + "label": "Longitude", + "description": "Approximated longitude matched to this event's IP address.", + "examples": ["151.2", "80.8008", "-73.9"], + }, + "$geoip_time_zone": { + "label": "Timezone", + "description": "Timezone matched to this event's IP address.", + "examples": ["Australia/Sydney", "Asia/Kolkata", "America/New_York"], + }, + "$geoip_subdivision_1_name": { + "label": "Subdivision 1 Name", + "description": "Name of the subdivision matched to this event's IP address.", + "examples": ["New South Wales", "Tamil Nadu", "New York"], + }, + "$geoip_subdivision_1_code": { + "label": "Subdivision 1 Code", + "description": "Code of the subdivision matched to this event's IP address.", + "examples": ["NSW", "TN", "NY"], + }, + "$geoip_subdivision_2_name": { + "label": "Subdivision 2 Name", + "description": "Name of the second subdivision matched to this event's IP address.", + }, + "$geoip_subdivision_2_code": { + "label": "Subdivision 2 Code", + "description": "Code of the second subdivision matched to this event's IP address.", + }, + "$geoip_subdivision_3_name": { + "label": "Subdivision 3 Name", + "description": "Name of the third subdivision matched to this event's IP address.", + }, + "$geoip_subdivision_3_code": { + "label": "Subdivision 3 Code", + "description": "Code of the third subdivision matched to this event's IP address.", + }, + "$geoip_disable": { + "label": "GeoIP Disabled", + "description": "Whether to skip GeoIP processing for the event.", + }, + "$el_text": { + "label": "Element Text", + "description": "The text of the element that was clicked. Only sent with Autocapture events.", + "examples": ["Click here!"], + }, + "$app_build": { + "label": "App Build", + "description": "The build number for the app.", + }, + "$app_name": { + "label": "App Name", + "description": "The name of the app.", + }, + "$app_namespace": { + "label": "App Namespace", + "description": "The namespace of the app as identified in the app store.", + "examples": ["com.posthog.app"], + }, + "$app_version": { + "label": "App Version", + "description": "The version of the app.", + }, + "$device_manufacturer": { + "label": "Device Manufacturer", + "description": "The manufacturer of the device", + "examples": ["Apple", "Samsung"], + }, + "$device_name": { + "label": "Device Name", + "description": "Name of the device", + "examples": ["iPhone 12 Pro", "Samsung Galaxy 10"], + }, + "$locale": { + "label": "Locale", + "description": "The locale of the device", + "examples": ["en-US", "de-DE"], + }, + "$os_name": { + "label": "OS Name", + "description": "The Operating System name", + "examples": ["iOS", "Android"], + }, + "$os_version": { + "label": "OS Version", + "description": "The Operating System version.", + "examples": ["15.5"], + }, + "$timezone": { + "label": "Timezone", + "description": "The timezone as reported by the device", + }, + "$touch_x": { + "label": "Touch X", + "description": "The location of a Touch event on the X axis", + }, + "$touch_y": { + "label": "Touch Y", + "description": "The location of a Touch event on the Y axis", + }, + "$plugins_succeeded": { + "label": "Plugins Succeeded", + "description": "Plugins that successfully processed the event, e.g. edited properties (plugin method processEvent).", + }, + "$groups": { + "label": "Groups", + "description": "Relevant groups", + }, + "$group_0": { + "label": "Group 1", + "system": True, + }, + "$group_1": { + "label": "Group 2", + "system": True, + }, + "$group_2": { + "label": "Group 3", + "system": True, + }, + "$group_3": { + "label": "Group 4", + "system": True, + }, + "$group_4": { + "label": "Group 5", + "system": True, + }, + "$group_set": { + "label": "Group Set", + "description": "Group properties to be set", + }, + "$group_key": { + "label": "Group Key", + "description": "Specified group key", + }, + "$group_type": { + "label": "Group Type", + "description": "Specified group type", + }, + "$window_id": { + "label": "Window ID", + "description": "Unique window ID for session recording disambiguation", + "system": True, + }, + "$session_id": { + "label": "Session ID", + "description": "Unique session ID for session recording disambiguation", + "system": True, + }, + "$plugins_failed": { + "label": "Plugins Failed", + "description": "Plugins that failed to process the event (plugin method processEvent).", + }, + "$plugins_deferred": { + "label": "Plugins Deferred", + "description": "Plugins to which the event was handed off post-ingestion, e.g. for export (plugin method onEvent).", + }, + "$$plugin_metrics": { + "label": "Plugin Metric", + "description": "Performance metrics for a given plugin.", + }, + "$creator_event_uuid": { + "label": "Creator Event ID", + "description": "Unique ID for the event, which created this person.", + "examples": ["16ff262c4301e5-0aa346c03894bc-39667c0e-1aeaa0-16ff262c431767"], + }, + "utm_source": { + "label": "UTM Source", + "description": "UTM source tag.", + "examples": ["Google", "Bing", "Twitter", "Facebook"], + }, + "$initial_utm_source": { + "label": "Initial UTM Source", + "description": "UTM source tag.", + "examples": ["Google", "Bing", "Twitter", "Facebook"], + }, + "utm_medium": { + "label": "UTM Medium", + "description": "UTM medium tag.", + "examples": ["Social", "Organic", "Paid", "Email"], + }, + "utm_campaign": { + "label": "UTM Campaign", + "description": "UTM campaign tag.", + "examples": ["feature launch", "discount"], + }, + "utm_name": { + "label": "UTM Name", + "description": "UTM campaign tag, sent via Segment.", + "examples": ["feature launch", "discount"], + }, + "utm_content": { + "label": "UTM Content", + "description": "UTM content tag.", + "examples": ["bottom link", "second button"], + }, + "utm_term": { + "label": "UTM Term", + "description": "UTM term tag.", + "examples": ["free goodies"], + }, + "$performance_page_loaded": { + "label": "Page Loaded", + "description": "The time taken until the browser's page load event in milliseconds.", + }, + "$performance_raw": { + "label": "Browser Performance", + "description": "The browser performance entries for navigation (the page), paint, and resources. That were available when the page view event fired", + "system": True, + }, + "$had_persisted_distinct_id": { + "label": "$had_persisted_distinct_id", + "description": "", + "system": True, + }, + "$sentry_event_id": { + "label": "Sentry Event ID", + "description": "This is the Sentry key for an event.", + "examples": ["byroc2ar9ee4ijqp"], + "system": True, + }, + "$timestamp": { + "label": "Timestamp", + "description": "Time the event happened.", + "examples": ["2023-05-20T15:30:00Z"], + }, + "$sent_at": { + "label": "Sent At", + "description": "Time the event was sent to PostHog. Used for correcting the event timestamp when the device clock is off.", + "examples": ["2023-05-20T15:31:00Z"], + }, + "$browser": { + "label": "Browser", + "description": "Name of the browser the user has used.", + "examples": ["Chrome", "Firefox"], + }, + "$os": { + "label": "OS", + "description": "The operating system of the user.", + "examples": ["Windows", "Mac OS X"], + }, + "$browser_language": { + "label": "Browser Language", + "description": "Language.", + "examples": ["en", "en-US", "cn", "pl-PL"], + }, + "$current_url": { + "label": "Current URL", + "description": "The URL visited at the time of the event.", + "examples": ["https://example.com/interesting-article?parameter=true"], + }, + "$browser_version": { + "label": "Browser Version", + "description": "The version of the browser that was used. Used in combination with Browser.", + "examples": ["70", "79"], + }, + "$raw_user_agent": { + "label": "Raw User Agent", + "description": "PostHog process information like browser, OS, and device type from the user agent string. This is the raw user agent string.", + "examples": ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)"], + }, + "$user_agent": { + "label": "Raw User Agent", + "description": "Some SDKs (like Android) send the raw user agent as $user_agent.", + "examples": ["Dalvik/2.1.0 (Linux; U; Android 11; Pixel 3 Build/RQ2A.210505.002)"], + }, + "$screen_height": { + "label": "Screen Height", + "description": "The height of the user's entire screen (in pixels).", + "examples": ["2160", "1050"], + }, + "$screen_width": { + "label": "Screen Width", + "description": "The width of the user's entire screen (in pixels).", + "examples": ["1440", "1920"], + }, + "$screen_name": { + "label": "Screen Name", + "description": "The name of the active screen.", + }, + "$viewport_height": { + "label": "Viewport Height", + "description": "The height of the user's actual browser window (in pixels).", + "examples": ["2094", "1031"], + }, + "$viewport_width": { + "label": "Viewport Width", + "description": "The width of the user's actual browser window (in pixels).", + "examples": ["1439", "1915"], + }, + "$lib": { + "label": "Library", + "description": "What library was used to send the event.", + "examples": ["web", "posthog-ios"], + }, + "$lib_custom_api_host": { + "label": "Library Custom API Host", + "description": "The custom API host used to send the event.", + "examples": ["https://ph.example.com"], + }, + "$lib_version": { + "label": "Library Version", + "description": "Version of the library used to send the event. Used in combination with Library.", + "examples": ["1.0.3"], + }, + "$lib_version__major": { + "label": "Library Version (Major)", + "description": "Major version of the library used to send the event.", + "examples": [1], + }, + "$lib_version__minor": { + "label": "Library Version (Minor)", + "description": "Minor version of the library used to send the event.", + "examples": [0], + }, + "$lib_version__patch": { + "label": "Library Version (Patch)", + "description": "Patch version of the library used to send the event.", + "examples": [3], + }, + "$referrer": { + "label": "Referrer URL", + "description": "URL of where the user came from.", + "examples": ["https://google.com/search?q=posthog&rlz=1C..."], + }, + "$referring_domain": { + "label": "Referring Domain", + "description": "Domain of where the user came from.", + "examples": ["google.com", "facebook.com"], + }, + "$user_id": { + "label": "User ID", + "description": "This variable will be set to the distinct ID if you've called posthog.identify('distinct id'). If the user is anonymous, it'll be empty.", + }, + "$ip": { + "label": "IP Address", + "description": "IP address for this user when the event was sent.", + "examples": ["203.0.113.0"], + }, + "$host": { + "label": "Host", + "description": "The hostname of the Current URL.", + "examples": ["example.com", "localhost:8000"], + }, + "$pathname": { + "label": "Path Name", + "description": "The path of the Current URL, which means everything in the url after the domain.", + "examples": ["/pricing", "/about-us/team"], + }, + "$search_engine": { + "label": "Search Engine", + "description": "The search engine the user came in from (if any).", + "examples": ["Google", "DuckDuckGo"], + }, + "$active_feature_flags": { + "label": "Active Feature Flags", + "description": "Keys of the feature flags that were active while this event was sent.", + "examples": ["['beta-feature']"], + }, + "$enabled_feature_flags": { + "label": "Enabled Feature Flags", + "description": "Keys and multivariate values of the feature flags that were active while this event was sent.", + "examples": ['{"flag": "value"}'], + }, + "$feature_flag_response": { + "label": "Feature Flag Response", + "description": "What the call to feature flag responded with.", + "examples": ["true", "false"], + }, + "$feature_flag": { + "label": "Feature Flag", + "description": 'The feature flag that was called.\n\nWarning! This only works in combination with the $feature_flag_called event. If you want to filter other events, try "Active Feature Flags".', + "examples": ["beta-feature"], + }, + "$survey_response": { + "label": "Survey Response", + "description": "The response value for the first question in the survey.", + "examples": ["I love it!", 5, "['choice 1', 'choice 3']"], + }, + "$survey_name": { + "label": "Survey Name", + "description": "The name of the survey.", + "examples": ["Product Feedback for New Product", "Home page NPS"], + }, + "$survey_questions": { + "label": "Survey Questions", + "description": "The questions asked in the survey.", + }, + "$survey_id": { + "label": "Survey ID", + "description": "The unique identifier for the survey.", + }, + "$survey_iteration": { + "label": "Survey Iteration Number", + "description": "The iteration number for the survey.", + }, + "$survey_iteration_start_date": { + "label": "Survey Iteration Start Date", + "description": "The start date for the current iteration of the survey.", + }, + "$device": { + "label": "Device", + "description": "The mobile device that was used.", + "examples": ["iPad", "iPhone", "Android"], + }, + "$sentry_url": { + "label": "Sentry URL", + "description": "Direct link to the exception in Sentry", + "examples": ["https://sentry.io/..."], + }, + "$device_type": { + "label": "Device Type", + "description": "The type of device that was used.", + "examples": ["Mobile", "Tablet", "Desktop"], + }, + "$screen_density": { + "label": "Screen density", + "description": 'The logical density of the display. This is a scaling factor for the Density Independent Pixel unit, where one DIP is one pixel on an approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen), providing the baseline of the system\'s display. Thus on a 160dpi screen this density value will be 1; on a 120 dpi screen it would be .75; etc.', + "examples": [2.75], + }, + "$device_model": { + "label": "Device Model", + "description": "The model of the device that was used.", + "examples": ["iPhone9,3", "SM-G965W"], + }, + "$network_wifi": { + "label": "Network WiFi", + "description": "Whether the user was on WiFi when the event was sent.", + "examples": ["true", "false"], + }, + "$network_bluetooth": { + "label": "Network Bluetooth", + "description": "Whether the user was on Bluetooth when the event was sent.", + "examples": ["true", "false"], + }, + "$network_cellular": { + "label": "Network Cellular", + "description": "Whether the user was on cellular when the event was sent.", + "examples": ["true", "false"], + }, + "$client_session_initial_referring_host": { + "label": "Referrer Host", + "description": "Host that the user came from. (First-touch, session-scoped)", + "examples": ["google.com", "facebook.com"], + }, + "$client_session_initial_pathname": { + "label": "Initial Path", + "description": "Path that the user started their session on. (First-touch, session-scoped)", + "examples": ["/register", "/some/landing/page"], + }, + "$client_session_initial_utm_source": { + "label": "Initial UTM Source", + "description": "UTM Source. (First-touch, session-scoped)", + "examples": ["Google", "Bing", "Twitter", "Facebook"], + }, + "$client_session_initial_utm_campaign": { + "label": "Initial UTM Campaign", + "description": "UTM Campaign. (First-touch, session-scoped)", + "examples": ["feature launch", "discount"], + }, + "$client_session_initial_utm_medium": { + "label": "Initial UTM Medium", + "description": "UTM Medium. (First-touch, session-scoped)", + "examples": ["Social", "Organic", "Paid", "Email"], + }, + "$client_session_initial_utm_content": { + "label": "Initial UTM Source", + "description": "UTM Source. (First-touch, session-scoped)", + "examples": ["bottom link", "second button"], + }, + "$client_session_initial_utm_term": { + "label": "Initial UTM Source", + "description": "UTM Source. (First-touch, session-scoped)", + "examples": ["free goodies"], + }, + "$network_carrier": { + "label": "Network Carrier", + "description": "The network carrier that the user is on.", + "examples": ["cricket", "telecom"], + }, + "from_background": { + "label": "From Background", + "description": "Whether the app was opened for the first time or from the background.", + "examples": ["true", "false"], + }, + "url": { + "label": "URL", + "description": "The deep link URL that the app was opened from.", + "examples": ["https://open.my.app"], + }, + "referring_application": { + "label": "Referrer Application", + "description": "The namespace of the app that made the request.", + "examples": ["com.posthog.app"], + }, + "version": { + "label": "App Version", + "description": "The version of the app", + "examples": ["1.0.0"], + }, + "previous_version": { + "label": "App Previous Version", + "description": "The previous version of the app", + "examples": ["1.0.0"], + }, + "build": { + "label": "App Build", + "description": "The build number for the app", + "examples": ["1"], + }, + "previous_build": { + "label": "App Previous Build", + "description": "The previous build number for the app", + "examples": ["1"], + }, + "gclid": { + "label": "gclid", + "description": "Google Click ID", + }, + "rdt_cid": { + "label": "rdt_cid", + "description": "Reddit Click ID", + }, + "gad_source": { + "label": "gad_source", + "description": "Google Ads Source", + }, + "gclsrc": { + "label": "gclsrc", + "description": "Google Click Source", + }, + "dclid": { + "label": "dclid", + "description": "DoubleClick ID", + }, + "gbraid": { + "label": "gbraid", + "description": "Google Ads, web to app", + }, + "wbraid": { + "label": "wbraid", + "description": "Google Ads, app to web", + }, + "fbclid": { + "label": "fbclid", + "description": "Facebook Click ID", + }, + "msclkid": { + "label": "msclkid", + "description": "Microsoft Click ID", + }, + "twclid": { + "label": "twclid", + "description": "Twitter Click ID", + }, + "li_fat_id": { + "label": "li_fat_id", + "description": "LinkedIn First-Party Ad Tracking ID", + }, + "mc_cid": { + "label": "mc_cid", + "description": "Mailchimp Campaign ID", + }, + "igshid": { + "label": "igshid", + "description": "Instagram Share ID", + }, + "ttclid": { + "label": "ttclid", + "description": "TikTok Click ID", + }, + "$is_identified": { + "label": "Is Identified", + "description": "When the person was identified", + }, + "$web_vitals_enabled_server_side": { + "label": "Web vitals enabled server side", + "description": "Whether web vitals was enabled in remote config", + }, + "$web_vitals_FCP_event": { + "label": "Web vitals FCP measure event details", + }, + "$web_vitals_FCP_value": { + "label": "Web vitals FCP value", + }, + "$web_vitals_LCP_event": { + "label": "Web vitals LCP measure event details", + }, + "$web_vitals_LCP_value": { + "label": "Web vitals LCP value", + }, + "$web_vitals_INP_event": { + "label": "Web vitals INP measure event details", + }, + "$web_vitals_INP_value": { + "label": "Web vitals INP value", + }, + "$web_vitals_CLS_event": { + "label": "Web vitals CLS measure event details", + }, + "$web_vitals_CLS_value": { + "label": "Web vitals CLS value", + }, + }, + "numerical_event_properties": {}, + "person_properties": {}, + "session_properties": { + "$session_duration": { + "label": "Session duration", + "description": "The duration of the session being tracked. Learn more about how PostHog tracks sessions in our documentation.\n\nNote, if the duration is formatted as a single number (not 'HH:MM:SS'), it's in seconds.", + "examples": ["01:04:12"], + "type": "Numeric", + }, + "$start_timestamp": { + "label": "Start timestamp", + "description": "The timestamp of the first event from this session.", + "examples": ["2023-05-20T15:30:00Z"], + "type": "DateTime", + }, + "$end_timestamp": { + "label": "End timestamp", + "description": "The timestamp of the last event from this session", + "examples": ["2023-05-20T16:30:00Z"], + "type": "DateTime", + }, + "$entry_current_url": { + "label": "Entry URL", + "description": "The first URL visited in this session", + "examples": ["https://example.com/interesting-article?parameter=true"], + "type": "String", + }, + "$entry_pathname": { + "label": "Entry pathname", + "description": "The first pathname visited in this session", + "examples": ["/interesting-article?parameter=true"], + "type": "String", + }, + "$end_current_url": { + "label": "Entry URL", + "description": "The first URL visited in this session", + "examples": ["https://example.com/interesting-article?parameter=true"], + "type": "String", + }, + "$end_pathname": { + "label": "Entry pathname", + "description": "The first pathname visited in this session", + "examples": ["/interesting-article?parameter=true"], + "type": "String", + }, + "$exit_current_url": { + "label": "Exit URL", + "description": "The last URL visited in this session", + "examples": ["https://example.com/interesting-article?parameter=true"], + "type": "String", + }, + "$exit_pathname": { + "label": "Exit pathname", + "description": "The last pathname visited in this session", + "examples": ["/interesting-article?parameter=true"], + "type": "String", + }, + "$pageview_count": { + "label": "Pageview count", + "description": "The number of page view events in this session", + "examples": ["123"], + "type": "Numeric", + }, + "$autocapture_count": { + "label": "Autocapture count", + "description": "The number of autocapture events in this session", + "examples": ["123"], + "type": "Numeric", + }, + "$screen_count": { + "label": "Screen count", + "description": "The number of screen events in this session", + "examples": ["123"], + "type": "Numeric", + }, + "$channel_type": { + "label": "Channel type", + "description": "What type of acquisition channel this traffic came from.", + "examples": ["Paid Search", "Organic Video", "Direct"], + "type": "String", + }, + "$is_bounce": { + "label": "Is bounce", + "description": "Whether the session was a bounce.", + "examples": ["true", "false"], + "type": "Boolean", + }, + }, + "groups": { + "$group_key": { + "label": "Group Key", + "description": "Specified group key", + }, + }, + "replay": { + "snapshot_source": { + "label": "Platform", + "description": "Platform the session was recorded on", + "examples": ["web", "mobile"], + }, + "console_log_level": { + "label": "Log level", + "description": "Level of console logs captured", + "examples": ["info", "warn", "error"], + }, + "console_log_query": { + "label": "Console log", + "description": "Text of console logs captured", + }, + "visited_page": { + "label": "Visited page", + "description": "URL a user visited during their session", + }, + }, +} diff --git a/ee/hogai/system_prompt.py b/ee/hogai/system_prompt.py new file mode 100644 index 0000000000000..fb00b35825867 --- /dev/null +++ b/ee/hogai/system_prompt.py @@ -0,0 +1,77 @@ +trends_system_prompt = """ +As a recognized head of product growth acting as a top-tier data engineer, your task is to write queries of trends insights for customers using a JSON schema. + +Follow these instructions to create a query: +* Identify the events or actions the user wants to analyze. +* Determine types of entities that user wants to analyze like events, persons, groups, sessions, cohorts, etc. +* Determine a vistualization type that best suits the user's needs. +* Determine if the user wants to name the series or use the default names. +* Choose the date range and the interval the user wants to analyze. +* Determine if the user wants to compare the results to a previous period or use smoothing. +* Determine if the user wants to use property filters for all series. +* Determine math types for all series. +* Determine property filters for individual series. +* Check operators of property filters for individual and all series. Make sure the operators correspond to the user's request. You may need to use "contains" for strings if you're not sure about the exact value. +* Determine if the user wants to use a breakdown filter. +* Determine if the user wants to filter out internal and test users. If the user didn't specify, filter out internal and test users by default. +* Determine if the user wants to use sampling factor. +* Determine if it's useful to show a legend, values of series, units, y-axis scale type, etc. +* Use your judgement if there are any other parameters that the user might want to adjust that aren't listed here. + +Trends insights enable users to plot data from people, events, and properties however they want. They're useful for finding patterns in your data, as well as monitoring users' product to ensure everything is running smoothly. For example, using trends, users can analyze: +- How product's most important metrics change over time. +- Long-term patterns, or cycles in product's usage. +- How a specific change affects usage. +- The usage of different features side-by-side. +- How the properties of events vary using aggregation (sum, average, etc). +- Users can also visualize the same data points in a variety of ways. + +For trends queries, use an appropriate ChartDisplayType for the output. For example: +- if the user wants to see a dynamics in time like a line graph, use `ActionsLineGraph`. +- if the user wants to see cumulative dynamics across time, use `ActionsLineGraphCumulative`. +- if the user asks a question where you can answer with a single number, use `BoldNumber`. +- if the user wants a table, use `ActionsTable`. +- if the data is categorical, use `ActionsBar`. +- if the data is easy to understand in a pie chart, use `ActionsPie`. +- if the user has only one series and they want to see data from particular countries, use `WorldMap`. + +The user might want to get insights for groups. A group aggregates events based on entities, such as organizations or sellers. The user might provide a list of group names and their numeric indexes. Instead of a group's name, always use its numeric index. + +Cohorts enable the user to easily create a list of their users who have something in common, such as completing an event or having the same property. The user might want to use cohorts for filtering events. Instead of a cohort's name, always use its ID. + +If you want to apply Y-Axis unit, make sure it will display data correctly. Use the percentage formatting only if the anticipated result is from 0 to 1. + +Learn on these examples: +Q: How many users do I have? +A: {"dateRange":{"date_from":"all"},"interval":"month","kind":"TrendsQuery","series":[{"event":"user signed up","kind":"EventsNode","math":"total"}],"trendsFilter":{"aggregationAxisFormat":"numeric","display":"BoldNumber"}} +Q: Show a bar chart of the organic search traffic for the last month grouped by week. +A: {"dateRange":{"date_from":"-30d","date_to":null,"explicitDate":false},"interval":"week","kind":"TrendsQuery","series":[{"event":"$pageview","kind":"EventsNode","math":"dau","properties":[{"key":"$referring_domain","operator":"icontains","type":"event","value":"google"},{"key":"utm_source","operator":"is_not_set","type":"event","value":"is_not_set"}]}],"trendsFilter":{"aggregationAxisFormat":"numeric","display":"ActionsBar"}} +Q: insight created unique users & first-time users for the last 12m) +A: {"dateRange":{"date_from":"-12m","date_to":""},"filterTestAccounts":true,"interval":"month","kind":"TrendsQuery","series":[{"event":"insight created","kind":"EventsNode","math":"dau","custom_name":"insight created"},{"event":"insight created","kind":"EventsNode","math":"first_time_for_user","custom_name":"insight created"}],"trendsFilter":{"aggregationAxisFormat":"numeric","display":"ActionsLineGraph"}} +Q: What are the top 10 referring domains for the last month? +A: {"breakdownFilter":{"breakdown_type":"event","breakdowns":[{"group_type_index":null,"histogram_bin_count":null,"normalize_url":null,"property":"$referring_domain","type":"event"}]},"dateRange":{"date_from":"-30d"},"interval":"day","kind":"TrendsQuery","series":[{"event":"$pageview","kind":"EventsNode","math":"total","custom_name":"$pageview"}]} +Q: What is the DAU to MAU ratio of users from the US and Australia that viewed a page in the last 7 days? Compare it to the previous period. +A: {"compareFilter":{"compare":true,"compare_to":null},"dateRange":{"date_from":"-7d"},"interval":"day","kind":"TrendsQuery","properties":{"type":"AND","values":[{"type":"AND","values":[{"key":"$geoip_country_name","operator":"exact","type":"event","value":["United States","Australia"]}]}]},"series":[{"event":"$pageview","kind":"EventsNode","math":"dau","custom_name":"$pageview"},{"event":"$pageview","kind":"EventsNode","math":"monthly_active","custom_name":"$pageview"}],"trendsFilter":{"aggregationAxisFormat":"percentage_scaled","display":"ActionsLineGraph","formula":"A/B"}} +Q: I want to understand how old are dashboard results when viewed from the beginning of this year grouped by a month. Display the results for percentiles of 99, 95, 90, average, and median by the property "refreshAge". +A: {"dateRange":{"date_from":"yStart","date_to":null,"explicitDate":false},"filterTestAccounts":true,"interval":"month","kind":"TrendsQuery","series":[{"event":"viewed dashboard","kind":"EventsNode","math":"p99","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"p95","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"p90","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"avg","math_property":"refreshAge","custom_name":"viewed dashboard"},{"event":"viewed dashboard","kind":"EventsNode","math":"median","math_property":"refreshAge","custom_name":"viewed dashboard"}],"trendsFilter":{"aggregationAxisFormat":"duration","display":"ActionsLineGraph"}} +Q: organizations joined in the last 30 days by day from the google search +A: {"dateRange":{"date_from":"-30d"},"filterTestAccounts":false,"interval":"day","kind":"TrendsQuery","properties":{"type":"AND","values":[{"type":"OR","values":[{"key":"$initial_utm_source","operator":"exact","type":"person","value":["google"]}]}]},"series":[{"event":"user signed up","kind":"EventsNode","math":"unique_group","math_group_type_index":0,"name":"user signed up","properties":[{"key":"is_organization_first_user","operator":"exact","type":"person","value":["true"]}]}],"trendsFilter":{"aggregationAxisFormat":"numeric","display":"ActionsLineGraph"}} +Q: trends for the last two weeks of the onboarding completed event by unique projects with a session duration more than 5 minutes and the insight analyzed event by unique projects with a breakdown by event's Country Name. exclude the US. +A: {"kind":"TrendsQuery","series":[{"kind":"EventsNode","event":"onboarding completed","name":"onboarding completed","properties":[{"key":"$session_duration","value":300,"operator":"gt","type":"session"}],"math":"unique_group","math_group_type_index":2},{"kind":"EventsNode","event":"insight analyzed","name":"insight analyzed","math":"unique_group","math_group_type_index":2}],"trendsFilter":{"display":"ActionsBar","showValuesOnSeries":true,"showPercentStackView":false,"showLegend":false},"breakdownFilter":{"breakdowns":[{"property":"$geoip_country_name","type":"event"}],"breakdown_limit":5},"properties":{"type":"AND","values":[{"type":"AND","values":[{"key":"$geoip_country_code","value":["US"],"operator":"is_not","type":"event"}]}]},"dateRange":{"date_from":"-14d","date_to":null},"interval":"day"} + +Obey these rules: +- if the date range is not specified, use the best judgement to select a reasonable date range. If it is a question that can be answered with a single number, you may need to use the longest possible date range. +- Filter internal users by default if the user doesn't specify. +- Only use events and properties defined by the user. You can't create new events or property definitions. + +For your reference, there is a description of the data model. + +The "events" table has the following columns: +* timestamp (DateTime) - date and time of the event. Events are sorted by timestamp in ascending order. +* uuid (UUID) - unique identifier of the event. +* person_id (UUID) - unique identifier of the person who performed the event. +* event (String) - name of the event. +* properties (custom type) - additional properties of the event. Properties can be of multiple types: String, Int, Decimal, Float, and Bool. A property can be an array of thosee types. A property always has only ONE type. If the property starts with a $, it is a system-defined property. If the property doesn't start with a $, it is a user-defined property. There is a list of system-defined properties: $browser, $browser_version, and $os. User-defined properties can have any name. + +Remember, your efforts will be rewarded with a $100 tip if you manage to implement a perfect query that follows user's instructions and return the desired result. Do not hallucinate. +""" diff --git a/ee/hogai/team_prompt.py b/ee/hogai/team_prompt.py new file mode 100644 index 0000000000000..6ab987b992363 --- /dev/null +++ b/ee/hogai/team_prompt.py @@ -0,0 +1,137 @@ +import collections +from datetime import timedelta + +from django.utils import timezone + +from posthog.models.cohort.cohort import Cohort +from posthog.models.event_definition import EventDefinition +from posthog.models.group_type_mapping import GroupTypeMapping +from posthog.models.property_definition import PropertyDefinition +from posthog.models.team.team import Team + +from .hardcoded_definitions import hardcoded_prop_defs + + +class TeamPrompt: + _team: Team + + def __init__(self, team: Team): + super().__init__() + self._team = team + + @classmethod + def get_properties_tag_name(self, property_name: str) -> str: + return f"list of {property_name.lower()} property definitions by a type" + + def _clean_line(self, line: str) -> str: + return line.replace("\n", " ") + + def _get_xml_tag(self, tag_name: str, content: str) -> str: + return f"\n<{tag_name}>\n{content.strip()}\n\n" + + def _generate_cohorts_prompt(self) -> str: + cohorts = Cohort.objects.filter(team=self._team, last_calculation__gte=timezone.now() - timedelta(days=60)) + return self._get_xml_tag( + "list of defined cohorts", + "\n".join([f'name "{cohort.name}", ID {cohort.id}' for cohort in cohorts]), + ) + + def _generate_events_prompt(self) -> str: + event_description_mapping = { + "$identify": "Identifies an anonymous user. This event doesn't show how many users you have but rather how many users used an account." + } + + tags: list[str] = [] + for event in EventDefinition.objects.filter( + team=self._team, last_seen_at__gte=timezone.now() - timedelta(days=60) + ): + event_tag = event.name + if event.name in event_description_mapping: + description = event_description_mapping[event.name] + event_tag += f" - {description}" + elif event.name in hardcoded_prop_defs["events"]: + data = hardcoded_prop_defs["events"][event.name] + event_tag += f" - {data['label']}. {data['description']}" + if "examples" in data: + event_tag += f" Examples: {data['examples']}." + tags.append(self._clean_line(event_tag)) + + tag_name = "list of available events for filtering" + return self._get_xml_tag(tag_name, "\n".join(sorted(tags))) + + def _generate_groups_prompt(self) -> str: + user_groups = GroupTypeMapping.objects.filter(team=self._team).order_by("group_type_index") + return self._get_xml_tag( + "list of defined groups", + "\n".join([f'name "{group.group_type}", index {group.group_type_index}' for group in user_groups]), + ) + + def _join_property_tags(self, tag_name: str, properties_by_type: dict[str, list[str]]) -> str: + if any(prop_by_type for prop_by_type in properties_by_type.values()): + tags = "\n".join( + self._get_xml_tag(prop_type, "\n".join(tags)) for prop_type, tags in properties_by_type.items() + ) + return self._get_xml_tag(tag_name, tags) + "\n" + return "" + + def _get_property_type(self, prop: PropertyDefinition) -> str: + if prop.name.startswith("$feature/"): + return "feature" + return PropertyDefinition.Type(prop.type).label.lower() + + def _generate_properties_prompt(self) -> str: + properties = ( + PropertyDefinition.objects.filter(team=self._team) + .exclude( + name__regex=r"(__|phjs|survey_dismissed|survey_responded|partial_filter_chosen|changed_action|window-id|changed_event|partial_filter)" + ) + .distinct("name") + ).iterator(chunk_size=2500) + + key_mapping = { + "event": "event_properties", + } + + tags: dict[str, dict[str, list[str]]] = collections.defaultdict(lambda: collections.defaultdict(list)) + + for prop in properties: + category = self._get_property_type(prop) + property_type = prop.property_type + + if category in ["group", "session"] or property_type is None: + continue + + prop_tag = prop.name + + if category in key_mapping and prop.name in hardcoded_prop_defs[key_mapping[category]]: + data = hardcoded_prop_defs[key_mapping[category]][prop.name] + if "label" in data: + prop_tag += f" - {data['label']}." + if "description" in data: + prop_tag += f" {data['description']}" + if "examples" in data: + prop_tag += f" Examples: {data['examples']}." + + tags[category][property_type].append(self._clean_line(prop_tag)) + + # Session hardcoded properties + for key, defs in hardcoded_prop_defs["session_properties"].items(): + prop_tag += f"{key} - {defs['label']}. {defs['description']}." + if "examples" in defs: + prop_tag += f" Examples: {defs['examples']}." + tags["session"][defs["type"]].append(self._clean_line(prop_tag)) + + prompt = "\n".join( + [self._join_property_tags(self.get_properties_tag_name(category), tags[category]) for category in tags], + ) + + return prompt + + def generate_prompt(self) -> str: + return "".join( + [ + self._generate_groups_prompt(), + self._generate_events_prompt(), + self._generate_properties_prompt(), + ] + ) diff --git a/ee/hogai/trends_function.py b/ee/hogai/trends_function.py new file mode 100644 index 0000000000000..6f57b47506578 --- /dev/null +++ b/ee/hogai/trends_function.py @@ -0,0 +1,71 @@ +import json +from functools import cached_property +from typing import Any + +from ee.hogai.team_prompt import TeamPrompt +from posthog.models.property_definition import PropertyDefinition +from posthog.schema import ExperimentalAITrendsQuery + + +class TrendsFunction: + def _replace_value_in_dict(self, item: Any, original_schema: Any): + if isinstance(item, list): + return [self._replace_value_in_dict(i, original_schema) for i in item] + elif isinstance(item, dict): + if list(item.keys()) == ["$ref"]: + definitions = item["$ref"][2:].split("/") + res = original_schema.copy() + for definition in definitions: + res = res[definition] + return res + else: + return {key: self._replace_value_in_dict(i, original_schema) for key, i in item.items()} + else: + return item + + @cached_property + def _flat_schema(self): + schema = ExperimentalAITrendsQuery.model_json_schema() + + # Patch `numeric` types + schema["$defs"]["MathGroupTypeIndex"]["type"] = "number" + + # Clean up the property filters + for key, title in ( + ("EventPropertyFilter", PropertyDefinition.Type.EVENT.label), + ("PersonPropertyFilter", PropertyDefinition.Type.PERSON.label), + ("SessionPropertyFilter", PropertyDefinition.Type.SESSION.label), + ("FeaturePropertyFilter", "feature"), + ("CohortPropertyFilter", "cohort"), + ): + property_schema = schema["$defs"][key] + property_schema["properties"]["key"]["description"] = ( + f"Use one of the properties the user has provided in the <{TeamPrompt.get_properties_tag_name(title)}> tag." + ) + + for _ in range(100): + if "$ref" not in json.dumps(schema): + break + schema = self._replace_value_in_dict(schema.copy(), schema.copy()) + del schema["$defs"] + return schema + + def generate_function(self): + return { + "type": "function", + "function": { + "name": "output_insight_schema", + "description": "Outputs the JSON schema of a product analytics insight", + "parameters": { + "type": "object", + "properties": { + "reasoning_steps": { + "type": "array", + "items": {"type": "string"}, + "description": "The reasoning steps leading to the final conclusion that will be shown to the user. Use 'you' if you want to refer to the user.", + }, + "answer": self._flat_schema, + }, + }, + }, + } diff --git a/frontend/__snapshots__/components-command-bar--actions--dark.png b/frontend/__snapshots__/components-command-bar--actions--dark.png index 44ab7e3741e099057ff307013b38e63d8d2b4935..62965c348e773d0f127d3025ca4af9825884bbec 100644 GIT binary patch literal 19746 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 literal 20858 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 VM<24xj@!jbh{}j$J%0J_e*p8+-4p-- literal 54278 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 z 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 YtXedh|6ElQex62FS`nFj`@xg{18hI6JOBUy diff --git a/frontend/__snapshots__/components-command-bar--search--light.png b/frontend/__snapshots__/components-command-bar--search--light.png index beb9e54a072c0401bec415b6eafdc885883f6fa6..75bd57cddaff11e9bffc519b58ff0e3b78b8f30c 100644 GIT binary patch literal 53477 zcmbrm2T)XNw=LS31yRY0DB21rQOQX_ZAFkI5+z9nK@bti!GM4Wiik)?4CE{zSy4c; zC^fHD0)xA}(_b#^^x>v6+%{k^6V=g}xC0S}pW=aBqKrMHkq)H%c z#$Pu)-?jn&c}ZV}KM54}s>(*(3j0=}!RCd$T zygtTxw*0{!t8t^P7ve6)JmpZ&uu`*bGom$)I}y}&{MHvO;w`luzVhnyn;0l4Mxwf- z<{w%8Xm`AAdiJ`yN3U|v{9d!kNHKvOW$mt0I~>^tH_*uLko`nQQ%TprC`MFjBi|!l z({K9yhSyWA#O6x*9&|Bvo+Wjyw`8pMIrr&YJ4LMbzG?}z+c zFK+vlGHu$-=hI{G?;TG2uHPuq4yo{!UnI(N!{G_-P?#ed#QbzQQ-o@Kt@ zPJ_Q+wBLEHcjpzQPc$=@}0Dw3no5_{Gf3ch$s5;>sq$e{U{YTwwYbE7mU-7+lqs@MHbY_ygaUp2M4d zkv>^o=j*UvSwH=ss}?Pa3a5n)I7b^t6_Qx&BDc^4`3?`UQq|G$9scUnD64SP^WRK; z=b7#A(ukf%JTV>fdi| zxfVN~(OuOGkZ0qIb|LQ@yllmkCfC>W4yl$<6@74`4h)^)j}A?gpd8cLA;#y zHUz&Zu)p0QL$RVk>nCb2;Qx$==PdC=<%^mF`ptLmS?EM4jn?N;aq)4%(n%6Dq56S`IiL2n>@8V zqSO!Xc+|uaJZe5W?Tukco#g)eJ7)1rEgkmYBnc`fG4cob!=BFaH%0v&xy+gP7cXuz zWfeK75H|jOx6ECy4SW9njljH#{{6qdeK{CQ__wRPwoq(7{_lr^+m3quTaDOLG88-h z{g8SC<@ft%i9u~`ZF~0Z%e&T@8y9z4%huYuD^(}2y5`@Trgj7s(0R3v_Luv&x3`m? zMnt&I^p}6QyER$jF!>!`;*Z0_UFIjd@7&q2XcK*z&cA%imMs&Vc_Jbr>Hg#26>o2N zXDH_K`zTEStMuA*-$&U%mQ(-kV9M+5+qb^H5iP>k#P@VsSy>gkywA#-9UqUJo<6SG zYLjrgm+h$6zQNK7$3{j{4NBL>+q2`9V|aOZnj0H0I_gg=$(=ucUO}Ph+c&H3 zf}Gc{Ul)ACK)tpc;^nPx$-QPT@U4I{AvM+1rbqYgK!1O~3Ze9Z3PI%HhYueX7Z;5y z1FwC3RrTe?nO!WR*XPFDFTOmND8c6>OFDaYzqH57;;-QVW+DFL$3A)?gW|xcbdI2W*Y45?2dy&%{?>Q*&wNo;n{FyU{@u%MQgqbJRy$1>k z3Jlz4%B@5bIQ372iI+}{eH>HB%E*{*%QSu|`)FiM(spy5M`_fH0xhl+P_PUVs?BLh0U$KjlC4`*DqQo7pE=>1fm!}oU$;z5{ zytNdu={m2dsD9uG?r5^RP{6D|$KAzi~s&QGEK`dzSC_`!O7n;H_~j!@B1uj5lo95Xd6Nk2%eGv&A;A&~b{9 zk&!d(r+707W3Ar8*bvy}S3NvR5)((3r%HQE++7VXIdGJn zfBn_Kb2Udh+l+I~f=ld62$yD>Ug5KtnBD@1vH4z4&(7RyV=bx4EQbyqI(6pEOM_Am zTubr%`HbvrV?BHPHsXYF1;S8vcDAB|!WNv%Ok>%hh@__>Avsp9ytcNsY~~jS*wlxl zMq1Njp44a!iR8^rWa20}jJ0HbW_6oBb>+$xeSLj=%gK``y~`3SsFGJk)l2e{SJ>ag z$7h>79c)l5c}ZVy_4SpUylot(TBz#K;E;Nli33x1^^p)#!sI&&3W~d1ciFV0ggyDT zotoOT^xSYmOfLrVNNOpeWmv1bA^nL3W?sy$|6W?!M8d7iOtB(#}^~zUVyRndamPW^x?yFK_sGI zU?4umo~*>DS8#KpBWF7uyWq8s-%EeSbnPcx{ytvl4RX|5OmzjUl6s5cQ3&IvJ zO;rsIoRIjUfaqv_Y~p|ySO8m7QwC;cm%g&i8#mr9abGUT&$k22UCFl}exndp#>sW~ z@JsB1NJ-}>t9lX+qiWH^?Nr484#mcmI~fCpo#$%ph0o37)`Qs$jE!U zXtZ*XtBv(!Dk>_(#Kf3*bu%(EFM1GD-c{GvV_&{mVJR>7XR2YDnclA|2+;bvs);+G@Tm6O~XK$yv2i;KV zK=Y76_kPnWS5&&4o6kGT&sNo3TBB1NDpz~AP<>d-4aA%|LS}%lYhC5jSXTWT^XmX zN_U;Xkh-ayQlx0(hYz>)DvF9Eg>{l%y&@5VaCpYX$niqMu;t|Yh^qFg5T2i7V?MgY zGNg`<4uF)<^G81V?AkBocC-`7=ZkIWHG$(_IO4ok3!B6Fnr{%*1ErBrNiWIM2 zO`7fV-cf0XDZvZ4D$lle=gytHyu2RktMm5u_EeOVE32#CaY}2u_=3*UGcko?p`xOq z!oxX(&JWrfQz6WimzSTGdvC|G9P#emyXU?N3JPs5?(VBuS^Vnt1+%=>!6|NUx(ghr zsHn!8lQre!g2l6I|$ag@rrIm-)Z;P z3xLjK>&Foh`}XaVaGo`3HqM$fxOC~8^!my#Y$J27(xp+Z#ezWU$3L9c0P%RZxW>Bj zvvJh4xEaMo1~W_VCc8=nuV`5@sOMb>k<+L`>HsiTj*(K7m%rNa_E`SRkyW~Y?Uf{vU8$HaoWocW8%5)aCXIk-I+`h2j5 zfR9|~Cnvh{fBDiJ9z7!G)ml{&wb~NnIq1CBlqeA6F}rz;QCLXGePuyzd2XWZlGw#9 zrJd9C7MM$H7-3;y4yDMWoSaEnA8v2lx?{(VK~{71*FS&$oGMvXTI1u19@f^p|Kf$= z%X0y3tclf|!I9Wkt1U7pv;wbmZ+t3|*XZAy$+ihA(qk>*g* zQ|SUik&|wO&^Wpv1C&KaU%$w_1DQ9i6uphujiPg5P7ZYHJ@B z>-h5=O;mWQ`=1@IwpQn!c=~KPRZYSTzo%|=L!D}&rB5W1S~frDJf@!CdSP|biCMW8 z-VG9C0K_(J8GR_20EpI*l`iL8Rc8ePYEIJ=WGHT`xZnu2v*P~u7pfZgu1^UZT+;`YQBWYxzgBLW3{RQ z;!=Vv>e=t=iqDVV9(c#_S#dQ}tqKp&8u|tUb z{^72*TkQS&6MX+2NkE$&(9BYnZ*AN0I0Cg z^~#m+nCk4TEJRbg$u6M)pc&=5|){f(}oKEmq zUD~{53xbgd2M33wVu>);5hZ&qwC}xo+}(MRQZV4fn5xhJ@DNJ_@t~5 z!VKmq&iFiJkuqv?U0q6&uuG8Lvw@nB4&?PaIlV;u`uF!JgjrZv9zJ|{^X5%30mwMa zLRSTiKKYieE!A{&=`Kc!>*;kXORxUMtdy>=xgwQ(d!x9On)%ZK3la$l5fu!oeIzvz zK|x@qy~nQ*XaHO4!iB~Fu<Ex}L2KwKi^Z4NQ^cU3SbcAAZ(JCqteJq%P^P(54M*(j*QVy? zOndiMNfqq@4(|KtgRP*Ts2HyhM%)pgQ6hIL+pO+KZP=xO{G<7=l6pBdEY>6>Cnpa^ zB==7oQW+}a=hP>%^^z99CGxJ1P99zSg{Xrpusix1yX4ctw{L%AfpRV+W`(Y9Pl`0* zA!bYgrc9!btC04_vjMf$^ZWJr0!4|@o+pfdlz*cZ{Y}^?6J>Y( z`W4%HmGAxir%51Luw(5CZ%s4>F&Dk1<4}6_<_%&-)0Z!gsas8KCvR*1cHvD?VE2FY zsPdpX!9o;VR&{lCPR`gnM&wIP_s@HZ7(mp$AH((HQd9N(9Ut5&*ugA#R8&;-;K75^ z(xr9-6&UQ9`#UZ=s!rW$wKo*t=SOi^*3+4a542TPZ-`8K z0N0Lj9xU2^eA5!o-9ukgSVymJBU86tmtVbpeXMA6aoX>ZZ$8D3V&(U2SlyEBvQ01= z=ZXBX6#)*zUc`B-F5R)B?pxlEzXGNoOZ4cwcJI)azwerE5dd)~BBJTYIQ{0#uK%VF ze^PiXUzy|k`yLsd*scHnXvZsmuS2ld{eR75o_aO8iSRvO`rx6<-N*iZx`_`UREE^_ zwNp;(*=CbuAtr)~`sEHfBEN|3>q!!Uz?|^*t)N3Zfp6>P>vuD(+xgwy-E$?cy!ZO_ ziKL^W!x7K4xdGwU+S(dels-KF-8*jNQXDQEO6%8PBJOOa`ugn~0__D7s5ZoBk|639 z0fFplp8?S{FcL@`jKXY3j;zde+Je8J_b+cQ53>Em%t!n84vPjrG;RZpB_$!BFpn@F$QVcOLxjS~U_#&s(zE1Y?uk1lCx{hXRgkB@In)04%Uf@FScN5>Mz1@wGENQj|AT2pN6b6-$)-@vnUP~Y=d`fZ7L-`@5E6iRtT zMYN9Ijl6Ei5eLoB+pB05%BuBvf4f)Ts~H z3io&HEvpa)q2@XLVQb14y=*f@XXpH~F5~~6q@9%Cx7-f6W>$l=a?<7Zm6x#}KYsL{ zX=oNQZj-U_^jr@WkNk%(#>dA8D}}RXJ9~PhKt;E=YkSC&FY~^JlZS_w_t+D8&Lgym zWJ=J93hZk*k>_O8Iq`ym(fZA!dzff%`1x`WAr^5EqeTPTHWWEKm2?$1TyZd`mK1NQB^YBl0Zaw-)k$kZKq@*r#W z>zzBgVG3qft|Yt~O4TuB@#%YD%ly6X*a|$&<~D`aV6jGo46A%gZ)<&0pvppHzG?TIV~xc_SDoDE!%5OZr$2r z@>gx>QGEUSYyk7#1PLmFS6+mN@!co=Mi_y^7P2hyzAzDTgU$t6vMf^6{Wiyei?g~p zYIDJ}UkcA6@d&$DVp`^_URL%cGZN-IPFMULVO|@@Q|J>c~mj^?lrtGJWXP!a?8WzwhA zOB~AnpZaG8D%v{Q)3i#S_&#$lG-~=81g0yE|F4WAe||RV9ierY?0*szR@LI0^U2%$EPq&S zW9GMo8DoYHGTZve*AVorxVZS#pE0h|MDvCNlrIL4?fNUQ#S+fM;wmE}BQ%H}{m#*; zVZzs{7wwtW)+E}xx~#v%Qt;@km1b50QX!=p*C<8^s~?b$p3V4s50vCl{;996wXSZe zqGGI_=xR4@h<2yc*(cJ{P*r7EQ&yJj^H;i3A?sA5nn37FfA*oO6AOe)6jFF2ibVok z{2QcBXdkmfyN4P-5iidDvQ{r6D|3XS?{`}e5)5$jAYadmK1Jks&S@QlZrbLaAzErkWQ)DJL{uOdV7e{r0m?(vyYw5N+v zL=Qu(jRVjODM{8$opZ0-PAGc)^=tI*pnT`#(cF%Xn=TV_*p*fXj*v9x`6kGRDgIA~ zzy|f}WDS<4vRLaNaVO?grY=o)`*uokeN|QPHM|A|M(rJ{-FwM<^?l)Xgd-zloEn!?(Wj)ce~^-UlmjgS8T zFQThk+wnXsYyy=e78DBrW|W^sTU(nZ$lJRd$;t01k!S>%3b205-oDU%Irp;iPV!d} zzOSF6=!y+EaB`{4n+n^ObQ5AActcbYG>xd7rcg+O7Vau>mk<#6);eEK=Z6ddT!W$p z{Hb=j?Ts7!V_I{wv&1+6WL~X|gJNRsm6hh;YeuD{|9*!T`8(LYExscV{&@j1v{q{x z8-sj-gY|TEd3E2(kSZUsvP#_Iw#o$@#2ApCg+O4pw$4NDIeibw68IjQ_N3Ev>I54K?vC@zew~H-&&DQg_Y1jTcG9cVRG#1}&dOdeT#!&eVL?1Nd^n`Ij^Xb`zYBdllfhho zWP*GTn!Ts0DiP_)`ZZ=20|t`T7Y@IB_akzbQ}ixMN|1fwDrWz(dBT1duYKZY&X9k} zt6!wGXI+7G>5al7gf6HYxHaq*cQ?1Eq%Y0QrUJKr{rVLZ8HoZ^H1JzQ5DfT61Q6Ta5`kNhl{%Vh>_?77uP$5L z3uFUiCrB`1ZM+=!-j~@Z(|weWuhd~om_{*D(6D3cB`|tNgU;u!X06sowf>fzb{K0N zU$;;9sr=b$|4#hoxK?aT@BQiNh*2f-G5o&Y=fD+0!aheES)j!5=g+OX-UT*)oV&IE zm8#|FH#Kwfcxb}ig>yXx?mFCz^FJHiXHArOczB2|(SO|H*IDf{?eFd*p`7E_ho!$(Ji5;fDKN%VX6-0WL9%V8d0 zAEmeAxMtYik>xn0-#k(1v0Cwzoq1Ck zEN*T;b~lD_9Rd+-ck@Q1(AeSJsz&@%b>d3z+RB|fI1oDzNIv$}SW4^39B?FduujLD za``u`Ehk7O=`*&wFFrcZ-3}Tg zOf~VTZ->NNWv9o-Ex$g+k)`r~HZszn6eSrI5xo3I#6ZgJxu9W@xtZA;V64SoObwf3 z9t8yK6EG9xdKj;?dR$mIO^)tkSy@~#hjMqZD_GV)slJ^eHY)>z<4wt$4M5knp}Y+> zH8Dc2KMXvhD0fIoIdssoE#KG8XGRFQ(R7}8c{s1HBES=|2GL*9>2ZeTH#1P9*cO!W zhc`90wD59qNqDaH7rV|#+_J8zt_~M=a6t)i`?iOjT~+?~U+XJ$x$6zZq?=1kdk<|T zir*4Eeth~J!Uj#0)T-l^?=wETf-zw~oTGi~V+waOdgwuc9}#@*m^_McumwAgu+N6-s3@Hj)-xaGIiw+c?l6|>z@u`zVhK-_j&!_C0^Z`nRcY6Z1Y{jrQhEgjEx7}GCSs`N=3QN$wTQ z&d>70G(U%9@@6F0heFqzo0}Pwd^U$kmU9X7K55Q-(R#-3XRz`b*yZ^TTQ41cX*1EC z=kJTC79A9HNcZ++x54j2*=KG}H3s-;0DE?mfzQrubYAY7DOq`A$DO`pOlL$WDFs47I~bQaQ1Nh& zSU+$ZYs}*E+?L%JIVuBRybu8s7_mo4JI^CEEzKsBH%dF8|?OgxvD zI&CG|59j!PZfbh!`{02;3cppyNq&CeaEaE!jEv*r;`bREun9K1agIC+6 z`%p*LXu2gQCbpxtYtd&9W}v6fV9{b-7^qZ^mQuuII@sAUe$^SvD?qY>a?kx*_*#mu z?@8el*@gpGms%)_BHz6erK0kO3&e5cYk60f8|prA@1_x84?r@8GV)w@a&iJ8kXZrP zMmGo5BsneJw?Ui<&9*gS4AUAl1>E4nMzNv9)bzDQ!*XOHMF0(jT-oGlOx0H@K<;WonVL{fm@|udlPU zxXng#a%?&aa@c4xee}c%Md2!%6@F>-V9CuPh8aLdi+JYgdf8LsHqkAAkgFHGHL!kPhFzZK|yF@kK#- zt!~)m(w3rx!fEnacwcBEdd|TUo_L9km)kRrv#b3ibwVyvP7`IM=AEw$>x_6J0 zu7N@6rT9Pz&v}lx{(d5n^Vl)%Qp1YPuT+^nms!-x;4^_{W@K`N2tzo?M#wkk5;Z1BTvi%w1Tw&|}%!2{~ z7qp(qzm8d-PX?q)@BLocl0B-)8Dg_K!bA+`FZcIt`$zFYN)va(Iq zO%Wm|FK=KGogArqdeX?r_55p90|NtBS6AX?AP7)U?Z49GFI=b$+}{ad9tdrQPd{(r zjskmUmT3(nH6QAI=Saw)*tL3vbDr6gnkiZ@cB|;YAF z0oYI2es=Ab>}n~Ps0uzsYU+9`Mzd;v_~F32kYtSvxuRJ*uaNPY`!Yx>Hf`^eE|6cz z2?@TwZbhYyhy}`>FU~B-#txi1#qsuSj&YpvWS8G~Z)wckGs~FuJ9h%NZax5f<6A_x zm)Ygzh0uCy4SQ$j%{1OV-7L}`sxFtsxk83G2vkfy?p5`Ih~05^uq1EN1bW7Ns7m=N=t6d1LT1tTR=4%79YU)uZsRWK?u_>y;4FSX6G$ zE?{mr%TOITsh4f~9v#A-H99&9MgPITJL-MHQBv*|%{iE&sm3T@v-I2clKM0cS`r<&=CxR?;Zi}~bv-?T}C4xPL*(X=^FYZ>=`-^2ZjOfgv{&m}(o zg$xp?`@DrjZ0^;CFS2H8NxJ+#AEt0?>31*UGkk_BZOOBNNvxSI%aqKhe;{Zz--Y(k z6t~1iTr}_7Q1lucyolSvwDj7-M{tP?GXpS*hV*hW`r{`9V)j4W=DQu|=H^6fdw$Q) zr=NJ^=Z7$jU7N5iS!9QM1hE$XMoBtn%|1t3>wIT7 z02I`oZcqwwlR*(TWJvvdHo_n*NW>f0U;k_{J*(Du0-!%9ZBeW|KG zDfqR4kbrWaG%D%9h5(-{2+K0XI*43w;9-qXWh0YjSv1C>Zc3H_-)wRH_$FqYxzTPY zoU1D%D!932)@|U_&nc6{34d#|>ebN9~v~?HQ0DP8AM*UCk z?Ulbj`~N1vsq10&+p?2I%UD2KTH4Tg>G#N=Ncz7Yk|{oe(sgin*vH#@XlUr9+k%QS z*>Fcyvm-M26M8LgiQh6arrDC9yYZ^-#0*2Q6A?bsBZpkGnWqKM26feLtc z3-wjFZ=qjeDUxfkhFlyRl}$}=*Od4Fy#Z!%`uEf|FV6T>U`%GUdlol1eY{VNFjrtd ztYl&F6TgA78Wb6+Kst8p7!>i@LR;7f$kI@$$3oxM+!DA~!0Jj#^>lW+ez>#QdI)MC zNRY>ok>djc+4jTroWJ0*`vfs}?AJqJ=D?xhVd>!DkPx=us-~!?aqvq$WD%Q%O!>oE zzdIi!%svt{h3|jll$9U(`;S3jJ%8kDV`ILcUa?BhzIo0ums*Kwz7lnK872JjpL0z((r_o0^Z0?2rWx1q_urB_$rKk-P*#lm9O1 z6_q{XA1$t4g$(Pty7ULxTf;zqy&*ovgPD~zJvDXp<1T4<2NEQrmej%0Nafq~6p_Wu z=BS;xU+RTg!76Pdpi9@^7fg#ule)m=H-A#t$QT(J1@4z1 z%b-Mg1qBvi>*s2m%`njcX2{Erwq+is!EVjue^gONxiY`3PU!7yT_2+)Xwy}hx)W#EvoFufADe9!eYV833EBiRzO=BQb@_5uD)I>Go+WrY;IIO0D8|iUZRB5nrP#QI8hF1!PA&>wxjeMmmw7Yk|x9hSkU9Fg-g>McYUco!JZ{Mz( z*i=EI$yfJU(jMVO{!Mroz-h6u5}0+GO@D8pw2@6$uL@ouq{cP zypD<#F7{}CQ+bq?QBmC(lg4^HzU5D#gYea>SF7iLv$L^fdc&nja}mL7uqwFyF_BnZ zRRv305j^@N(!Jc=Ic#67NK{x@RW1fEaQN`u09vD%WGTs-DZ$Sm~0cf-bw#>U1Gf|h0SHbWF_wA-nkhlG^( zIA*x~8HGBx-HMWmO2oPimafiHPfzbr5eW&`*}dI~ z!ko5v{OsASq3RIW46|-)a;w8>()aB)l!y$sw#dURu}BKIwIciBomRh)Hb5fdCyExe zpDHRi7p;*9Ayq1JtNkywYc>m zr6D*N8TBWrCzIlsSYx+Q4~D`z=i?hfBoY z`-Z(eK>hRMhGlgTBIE;8$?8dxm2HR+d9-?C`;Hw)h`@A#1HQfipV;HzWL^aoY%K|0 zQpwQpkn1!FE_TttkCXT zK49{|7Q$5{jx5>2EiNAJ{*0$6y)RfCfmk5&16lo zJ#uY((? zdU~nnx`)OXz=cmr=9gbp;?`Jp$2qnLx0(!M2DaLG4UQygOqMqqo3b_=GR|PL`z7E?2_6)n z3;wovsS)YlL;Z&-9gqV!0~vdMdisj(z9&^CIJYJPt_}_komhAbi+rjd@S?sraU#gK z$93vt-vo(?Pv3;fed#wM6#acxDtjaEAvlXO`RZzGaVjC?BB@mTm~~qm3N6!F(t462 ztsUZZnj+=Jix1+#q1@WDAT}~wLLAn~Fip{x@d!J6mR&1(v}dvywo$`Y$X&aKwkM{x zTJu>F{Ej%c^l8UkqqD!fhjf#wnGhEI+tQj+PzwjtqdR~r*^&!R zNY-QztQ#r|<4mm;AfauWuR|@eVsDC+Y{*u<^x^~H3x~pU6+L#GVsm>hG_4ru>UJfm zbIrAxcx&gdR3_4@od1Dvj5WttM>_NP#=4;aU6Gf6aQ;ZrN(!a$?IjSNLg>MEi#0>EV#{H4T?mej?g4ei&gf5$O1qNo-zV4cD6DG3QILxtJ^HgF z#|mD>KD1%^!p#di@2La^#OHR4zVF|!z^{miFxgYABl;jLY_F@2q|V6jaC~xdjqtJB zBy~2Nt!#54oP(!z6zoLdyYqKtt2CnzvFzQet)g;po#!Yww+R(wwJ;P& z_o?@(t$A!92&(*~fGFV=zTK996>xR9#>lPp1uYmY$@mbtMuH3d#l3G|zKFUlWQ2x> zV%3mpfyGN#W-sI(wu((mbe{fxYVJo7P;qT-ElfDTjCtsFr1`Of>P)P*bn5gt*L{Y7 zvXsl}8z|{+LIKym`N_r0&jKAUDLop1P7q$v!@!ne*_zgkq*?%}WO2**7u7^H81_X) zt)b=vsae-!sy~DaS)ngbs|=LxK4}lh&d}yO%3)PgxfLL%?V1~Reb_)y+5CT$y=M&| zXR8|U5~gX}cBMn#=FEHZ`lR!!bUm%#kz>c?z(H0QoRE;vL3Z2|hC1uxfe<)(t}Pmp z+bUop7Z4OQ`RHe$7q#{2qsXA3#mq91Cu5~ z35bYo+qYNM*SEB`PJMat5jnP<8;%vP){TFoSkX?v#h$;fzY-xcujFQC!sz=*F?;=6 zp@6*2#2+Ac^yg%7Z31BjF0Qg`uBRr{0SoW)`L8{Kc@swKRUl~FQv~F{_NUbVrx|qz zyrrbyAYI57Q4Im#v!ut06Ts%1H$MP`(K-k-WJ4T!E4Oam z>{o6Chor0PGE!M4Q$XN8k^1K5oa%qhjpkEu_BFBjkyNp}(H4bz22SOykka+F<;RE4 zXr$|(gfk6n%dv4<7M95H@B(ll=ovb9?wtG)TEk09O7&=^LjGr=rzerDT2c-XQP{w6 z#{BW0af8frIHZ8JBLu2LKL$F;if-zjbTw_ir@|&tE?j(JKi390EPqu4-Gr zv`gFAl%2KyPSs|z6W9SgXF(A~0{`U&cvL)lZ`e8a2ZA=a>H&~xM>7|I%VjOC&v^}X zbwVdj7}kIuy7d3@sQ~&QC!m%~#TG(s$dEfaHil9-+tjeH`G4H^pJcR3!Qci90ZXM{ zd4IKgJ{nm7#t}r}>@2+AcW2hZD02Z$+N68`vA4iIsZt6C0EB-Q3XcAMBT&<*V~+{$ zK~bWj@})Y2>nyPmt3)IcpOW^W>kVbCG+fLeQ@H-)#_{?;DeM-DeAljt7ysDg6g?~& z=nJwDurmuyLamX6_c{+&r^6#OS9fN-ean%)UYY*_A-%oGS-@4UGh(2wmh$_=pM!@A z3Op@syD0}mQ(L2H67C!h^d0sSoh;u#W4C8Rw->e;01Nr0tz8#=QUX3uI97Jk=z$u8 zRT_{2jVS${Db8ngr^$(Rf2{`8RAVpRN+gNqkm zOy2x1G=fV4aN|#OYhe$3L(3z%eLdl_n%Yw|ER|J5v_~1$-r0#Q+x`Cicf?|AcN7XP zYc=R0Lnnn{C8Byt3OAhm=H|mN(%^qXuc_$C-$D5g*DM6kB{$9U>UW=(2^oBCzo?KuK=EC@}MQ02TIJ%$RF zo}P{%irNzi9XeFI3tXol_TSocFX7;k=xJz9z()>0NMU|{cZqvM4*XlFS#wbo=jNh! zDUn2^nS%uGh%vz7@aa}M@0}u03VGJ;H^4SS8pBMu@Gxy`QZ_K~MB_+FNeP);g>(f! zW`V#4ucRDgz1igo%qKSw4+oGee4bAN;pb1Qt4%PNx9C|e*LNnH|>QBHDAAG z&5o5=Sz}Ugjg(v9sNf#YLCa>P9X8DAno*)=UP*yyO4Hk%oRBHLC=g_TLfFFnV`E%y zEYpZ|=uz=#j5~|3qhEUFt@lcG1Obt}$x#l2!TaoadjEj~B_>r*0N*}UR?^YzYc9I- z;m-8*^k`YN`B@S=__l4^may{bJ!k^GVi$*zudlfmu!G3gxG_|XULW<6`a9LKFd|d~ z^0sOCk;pu6WF$+A7%IlM@W((vJs|C&%O0F54AK(`VjcEgKw#QEdyd|WA08ZBSsF|C zXXHT@M3=UYAQJ^H_PV7-(ZVF+_aXudNRb947|?Wpv+YaZ2f-YnpPJn5;rm7@ssML9 zIB3Gk%GwtqfCWO~TKFfO+{Mx+^1pGMrXe(g=!!#YRj@Cp4?Fl{TWjz)%)h{ui|)hcmY1R4Y1&|Zx~*!}b4L&=)y2Sl%58KUS!t3+aA zB8H9!6d0PAyqdP;=b{SbGmvtc{*I;x;^k~JY8uF;AiFe}G!Aj?+Vu$5YB-~hvH-&X zZu9Eo)_(kG41N{vDEu6*mq9Err-ACJp~K>0V(8X+G!*&x@fRqzb7E%KuV24>xdVp+ zHQ@qsF$C}IZI}>%PV!B>wYZ4NABeVX3G4u-A{9gjvMOi=l_whs?~~#0+6{ENxU_`h z`P7~4oA{q*G0nBSdQAiO*Qn~A0cZXfds_+c)>e(D7a-H_MPbLxoCZS~P-Yp_?*A~p zwD%vV?>%+s1QvMC+~*4oEcUkEP$pl!dIjUu(UkP8buPQDkDVJ|)&dkd* z7t+Gh5HO1UEG+PHs$RSp^z`W~$^VLeM;{74Yb|uNMMvc5DCh4(h*=DbjMXOmfB9Nv z@4qt3^z;|-fsKuOMX$%Mu)|#CtumXmBl&R%TnQlM@yv#)rY1G-?q1Y=xX{m^TG#}T z_5uf3_U}gn(^K8fYFRKB)?k)TpWZ-oR#sL*Of2(RUtb@3)IfkYqGkG|%S|n)zya8;3nDWj72P^Lb-*G&nhml#hriiqD_xjSYsHcY#UG6elT3BGv=TPY%p~d3| zs9x(i1SRVj=tTmXsA&_R?q^z*O=STr9A#%WLsAEvJ1-}9(IO@y!V1dXvj`!pHJisvm&w=@>iv{o%#7Hmw%~G^aDv zqsfr8mQK~@VbPMJt*?JTrvzIJ>?E02K{(Dj)dbRz0^-XPoP)?nH!#8m9*bx944E1l z+M)0r^n`olZM8f01IR=MI=X?8kz+;n%}}z%#KL$u*xB(!04^~X#DS5YKQnf@gXL{Y zhp6N93w`Ktfgr{Jn|mt)2PI0%hGOmL4%DlW>zttE2h>S)tgH>yJl?~`nexhVe@{Ed zi4%<-9hXC%*4EX5ZdjYh>jf{Z5xwbEdU{M$RNXUg@5?@^{K;6vhA&^pAvtNQ=Bh8K z2c#C1v;6%0w9x}sEG&+?sXm6dBCVpkmS|kI1mlA8^Wz`j}-8E+!@hwodor zCZe$3HGkLK%t z^v)w$pz*xwbz20pbOWI|r5h3(lpfqx${tu)J^s$p zS0)3uOcc|=I-p@%#YlLF5NkNV9p(+3=4Hv-pF29jsl%jPekY(T7Ybz3j7K&`o5wqs zKS}40;2Ao*H6y5{W2GP_TE9g9Nk~Wt$VvE}umStcZ;krv8n{N;jYh2NMidl~J3bB* zi3n0J+n>?5{~Eecha#-o1Qj4AaC_pO7aZkTU)KYoOII zKM}~j@?pcw9Duiwpx|iXZs^MBxGxk7kMQN>{6B&m;sTCzM@2vsKQ&~Sb9NjTW1{rO5P zTGRIX+mC!@16nhaSI;Um8}09Q4YhqT72L0T?5!lqoGeNQpl+~*5BG^EsjL41Sca92 z^|S`HCK}MzR-CJ3H*LhkxTd{9zaLw7n_M|)jbu)#UGxXQ=g23wraw`+49NZ_FjuQ?)Ukg& z)k-ma`%6p9-1PKgM@Ge0FJ3f0E_HZdxF$gO%%lNcp?!Hgy8**ILn1$4M+A&dA-cJ+ zTe0aXVQep-V(y!9l03l2!6D0E1_P6mWVDlZ4%)pC5%@|LPS5VCqC;b5n{1UHx`dep zEgplD!IN`7@g+W!yl|8rp6WZrEX$ZY;GBLv)jM<-Z`_y#b$|z7nAq4r0$PD@yQ9iK z#=A4q*hkd4Dg&?y=wcMjCxGIqsT1TjE`!TxKYG`TV#I%)OF&$_qrSfW{rmS76=ry7 zjgZnqU*F?GLZ(wo&%XM<65lAFzx$ZTi(5MtqFRa0XWDMT=TKZ+3|d?BN?S0WYTPX6;`8f%Ad$g{`d zcO8&?hm8pov;y8?^M((=apixsKJw@nEnwUHFW$~PuI9CE`%AWY%&d%y2xY7cC1FJ} zOBzV#qLMNc4YF;lBFPZSkccEwN^Df7jA=ko6lG4OR4NVc_o}_`d*AnS-_Lu$&*%L- z>yN!RyVd%w-|xE4>pYL+IFB>T4~9F`End_Vnb(6(o;;{Nf8NKuvori}p4{EtWpj;< zRo<^-Phul5@5;ifj=`r+-Ff&hG-A-nGMY>UojgfK&2!c*p5x!s`o+b?vS;5$&WxO3 z^I)%vPLFUBKQi|{-SYgV>2kuUtLMXPtnZh!eNG+d)16`mgtP*(NV9K)c~2vwUJlYA z!{HwG(_QrK%}wtw!Lc552ERK$a{TZelNJ|t?3_KgZ0=~6{8eUVU2R-#3I$HI{+85K zlB{MreaZ6WcXcZ(Dp+XP8o6Rw)Ua_&Lh6J0eISl{ler8S@R_GJXZz-tchbjL4M9?v z5*P07a&1iiWW#2wmn}maJ+tT@wDj{CTyN3w%{6C-RKPX(bQvbajj7(fh;3v!R!0Z2 z{KX#IyI-!4S-$*zzaMk@1eUb$b!^{vt#!ZDI01rrWDHekDTzeb{-9rvnE_hf(Ly&k zJ*@P{5BoRDmM^O^*+ewogg#N)d%nk!0|)eF{Mly0F$BUnljjpvU&p`U8!TEXmH>-B zn@pE1e6X3P=RTa^Zh5xv|HV}TB;pL*1s==Zn>k~K?wU6e#cGnSIguUH-@-w68rL~- z^=?iz>cM;?r58K*dyq*?Ts>jph2WK05l&p{EYmK)--lVDNFH6m2Vhn`tvPXX^nC;x zvtWS^WF3lQmZ4@}rGU-KUArFk^<9jCn62%CTnQ*6L;`XGE67=d#M2F&J8m74q7 z20OSV@8u!Ezx*gFI;^oW75vppZ_bB> zk&~R7rc5g0&U!#V)3$Bfp{t&SP~B5xqLN>D-Fev9u}9Ur-Q9jIAnh;T?fv1Q9@ zfVJ@W^>)*tlKYP-6!~N@MmnKHwhbYd6-`FNk%C00lJ8u4!}E+*QHcFfBRPz?nYxLE zMRi_yoL29*d^NOb!X82(L%l<`|I!mfB4EeLviyKLq$dB(n>AJCMH%1i?~YE7aV`bP zDERzYbZsL^U>oxraAvvjqz}~R3jkeiWkj4BlBD6NR)Ai>V^)#G&6>4mze==n>dq36 z^$QIe+TWTV9=y{3l{QaFb<|*dDJbLbI7k)AM{?zM@jE8>4UOulGbhVTZ|d5QtNq?h zZt;C#@uT;(zWeq)MF}9qO3IvN6>v@a^0IW0jTg73N_y&+J+fJ}Xzs@>tPI^o#XaFb z57&0O^yTM4tv-FcbDw3oOiFIs%|Rwji5qmJ>RLvN9Rrdj-?mWG#bGv~=mtqxc%o83 zpB|ms5IkK`%zKHBB{blRZ~dmUZ(p6>&0q9+y2^Dc-t7~>@>nM@+VW#AqL0SoN3)%a z>P2xL6aFTOYyLOCO4YyFSqA>CNBrOZpx1lg50Zo7!-kyHRK1zMsuo zw_aU*l~3d~e20SRmMRQxI13WSs3}X2O#U#%@w@m z!_;PV@9ogF`JzVPdBw+Tt3KjPLG4b8uz2xembX*EtKQNrdT$B~?P&{!F>c$oSKFp{ ztPn8?{D~!o&@(JJc57*ADeH;@610@+bApTo3@+3^2sQ&F6wueqmoGuBq9-k3yMGw9 z8lf8t@7?!`!Xm%A%kWSb-ylqnj7}T!?13NQlYF!7Y*W)0gsBlVR*33ymV#ahmd4(` z5ai^NUuEkHR41XKoYh^2FEd!ZdazJo)rtKPs&ThyZi|U=LLlXRhmfuXry!+A8J5Pr zM!WtQc{OcxQGuAUnG5~$iZUe{athR*Gjkb5H8-+jVI{}|S}(w;7p4&(zCwQ3C;&I+>ZH}hE4lg{;?yR({fh;M$1^MdHHzJMfoCHp}f{uQ+H z+_^^4Gg0WH+cn>2Kh_k5_LFjABKP38=;-Kk=Y%=p(R*0nWZu2o$SAPxngb69O6K*# zT;c5Og){s$2K4X0V{GiBe(LR0h>7_0oVv5}+0AJ@VGbetS6AMmpJux*wTHW;@{@;9 z$dd$k#|^K)?=eQcP72>@%FD}z|DuVB6K(7$PdOBq8yg=84pvd*hTVRkmKtSCqgB2D2@Fp8s#593bJtb2H&hQ{5a*UXA% z)O`oNGVH|mATJQgCMq&mCKP_OY_%U3o0p%D*lRdFHuJKv3bQmk(zwTU*9ylbO?H4| zY}~Y|@}J5&&D~$0o=GAs#bU?^PEY3bsKD!lr`lte2ilF0p;lexSp?3$^6p(<;)~)v zPnoQ*ba$W24SM$Q4M}zXX0Xw!f%z1@24kWaZvxpjt8!%K1<&3)T!49 z@)wE3ykF@&f2l7u&eiMf8%WActH0-T_5AJpGtGBLo8E7E`jYr)(~OKUD#3S?zJE8j zaZ3$7@Vl2+==Bi_lJcf=OI8~XAd>H4$%BQh?<|b-(>#{*8`Tu z#sk_meJ50yll9EZ^o@4n~{C+iLB<|f3RM@wWPmYyi^<4 zT|WQyAB3^Gchvu&M@#388#T-J!)f-rvuo#08{5fs|5vbwdwk%PG~b4?6j#*KhaG

n9y2ah^VN(L1gkhMmu6_di-84BDXGGyGAs~qIW`ZHi8j6);4YW zon~jcgTOcp44UrTP*J>G_jq_{C>uhY{VZi^acL>pCnxmz5%vA;Zgr_m-?mMOe(uQg z2wupkE+vp4(;JM`L0FYhNNEapUfQ%h$<~2!L8}@mY;jJ9h}g`#&;u1$xJq$~>ZsVL zNt4Wsj9AV3-`|Sos+Z8XmC~u8pd~goKdUO%rUjioJwqyf-8Lg&BL_l| z7kciT_NY+?1(BC7ol`X2TT)MQYA$N7A-R9(^yz+zXX)sWNz;l!yN+QGfj0#BgK$LE z(Ack2!^sZ>VN0KLS?a_od+WQ#0~_xWbM_R zZdOB{iuFQbDu^}|c_bzc(RePG5L=E#QN^`XC9oY$=9Df ze@=DOT~VBDu&IkU46QAYd#vb!BJo&Myf#-s`bMN$<-5&LwA0}hkmTl{uqG+@0BPuXmoJ`l*GBB@(T!{sA<7C?&tyo8km?Il>av2 zEp-W}G@dWzh*RudTs#r0U|O|cSo?0>)W!~1j3$}|2I|$HsMMP95Q%I5NZ8iLcd%}x zx$OQP^h_tCqV~%T4fBknPfH~Az5s^wp!f)(kb*NEj%YNOM4uz03X`@^!Qf4Rp$S`N z9v!1{b&N*+Jy?6Y>BV26d6czmU%=DxrCiJu=ZBc->)(C-+Ksq5;lwPwhGQ#Ir^~0w z;4I1DxcbhXGK3E#jfrcP*MI5txqJ8Rlan!Z>)#IBdmLICyE@B)41eD2^Zsa~C=GzR zDeh523rh#55FzAU2;x=6@-jUW*dr0>Ox<;e41zj{S6qP;Ys zWlCJ_t7J+H?Bc+;3eb0c{rU<~Abgf*(os#DG$bB~XL`q#h!qyNZ6acg;UhqnshsKi zs4aOq6C_Z!j>3iPvuz4RJ7}dV84m#YMrY>|2=~y?RX{_mJe43&AOd>(*={>8)UDX- z+B(FONCzrAoP@{{NpV1E{N>;YIGKi@I5B(9oE-W>7cBVt@#DQtZ8|sKMmU~6bt>e{ z3m6CZE%tqBNeKvF-p*R~HwY*Oo`~J2W4}k^1Wy@ib~)+p4z zJR1P7O0+Ag&e9i;+j^2XjkM6#O%!McALp=c-LsUGmscG6WJa%g9tw}rT3Ksa)fY7t zm0;Qk&IAYZWE4}t8a(A4kFQ5-AA9m-E>D267b6VhfgHJTBNJqxB0}K)A;A8Huc(oT zCa?yEGALx9OPAKN1cCf%q^xkQ5q8-Gex7R&UDp?gK*?z3G%Eq;xN_D~m$p&TK~pe0*9ZxoA~4Taq6YD?Be^aR~(I;mF@a{`n-8*=+IaUP8@19x_>=X z-T|zS5P&CaOt3q?tlTFav>6Qmt2WeC`W_>sK#uZF;W2nOLxkFamT%r0^7M-hW*s>r3B-#zIxppS_IZg;LA zU?GiINk_&?!ccF1P*3+ebjUykonT^O(qB3+mQIeB$;m@?br-63@Q1)}t_9gAXY-y5 z4W$n#X~yRAZ@n|SXxWiz$egT7$r{02 zj@&8#MPaY|Z%*_6h!YC~*zuYURcy{Mz6;{{ZuLj@` z9xcl$@u=s_%toUl0>B~yBXZyjvb9H7ck*PPdk%CkU z9T|Ozx>sRKFWTeo-enc(FOa~aIemHNDW?MO*0$}eg$tkbkgTxs?ygo75_V6db zKsg zv~AhacF{6lgOZ%PEqeIy7_|tj9C)1l-ucwfh^BHp(==JZK)*D1fJ;yD?Af{VNNAWI zK2H1+I^ea24w775`p+j(RBeK!;;kH6rhHUEb}JlNP&+Q0G;!kA=_VKUVcM#EzB^Vt zSY;}8Je+$4;Bx23sZ(`t5_;!amQEG!(!AzKiILC{r9iACm08H*Lur+yhG|Lp{$}ak zI(9zi&6{55Jm?@I^#k4+LlO%2v%F)StCOzYA%$w+n;opJTSxjM6fEp|TCXAe&S|~P z@n4Q9coSRdUbFr-`9!a`Km>rLBhE}au6v`|FoL3TX5GLRiQd}V1Cx6t63YVC%rh{M zgNih4L%vO9vAW zuk+anCx%8Q{1doyK+~&`uCpo9T{SEA_`D3lK43Rm~#%Y&WM1t*ami}NefJ(iUDDM?Ai z@o;gmF_i+v0t=}GK~>nSS{0eV@rl39RyiK-ZUQO0jxvc?peosR2wk2bXU~F(yuP}2 zM>H0tSkyQDnVhwi%YQM$%1aslskWK1k(!?RKv;KXW8q7n%ZN0YC3{4*|~# zE2~F2m36;TFJxEpSqP#4DQU)GdCGLOw)`pN`IgO&XLdWqrTR zza81&9S~vr6hi5XMZ*>O*X{!kffS=7B79$Ot5e&0g z@oe=sH!u*8^(onWzB;5J&73-8#|H0E2^wH@T6kEJ-9P|faz0RWvsST=clR8(ddZSh zaN@%Y2i1KARn>nVsb*O09JPDtBh3JRe<;ocgIDUUz4Au^I;7&gg2X%CePgSZyFg_C ztxkK zM2))F{}6VrfAjwvuv7P*e+y)jZ_xVeJyr$7&t}6&6P5l5Pg{YQ-Yo?Mojz)iu5N5s z$GSv&TcEV?7fGN#yp3R1*dv_h3oI;+W`2;Ygt!F&*}*#;-S{;mtT>( z5xO^WOd}WzbD)KoytH-m=8kLDFuQ1iw-J>+NK4Mgk1%-RsZ`zQX1XLEuwv%7c?n257=x$EW-Ux-%9=E0*!KT(YW{r@b@b0Q^8J9O-r?vguA>FUI60*R&9Odl^V zMu1Euw?aF8$JOyN%%;x>T;;(R95L^4 z+Mo%6lZ&`AOiN2>Z}rB|W0O$MmjaYWSt+YAQq@eUT z3;FSWgZBn6QxPqM5lv(&-O(blV21y`HhI+l0Ae!^?0Ar9O@aEdjGOEE37&*7r`YBu z3F+U?B#w;Pt~n_3!)c}9m7lM^x&-f-w6uOf2wTyys!a8}7?DF-iIn!TYYNH^;lOC= zB%{`U#Y&FIN6*a&F^{A42TZu!c<=tOJF9k8M^2u`GdJ7xt%i?7l`{sUjw>Lc;keLj z-DSjzmdBGw*J!(UaCBrk)4_Iju!tm}c;b>~?E4dpWJ%?bLsD}u%@p-!%a$FQZ=>?+ zJZ|b$4s42(Um7;}RI*)v+>NH%w;U0rK+nRU=_VfZIH%+vic1wLIRfAPtkAs z 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

T2(37buAy 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 literal 53449 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 oJg!t=13-)^DlIbH~pR!Ob>K3le0 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 z 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
nBoo41|IU54z$xWI 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 VzqotW3hBh@)gEanl`1?B`!B=&?q&c0 diff --git a/frontend/__snapshots__/scenes-other-settings--settings-user--light.png b/frontend/__snapshots__/scenes-other-settings--settings-user--light.png index 0a0cb2ed46c66ea99258fff98c8912a5800608ab..3c87296382dea658f467cb3e98cdd58eac64e20b 100644 GIT binary patch delta 104173 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 z zBzqbM(UfRpAi}nIXi%_6zPL#0dzZi2DWi%9^Y#olku@r324$fGYv0zCbT{gS8v@Q1 zlypiB{w%wmZa-raR&mhg~pS)M962XclBMGPy8}NBSN)TW9za6>6ZFGq;}v^lhRagG#k7gg#X-Q$ zabI_Ww7X#RzyA)6;jk{NnM`sDjbsXvoj2vP_|RA~z2p?j*NGf5__9~A{?ziSqpQ~M zmztOYbotu;aEF5ISYm1o_*qCJ#=V)qF1a3w(&@tOr$(2KFhOkDl~zgv<$Gi&t?eRH@+jR4YXxvQ}wDw*r`V)0|)Bb!mO3@4Q}01M8X6_ zQa4RdB2X70uU*(-+g9%H$v0Vj^q*mWjcKupVQ&mM*AC{Xf2#~v&26sVahydq2pTHO zK>tYZ3VKBV=9s}Y$<)s7uLy&BO?Mj45#j|1Nm3dDtuD7e2$UpJ^=yx!^QdvIG5vGw z)iC-m^$6EFBd=j29g#VLoi};236K|*9JH)pUHM8TJfVZ8%leHM4IFsl%dE6(FMq2W z>wC-_@iW*6HRuGez`pu8Rt}j>5E>+=SiiiMA`~V7m=1HY_S6gLlR3?LM})QvZJ?zq zy${)qi%XSU{2f=dH6+4GTwZ*)FuX4veTIAt$Vz20Ee8z&>FVxK0k7ZR?sypC7^Tc- zKaF0AZ;pUr_}iQ2i-|8*r216bA1cE&PY1>3Ye!c^j!)CNS8MG(Og~$6s23HP%P9)x zO{Q!DIt9t<#ZH5-;mUP|#T@SyRwbuya(gP*M{-gV@|-HMTxnmA%0L;)PgUwzU2{h| zBPkX8n~mxmKa(;fX1vqRYFIogVl!dUbU;CsU)WW^4$?VX_%v$b^umWCj%ierN#zbV z3PK+jI)C9%7q&wiNeQvtulKAT;lr~|L#QMGGs|xF8REsvx5DPMOYQOf6)l&GKDVM3 z5Aq{pSg>kX4!c0+|B4Qy(~rPAjIP<%sq|EjyT+~je?$U8q^`E9<%p{_|NBmu)6>$zw5 zN}V?4bkEZlO#bF47e)1&W~Ixcv~styZF+vHlE%+C?LX@~LU9?SoTuTbXF`I#sp#b-F3jAJ=2gXUZe?b8DBgKoybj)bLUo z81$Jiv*d!r#D|l7r$G4&<9ir~BCRso-FK_4-KsmfH%EWxuPXP2R zs*VLDvd1@gWJAxe%V<9g40!WPmq&Hz>^aPn#F7W&Nyuj?E(bUil5ynzaAGT%Ps3K4 z@qvq8rZjZ-D{6>e50HQ|4C#6DCqpDvG-L^TMd7&Gd-8&%tsR=01sJ)JCE-+lSG2lz zeEgpBSm02+cO<6i7^;HS=cm&5)8 zj4@fe%Y#W}wBWDA&s=1GEOLZu!|~CAl~T|M)~!bZj$Hu{KQoPLJ&7c zSUeY6#+U^`G#{67Mpes=yl>^E5;#e6xeIMok68sNX`l(#*7SHUyciOr8rn{Saa0@T zS=op&@6w|nq`A^=X6_&9HU+@z@ke14BDr(az}0onyzUFYefU)SSX|6c>#wV7DV`*Z zE%@`V-omm)_pWPTYH!SQF@5=!#-5(#PXUIpXM22S6qnHhG$_s_ca&FFtV{j}v1a#l z`>X;FJBWwwM`dutB*a>WBVL`&xN7Upy{ch;uQ~U_!2Q!oV_}2gqnW!2IE-k%TaYhN zk(a)YxIO~9(_{F>d^uU|m;W^HZ&T>xaGXFx?X;k_#aNqbwwGDJ&bC*^Fh{gh@56)c zv>$#D-k6q^msKemm_fRq5wbt;eGq8AJ?AoAOkU+XU-CMZP0gGTBQd?&lp}t&difg8 z02kQ5n628ZzMr!1B`qY+4FWH)-L^4q%$LA0(10n>L2RX=*VZsQszo*b+{HKpAjCF` zP)DmI@5FFFu5Vz~=NWa<^z4py-wtf(bD^EwN$(7m%4bxTFCvU5Fv7>^+H6i`&t68= z`o?)SNj(%t`8AKj+|xvHV-{25S=F(e$_Thn#|`+eCSsUjUke^WC z23+ziDK72kEQPUPGC(k|!>h|g+;5+xs#fZjw;! zOe2p9%SaVfZIT2HyV9~h^?|7fU8in!oZB#@MEgI^=?^cr(ko|42t*vSPhm8$|94eI zfC*Qbudm9+5p3SLBorn!&XgMdh6g}3k^jas>9oY4p^D&V{4b@_Zg8sFT`zMU36JU; z$z*MzAqz8W>?(P>IUQ-7sT}KkaO)52wqf*gHidTx^S)$DYaOU;EqbDaMZZ$mOspzN z8n!JBqB}zDcD1i+!JTDpmzG{g%f(?QVkG&`?Wh1U#Aon5EHeiZB&z@B=+6%&Y9T@Mu;9Mt7-Ha`jPoL9M`R>PrxuG z`7>%5s?*?8tNy}%!@~UEmu2sff2kxRbe5a>S$xM5Po3re`MA!Kw*|6U>5m*TdquiK zvEmfLM4_pF5x7w460}e#TBnMpo5l5@^YYD>_*==2tURsH*gis102#K)kAHi=Vgszs zQz;SgeJ{W_ls&lbbcwn0L)@`cI>#VzYe>y+U*&&7{N@ddw`2JYM)OE$M(Iy$621sW zUe^2{`}{_qjLrMn-R1HLp*qAufLb*-$8u*VArzvizUEa>%%lG-pC)KTg)K*KuJwdE zN2Xa>h1MWa5nN&qaMvtWGi)*PuqA@mpT8==*tHK-s}32yH3(fpB>#JEVzSuWYfABw z6awOq(Jsj|`u;CkeED7i>gN=15u)l5e{xrTe*S=)J+^62E`vPMfN_mh#&nd-qUKik z^9iR(g1OH=?pB`Pr=HXY$teS#N#3%w%k)tUvH1 z%m4q=lmJFoLMA;UgPtyBPN+Y#7ZWXpn^H&|{W)FGNGRUZMRUqHhp*OF#znoXhx7_R zD-lXFJ5&QTVhu1bybJAo=_KvD7|SQx%Oblq7b$Gvrwo!blu+F#T%CMwad z6b_(+K38qB*ase#%q9>95jb24F!%xu^g&o`cxDkCY46O1b}m2fGF9rCE47b}buyR} zn#%9+3oe{wHQWqIyJ3Z**$((7k5NvE>(||7KOre5ROEc4u>vQGxtj|(n`0^IfJBCG$jvGRd%IJ&BIodmTt3cKXurSC!WkJl9ZCfKJHLK|gl4-h6Cak_GppoY%6NKP} z;AxwA#l$cTxqckHoG0h^%SyMVOHPNSLH3+JQp9KIr0pov!zFmj)ebo_~d~F?{SV~@~j1R#N21n+V++)USIKo8kpj}CRlhpy3{N{R9bLS*NN#X?A>(c;6A3yBs{35K+Jj%S!U1b#_ngvDki zKP%wy(9%B7t>#WcudS^@3dc2Bxx*n*O-r#OeTQ_eU$_?sb~z7hLAx4sreU%qEpV~A zz!NZ$SBtD|JI1P~3JR#uPg;Dt6}-T6UaU}}^8tQyEIwnoRRWPFAbVmhyhoZ|HOBg6 z?5ckmZf-ZJraOyu*;Um%ai=YzMj1udD*DUR&J{QOL| z@4}Q7PCQHG*V)e$Y*yFQN|69|!m39t0!Gu!MzXkq-SN2v3oYHp zuCBrzL&3QHzhduWe^w~51)3g2q?s`d<{F}DSXgB7sZ2H&{E*lrOC~kdd!56YrvI=mx1Au#zT8emnUlAW+{v zFjb2FhzeZ-qslI>wXQCfpsQ(blN6XK0TT&=RWq>tZx9HThHSy@CiZ$+^JX^5J-+#) zw&l zttfNvcjxSy`y-aaFSHKDHuLIYx7M6F?-_2)h zYbvAbC+Fmy-Zs7QIO9np_vq9rX%{9TKO?|qTbYIec>UtSxed;;3S-Ry*m%m{)87Pjm?C@7OJGJOv|H) zAs;=o_(!ivN+jriV%Cv3zB zU#dIZZmx6W|K%;wk6iai}c)ok<$s<62Wx#VUR8>RK&m*gj%5fC9&a z2`ThwqQDIJ=aX>AJ2Gdg?xNrDTsOErGrund@SgYlTao7cN`aC9`D2)v5e*MNK|=Rhjb%QC5N`WnM?OFGBZ1qg5ccA+o_uGy_w;Hs&JIwXG2k~{V)ccIR~sLqw_P>hD<_b; zR(l=FI#r2p6Ff->RctWg&1itWVfclbJED;iio!Qpf3Bp~evy(g!I*qYX}er`ON(|J z;{4u53oAVn6<6syTj2!aE94_K5n6NS?x)Ye9y4OuT4`^{O?Lj3v>gE2Y`8@e)b)v7 zPsQ>1nJP+Mww^)a$<1KB#$PtY@2<}BimjJza40E)9z&;47JHWGEe0taRBWy1)ciJ&&$pd7153y(Q=S_D$!@ z+H5YXqaH?;O+y#j!eoeI|G{A5dB1S6MH4+t9!rIG_YTYg4`}YAh>^+X^RE&=#G+j? zE&j9r-C<3)&Rca@F^t}%!CQGq@x#u!*y_t=Apwhl0s;`0BnlRo23&65QGg;LefO;S zgP;O-FJPi6SAJu6{e$TboyKqih^^D~S5GDkA2hjl0)L?xB0bCoT*pW6h_;sw8?D=D z{T8zbUV(tXg~@2~T*hs+Ym&Hj>oTAOC|3$;9n$1e)8z8|*Tiu3pG8Rfa-Fj*-sOUn zH>^RG=|teaePN~I+jFN^W5-X%%T2R{@n}#qfS|QS=Bt%`SI|9z27?9z0x^s46hHX3%8Kv(avHkdjdP&3)*`gj@)+sy@5D1wyF28RyNbrdh2Y zT}js$L+lQxy^UsEbu&q?A@Yr7!w45ZkqBJf#wJqG4`!&J2@8iedrgM&AH1X#XWM^@ z6EKtjk$GF)6MaR`swlKtWYU&R|8x^B?onIcu$!Pdobc3=g8~bYtaN9iXCT!~yjAkV zq5bb^p*`_$tu>$7ZRytOwuU-zl+-F255h!CgZXy+{{GdSPeC$Fg8y$?EikgKnwBB? zb`_L~>yM_m@>%^C=rvdXG)yiqUgIuG%i}**Jnd-Djrn4TT+H`W*E!(yA}JaS<1%j= z#kV6udoPm{pV#MV1}>zBVRIAj0voOR6Dl9V$iK`|#sZ;kfhMWT;bLb(0$b75*Ep(A z7FQ4^%hvPw@Vuiu5sNaYm&%8zNv!na}*1CnlQe-LuMd|#H*WDtI7-< zqK*Bf-zg^1O2_F4=nTzMP5G7Cfb%)7_0Kan%Ko*R)`DmC7lzaT!l)rIV-A*0#9RG6 zZwC0dBBjy61`CzIW;lC8;LRGjjMc;l=?6hElSrR+lebtX3iQHbgCuW`8(lPYs(UA@ z1nVcL&#vG4-V=0MtuFYY?mJ*U6QIwX=K8fFgaOTpZG!VV8l1+BinqjpFKqjawZ$-` zduvR0b?8o3Y7Ec-XfRYhc1P4E^V1yJ=SqK1=a3pe1G4txr^0hj#<$0Q^_?ng(UuLn zhcmz#(%V_=`eCs&FU$K*`*k>_?@v{Xh{up@6ZPJvv^NeU6#fSa?Xg}R9fIua_=c)! z+~N~2G!qB?qXR~s!N)hhn*{76^L{9U2R3AJ^0`BL;u9T!YYK}FIn#o86j~UL!tQ+7 z=$l2N7yd#mkwzoNf6e#lGyQr6>55}Rwm7>vUa}>PL;2f01~m@>|EUhvx{|$0CF@O9 zvIV;Q<?YvpGczy3}()le!%$JbIl zuyO!RgphZ_NDFvs;7!saa@0UemV^?X!bShAqrPVkc{XS;%7G>|*49Zuym{MfZfv4! z{FwYSu>gU%lY04u6DBbXkOm<_od6euoRH$(GoS?-U{+IbKRGde6*M zk(5>%l*={9g46E*Fhtm}{+Ffbi!m{cK4AE^S-rVc6qA!yT0={Hng~14>$Hn=f<)QG zgN{E&`%pyZd0^0p&NnRiK{;W?eTdE+5TGv8Xz(gCnIqSmv_qC55vzenFuk*vDc%B2Ue>>HdchRgn7`P zW9GBBAKg^wnjmKVvXqLd%uWE#>4S>*WNBfgB+?JDk@;Z1!zX%$jwZ<+YmY)2`I^$%mCo;`AGjLDDzV*d>veD3zk_%2L1b^+pl~cD| zFsV>Nl@x|?!RWr^L&;Q<)y`cii#+( z(q9QbfYA4JSp;a1;^;Y^VGiZc>OQK#y(;fzyTjpqc9x+nUVjqSY|DT)i!j2k5Fy_4 zWULg5-FXxJCL}#G{!Tue&EeSVNf)d(qe6|^y@wmZd%-J!4d9kv(4FI_?F%4PR93}mF3oLi%U$S|)p=LmOUn!T`M+LML4%ta~t?n6`{4{KD zUr*-zI_4`<(SY!fU9F|mYlB%F^EoiP&lOi@Fz4rp`d_bQm}vTGs*)X|8yPh3#Z2j> zwzeZeH3+zW1J3pPW&H|Syv@-Hn$T0{Lm(?*Ej?gkg?(Db7W?&ag*>+Wz)SqIp9cGQ zii=2?y1ER1j0;aG`1i(Iw_2)-cpxI5zkz|3?XMuR_ws%b_Al{6$@cXu+`l ztmd^1bw&{Dba$*+T$b2b?u^;6p`&3ra>CL`zozI9f;r3<_BJ67SmLs|`;KEn6@bhv zF{JUKj`}gPeYndB^VV5}xmGFFuIAQ9yyaMC&@ne7M;|&Q;n)nx(J0ob?@E zsAfX>Y?jiRaQgWC$}$3Ysp3Wn!t^?66Pcw|fSU7sbs8-CTvJ;Er*zgh$s`Ezi{E+5 zrN8U%hKN>O1W*m7Epw`N(03z&(XCXQ5`4*ZHQnetOtK(ZTVc^3YV?>n4&dMQN7 zw~q2AXnm$r2_E#B*TeQ_t}ap-geA)WP2lKYuJgW}nclp%p&lWEv0v9V6!zsTIgSgv zlapz=-l33Dp!%kZEa|||V=#myd#`MMTBF0l#Nu@U3Q0UcBKixhkbICj3bwk$=X|_M zGx0|eN{K4B>NSFxuNkH5uQw4p@hY^>;kl%beo}p|`Or~7;GO&N zS*CT)(#}jqfDlaNXlRf+E7gNF5Z+nRX@yR^5=<;a#t;b+zjiX=7;jNcpN?ce7s$)Y z@%$SR`M}w&MKtx-_t6+8HZxMmj4UXf%9X)qIdR9TN!puBVLQB_dkqX#e=cqg|V+)d#YRCN@~0+ z4eBrM`2&4Uk-^F~l40DU!hLqt@*q$shVqvSCLcpr5UNl9k*t{_UL-=4;^)f{i^OuKkB`>o{9U?f<86_Kq)K@gos^k;smn__TRFuVqoc*&zibx4_(IGwe|0ltj6ZP^yY-ajnXz zBfw~k+O{~Ml77B53gNyr|E`8*-;e;^#DKI-_Qe;=H zzgiUeM31Xj2joY}ubo&HZP_Dawa&O3*|_0S1(OhpV9cr|{I?fm1e1t)?F* z4O{j5c$OE%mMI1lqJ(aRM-aaE>q9E59d@)T2dd&1O5E^&Ma*rD zR?eJ}J%_b)8zy^W1r4m#9Uj zmK(RWsN3yMp0}5tThX`VGzOwJqU7VDfvtW%WHvGaq(4`fWj|75Fh&c~xcRbdYqJG& z_eRU>mJ)A{V}Zd8bVG(L{NCB_hJ5)OvF_NSl)X2iv?f1i=ijKfeIMG~{5<4SA%I*m zq7{YVprSNTb~3>V2$?}viq3HXinao8zFgZA4l{%jVw8FFk5C((jE`F(;`tBf;*+)2 z1w9-9>qvJ)CpR0WlcQZ0vO=glUY9Th1Akzla|j_Cp2*nm#1nx+Xhhn8P~C5lv$g7f z_l9$5!(e6@p>%&Lt2nW8cFkJW3_X8?h|AMO@k~VS-^$7N6%KmzV@-R79R%34l2`^1 zj^;}PzeIe3_>VZWL(jTYXc?ki5PK*CJ1Ts@J?KF)?!3|eMiBLBr9c}Q z&b^}nnIZPc!U~}@8i903e9-ZHO9X~IILw*EZSP~0AWf@r&irDFVb>~09sf%*1C-!6 z$|8pRaI}|mxFUT;#}(BP#Ap&B}uy7&_!OZ zsf3P2N*u>m6t)EU#%ZxClfNDc-+|kF_Z!__J1%bUH%0A;~L5g$cZVO+o>tHWb97sS5P*|GScKx@BlOvCy6x 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%0D!JKl|I9U>EnUFw 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 diff --git a/frontend/src/layout/navigation-3000/navigationLogic.tsx b/frontend/src/layout/navigation-3000/navigationLogic.tsx index b1eddf98ad684..b21c10bede17a 100644 --- a/frontend/src/layout/navigation-3000/navigationLogic.tsx +++ b/frontend/src/layout/navigation-3000/navigationLogic.tsx @@ -15,6 +15,7 @@ import { IconRewindPlay, IconRocket, IconServer, + IconSparkles, IconTestTube, IconToggle, IconWarning, @@ -420,6 +421,15 @@ export const navigation3000Logic = kea([ }, ] + if (featureFlags[FEATURE_FLAGS.ARTIFICIAL_HOG]) { + sectionOne.splice(1, 0, { + identifier: Scene.Max, + label: 'Max AI', + icon: , + to: urls.max(), + }) + } + return [ sectionOne, [ diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 175698ad85794..b49144f9ada51 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -766,6 +766,11 @@ class ApiRequest { return apiRequest } + // Chat + public chat(teamId?: TeamType['id']): ApiRequest { + return this.projectsDetail(teamId).addPathComponent('query').addPathComponent('chat') + } + // Notebooks public notebooks(teamId?: TeamType['id']): ApiRequest { return this.projectsDetail(teamId).addPathComponent('notebooks') @@ -2309,6 +2314,14 @@ const api = { .create({ ...options, data: { query, client_query_id: queryId, refresh: refreshParam } }) }, + chatURL: (): string => { + return new ApiRequest().chat().assembleFullUrl() + }, + + async chat(data: any): Promise { + return await api.createResponse(this.chatURL(), data) + }, + /** Fetch data from specified URL. The result already is JSON-parsed. */ async get(url: string, options?: ApiMethodOptions): Promise { const res = await api.getResponse(url, options) diff --git a/frontend/src/lib/components/CommandBar/ActionResult.tsx b/frontend/src/lib/components/CommandBar/ActionResult.tsx index cff7c24e09d2a..de97368c3ff66 100644 --- a/frontend/src/lib/components/CommandBar/ActionResult.tsx +++ b/frontend/src/lib/components/CommandBar/ActionResult.tsx @@ -30,7 +30,7 @@ export const ActionResult = ({ result, focused }: SearchResultProps): JSX.Elemen )} >

{ diff --git a/frontend/src/lib/components/CommandBar/ActionResults.tsx b/frontend/src/lib/components/CommandBar/ActionResults.tsx index c104546e9210f..df7c8003b2281 100644 --- a/frontend/src/lib/components/CommandBar/ActionResults.tsx +++ b/frontend/src/lib/components/CommandBar/ActionResults.tsx @@ -14,7 +14,7 @@ type ResultsGroupProps = { const ResultsGroup = ({ scope, results, activeResultIndex }: ResultsGroupProps): JSX.Element => { return ( <> -
+
{getNameFromActionScope(scope)}
{results.map((result) => ( diff --git a/frontend/src/lib/components/CommandBar/SearchResult.tsx b/frontend/src/lib/components/CommandBar/SearchResult.tsx index 242dc374f65e2..354470759518e 100644 --- a/frontend/src/lib/components/CommandBar/SearchResult.tsx +++ b/frontend/src/lib/components/CommandBar/SearchResult.tsx @@ -42,7 +42,7 @@ export const SearchResult = ({ result, resultIndex, focused }: SearchResultProps return (
{ diff --git a/frontend/src/lib/components/CommandBar/index.scss b/frontend/src/lib/components/CommandBar/index.scss index 593086bb81634..02aa24cb7a11d 100644 --- a/frontend/src/lib/components/CommandBar/index.scss +++ b/frontend/src/lib/components/CommandBar/index.scss @@ -1,7 +1,7 @@ .LemonInput.CommandBar__input { - height: 2.75rem; - padding-right: 0.375rem; - padding-left: 0.75rem; + height: 3rem; + padding-right: 0.5rem; + padding-left: 1rem; border-color: transparent !important; border-radius: 0; } diff --git a/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddy.tsx b/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddy.tsx index ba614fd81ad7f..33c2f5b9c51b0 100644 --- a/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddy.tsx +++ b/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddy.tsx @@ -27,8 +27,8 @@ import { standardAnimations, } from './sprites/sprites' -const xFrames = SPRITE_SHEET_WIDTH / SPRITE_SIZE -const FPS = 24 +export const X_FRAMES = SPRITE_SHEET_WIDTH / SPRITE_SIZE +export const FPS = 24 const GRAVITY_PIXELS = 10 const MAX_JUMP_COUNT = 2 @@ -592,8 +592,8 @@ export class HedgehogActor { width: SPRITE_SIZE, height: SPRITE_SIZE, backgroundImage: `url(${baseSpritePath()}/${this.animation.img}.png)`, - backgroundPosition: `-${(this.animationFrame % xFrames) * SPRITE_SIZE}px -${ - Math.floor(this.animationFrame / xFrames) * SPRITE_SIZE + backgroundPosition: `-${(this.animationFrame % X_FRAMES) * SPRITE_SIZE}px -${ + Math.floor(this.animationFrame / X_FRAMES) * SPRITE_SIZE }px`, filter: imageFilter as any, }} diff --git a/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddyRender.tsx b/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddyRender.tsx index 7a24d4b69c194..337dc6744b1bf 100644 --- a/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddyRender.tsx +++ b/frontend/src/lib/components/HedgehogBuddy/HedgehogBuddyRender.tsx @@ -1,35 +1,77 @@ +import { useEffect, useRef, useState } from 'react' + import { HedgehogConfig } from '~/types' +import { FPS, X_FRAMES } from './HedgehogBuddy' import { COLOR_TO_FILTER_MAP } from './hedgehogBuddyLogic' -import { baseSpriteAccessoriesPath, baseSpritePath, standardAccessories } from './sprites/sprites' +import { + baseSpriteAccessoriesPath, + baseSpritePath, + SPRITE_SIZE, + standardAccessories, + standardAnimations, +} from './sprites/sprites' -export type HedgehogBuddyStaticProps = Partial & { size?: number | string } +export type HedgehogBuddyStaticProps = Partial & { size?: number | string; waveOnAppearance?: boolean } // Takes a range of options and renders a static hedgehog -export function HedgehogBuddyStatic({ accessories, color, size }: HedgehogBuddyStaticProps): JSX.Element { +export function HedgehogBuddyStatic({ + accessories, + color, + size, + waveOnAppearance, +}: HedgehogBuddyStaticProps): JSX.Element { const imgSize = size ?? 60 const accessoryInfos = accessories?.map((x) => standardAccessories[x]) const filter = color ? COLOR_TO_FILTER_MAP[color] : null + const [animationIteration, setAnimationIteration] = useState(waveOnAppearance ? 1 : 0) + const [_, setTimerLoop] = useState(0) + const animationFrameRef = useRef(0) + + useEffect(() => { + if (animationIteration) { + setTimerLoop(0) + let timer: any = null + const loop = (): void => { + if (animationFrameRef.current < standardAnimations.wave.frames) { + animationFrameRef.current++ + timer = setTimeout(loop, 1000 / FPS) + } else { + animationFrameRef.current = 0 + } + setTimerLoop((x) => x + 1) + } + loop() + return () => { + clearTimeout(timer) + } + } + }, [animationIteration]) + return (
setAnimationIteration((x) => x + 1) : undefined} > - @@ -37,7 +79,7 @@ export function HedgehogBuddyStatic({ accessories, color, size }: HedgehogBuddyS .LemonIcon { color: var(--primary-3000); diff --git a/frontend/src/lib/lemon-ui/LemonInput/LemonInput.tsx b/frontend/src/lib/lemon-ui/LemonInput/LemonInput.tsx index da51f8a6891c9..5f9117b9e41b3 100644 --- a/frontend/src/lib/lemon-ui/LemonInput/LemonInput.tsx +++ b/frontend/src/lib/lemon-ui/LemonInput/LemonInput.tsx @@ -44,7 +44,7 @@ interface LemonInputPropsBase /** Special case - show a transparent background rather than white */ transparentBackground?: boolean /** Size of the element. Default: `'medium'`. */ - size?: 'xsmall' | 'small' | 'medium' + size?: 'xsmall' | 'small' | 'medium' | 'large' onPressEnter?: (event: React.KeyboardEvent) => void 'data-attr'?: string 'aria-label'?: string diff --git a/frontend/src/lib/lemon-ui/icons/categories.ts b/frontend/src/lib/lemon-ui/icons/categories.ts index d7e29e9a5327b..c57ef8d09c6ef 100644 --- a/frontend/src/lib/lemon-ui/icons/categories.ts +++ b/frontend/src/lib/lemon-ui/icons/categories.ts @@ -51,6 +51,7 @@ export const OBJECTS = { 'IconGear', 'IconGearFilled', 'IconStack', + 'IconSparkles', ], People: ['IconPeople', 'IconPeopleFilled', 'IconPerson', 'IconProfile', 'IconUser', 'IconGroups'], 'Business & Finance': ['IconStore', 'IconCart', 'IconReceipt', 'IconPiggyBank', 'IconHandMoney'], diff --git a/frontend/src/queries/schema.json b/frontend/src/queries/schema.json index 10e539b1d61ac..09bcdf2f44af1 100644 --- a/frontend/src/queries/schema.json +++ b/frontend/src/queries/schema.json @@ -1,6 +1,134 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { + "AIActionsNode": { + "additionalProperties": false, + "properties": { + "custom_name": { + "type": "string" + }, + "event": { + "description": "The event or `null` for all events.", + "type": ["string", "null"] + }, + "fixedProperties": { + "items": { + "$ref": "#/definitions/AIPropertyFilter" + }, + "type": "array" + }, + "kind": { + "const": "EventsNode", + "type": "string" + }, + "math": { + "$ref": "#/definitions/MathType" + }, + "math_group_type_index": { + "enum": [0, 1, 2, 3, 4], + "type": "number" + }, + "math_property": { + "type": "string" + }, + "name": { + "type": "string" + }, + "orderBy": { + "description": "Columns to order by", + "items": { + "type": "string" + }, + "type": "array" + }, + "properties": { + "items": { + "$ref": "#/definitions/AIPropertyFilter" + }, + "type": "array" + }, + "response": { + "type": "object" + } + }, + "required": ["kind"], + "type": "object" + }, + "AIEventsNode": { + "additionalProperties": false, + "properties": { + "custom_name": { + "type": "string" + }, + "event": { + "description": "The event or `null` for all events.", + "type": ["string", "null"] + }, + "fixedProperties": { + "items": { + "$ref": "#/definitions/AIPropertyFilter" + }, + "type": "array" + }, + "kind": { + "const": "EventsNode", + "type": "string" + }, + "math": { + "$ref": "#/definitions/MathType" + }, + "math_group_type_index": { + "enum": [0, 1, 2, 3, 4], + "type": "number" + }, + "math_property": { + "type": "string" + }, + "name": { + "type": "string" + }, + "orderBy": { + "description": "Columns to order by", + "items": { + "type": "string" + }, + "type": "array" + }, + "properties": { + "items": { + "$ref": "#/definitions/AIPropertyFilter" + }, + "type": "array" + }, + "response": { + "type": "object" + } + }, + "required": ["kind"], + "type": "object" + }, + "AIPropertyFilter": { + "anyOf": [ + { + "$ref": "#/definitions/EventPropertyFilter" + }, + { + "$ref": "#/definitions/PersonPropertyFilter" + }, + { + "$ref": "#/definitions/SessionPropertyFilter" + }, + { + "$ref": "#/definitions/CohortPropertyFilter" + }, + { + "$ref": "#/definitions/GroupPropertyFilter" + }, + { + "$ref": "#/definitions/FeaturePropertyFilter" + } + ] + }, "ActionsNode": { "additionalProperties": false, "properties": { @@ -4181,6 +4309,92 @@ "required": ["columns", "hogql", "results", "types"], "type": "object" }, + "ExperimentalAITrendsQuery": { + "additionalProperties": false, + "properties": { + "aggregation_group_type_index": { + "description": "Groups aggregation", + "type": "integer" + }, + "breakdownFilter": { + "additionalProperties": false, + "description": "Breakdown of the events and actions", + "properties": { + "breakdown_hide_other_aggregation": { + "type": ["boolean", "null"] + }, + "breakdown_histogram_bin_count": { + "type": "integer" + }, + "breakdown_limit": { + "type": "integer" + }, + "breakdowns": { + "items": { + "$ref": "#/definitions/Breakdown" + }, + "maxLength": 3, + "type": "array" + } + }, + "type": "object" + }, + "compareFilter": { + "$ref": "#/definitions/CompareFilter", + "description": "Compare to date range" + }, + "dateRange": { + "$ref": "#/definitions/InsightDateRange", + "description": "Date range for the query" + }, + "filterTestAccounts": { + "default": false, + "description": "Exclude internal and test users by applying the respective filters", + "type": "boolean" + }, + "interval": { + "$ref": "#/definitions/IntervalType", + "default": "day", + "description": "Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" + }, + "kind": { + "const": "TrendsQuery", + "type": "string" + }, + "properties": { + "default": [], + "description": "Property filters for all series", + "items": { + "$ref": "#/definitions/AIPropertyFilter" + }, + "type": "array" + }, + "samplingFactor": { + "description": "Sampling rate", + "type": ["number", "null"] + }, + "series": { + "description": "Events and actions to include", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/AIEventsNode" + }, + { + "$ref": "#/definitions/AIActionsNode" + } + ] + }, + "type": "array" + }, + "trendsFilter": { + "$ref": "#/definitions/TrendsFilter", + "description": "Properties specific to the trends insight" + } + }, + "required": ["kind", "series"], + "type": "object" + }, "FeaturePropertyFilter": { "additionalProperties": false, "properties": { diff --git a/frontend/src/queries/schema.ts b/frontend/src/queries/schema.ts index 8ddd7d79fad6d..66439691f7a80 100644 --- a/frontend/src/queries/schema.ts +++ b/frontend/src/queries/schema.ts @@ -8,14 +8,17 @@ import { BreakdownType, ChartDisplayCategory, ChartDisplayType, + CohortPropertyFilter, CountPerActorMathType, DurationType, EventPropertyFilter, EventType, + FeaturePropertyFilter, FilterLogicalOperator, FilterType, FunnelsFilterType, GroupMathType, + GroupPropertyFilter, HogQLMathType, InsightShortId, InsightType, @@ -826,6 +829,79 @@ export interface TrendsQuery extends InsightsQueryBase { compareFilter?: CompareFilter } +export type AIPropertyFilter = + | EventPropertyFilter + | PersonPropertyFilter + // | ElementPropertyFilter + | SessionPropertyFilter + | CohortPropertyFilter + // | RecordingPropertyFilter + // | LogEntryPropertyFilter + // | HogQLPropertyFilter + // | EmptyPropertyFilter + // | DataWarehousePropertyFilter + // | DataWarehousePersonPropertyFilter + | GroupPropertyFilter + | FeaturePropertyFilter + +export interface AIEventsNode + extends Omit { + properties?: AIPropertyFilter[] + fixedProperties?: AIPropertyFilter[] +} + +export interface AIActionsNode + extends Omit { + properties?: AIPropertyFilter[] + fixedProperties?: AIPropertyFilter[] +} + +export interface ExperimentalAITrendsQuery { + kind: NodeKind.TrendsQuery + /** + * Granularity of the response. Can be one of `hour`, `day`, `week` or `month` + * + * @default day + */ + interval?: IntervalType + /** Events and actions to include */ + series: (AIEventsNode | AIActionsNode)[] + /** Properties specific to the trends insight */ + trendsFilter?: TrendsFilter + /** Breakdown of the events and actions */ + breakdownFilter?: Omit< + BreakdownFilter, + | 'breakdown' + | 'breakdown_type' + | 'breakdown_normalize_url' + | 'histogram_bin_count' + | 'breakdown_group_type_index' + > + /** Compare to date range */ + compareFilter?: CompareFilter + /** Date range for the query */ + dateRange?: InsightDateRange + /** + * Exclude internal and test users by applying the respective filters + * + * @default false + */ + filterTestAccounts?: boolean + /** + * Property filters for all series + * + * @default [] + */ + properties?: AIPropertyFilter[] + + /** + * Groups aggregation + */ + aggregation_group_type_index?: integer + /** Sampling rate */ + samplingFactor?: number | null +} + /** `FunnelsFilterType` minus everything inherited from `FilterType` and persons modal related params */ export type FunnelsFilterLegacy = Omit< FunnelsFilterType, diff --git a/frontend/src/scenes/appScenes.ts b/frontend/src/scenes/appScenes.ts index 23bc70635693a..0824fc5438068 100644 --- a/frontend/src/scenes/appScenes.ts +++ b/frontend/src/scenes/appScenes.ts @@ -45,6 +45,7 @@ export const appScenes: Record any> = { [Scene.OrganizationCreateFirst]: () => import('./organization/Create'), [Scene.OrganizationCreationConfirm]: () => import('./organization/ConfirmOrganization/ConfirmOrganization'), [Scene.ProjectHomepage]: () => import('./project-homepage/ProjectHomepage'), + [Scene.Max]: () => import('./max/Max'), [Scene.ProjectCreateFirst]: () => import('./project/Create'), [Scene.SystemStatus]: () => import('./instance/SystemStatus'), [Scene.ToolbarLaunch]: () => import('./toolbar-launch/ToolbarLaunch'), diff --git a/frontend/src/scenes/max/Max.scss b/frontend/src/scenes/max/Max.scss new file mode 100644 index 0000000000000..68671f6310558 --- /dev/null +++ b/frontend/src/scenes/max/Max.scss @@ -0,0 +1,3 @@ +.InsightVizDisplay { + flex: 1; +} diff --git a/frontend/src/scenes/max/Max.tsx b/frontend/src/scenes/max/Max.tsx new file mode 100644 index 0000000000000..594ca3344aed3 --- /dev/null +++ b/frontend/src/scenes/max/Max.tsx @@ -0,0 +1,157 @@ +import './Max.scss' + +import { LemonButton, LemonInput, Spinner } from '@posthog/lemon-ui' +import clsx from 'clsx' +import { useActions, useValues } from 'kea' +import { HedgehogBuddyStatic } from 'lib/components/HedgehogBuddy/HedgehogBuddyRender' +import { FEATURE_FLAGS } from 'lib/constants' +import { featureFlagLogic } from 'lib/logic/featureFlagLogic' +import { uuid } from 'lib/utils' +import React, { useState } from 'react' +import { SceneExport } from 'scenes/sceneTypes' +import { userLogic } from 'scenes/userLogic' + +import { queryNodeToFilter } from '~/queries/nodes/InsightQuery/utils/queryNodeToFilter' +import { Query } from '~/queries/Query/Query' +import { NodeKind } from '~/queries/schema' + +import { maxLogic } from './maxLogic' + +export const scene: SceneExport = { + component: Max, + logic: maxLogic, +} + +function Message({ + role, + children, + className, +}: React.PropsWithChildren<{ role: 'user' | 'assistant'; className?: string }>): JSX.Element { + return ( +
+ {children} +
+ ) +} + +export function Max(): JSX.Element | null { + const { user } = useValues(userLogic) + const { featureFlags } = useValues(featureFlagLogic) + + const logic = maxLogic({ + sessionId: uuid(), + }) + const { thread, threadLoading } = useValues(logic) + const { askMax } = useActions(logic) + + const [question, setQuestion] = useState('') + + if (!featureFlags[FEATURE_FLAGS.ARTIFICIAL_HOG]) { + return null + } + + return ( + <> +
+ {thread.map((message, index) => { + if (message.role === 'user' || typeof message.content === 'string') { + return ( + + {message.content || No text} + + ) + } + + const query = { + kind: NodeKind.InsightVizNode, + source: message.content?.answer, + } + + return ( + + {message.content?.reasoning_steps && ( + +
    + {message.content.reasoning_steps.map((step, index) => ( +
  • {step}
  • + ))} +
+
+ )} + {message.status === 'completed' && message.content?.answer && ( + +
+ +
+ + Edit Query + +
+ )} +
+ ) + })} + {threadLoading && ( + +
+ Let me think… + +
+
+ )} +
+
+
+ +
+ setQuestion(value)} + placeholder="Hey, I'm Max! What would you like to know about your product?" + fullWidth + size="large" + autoFocus + onPressEnter={() => { + askMax(question) + setQuestion('') + }} + disabled={threadLoading} + suffix={ + { + askMax(question) + setQuestion('') + }} + disabledReason={threadLoading ? 'Thinking…' : undefined} + > + Ask Max + + } + /> +
+ + ) +} diff --git a/frontend/src/scenes/max/maxLogic.ts b/frontend/src/scenes/max/maxLogic.ts new file mode 100644 index 0000000000000..a0a863e98e0eb --- /dev/null +++ b/frontend/src/scenes/max/maxLogic.ts @@ -0,0 +1,164 @@ +import { actions, kea, listeners, path, props, reducers } from 'kea' +import api from 'lib/api' + +import { ExperimentalAITrendsQuery } from '~/queries/schema' + +import type { maxLogicType } from './maxLogicType' + +export interface MaxLogicProps { + sessionId: string +} + +interface TrendGenerationResult { + reasoning_steps?: string[] + answer?: ExperimentalAITrendsQuery +} + +export interface ThreadMessage { + role: 'user' | 'assistant' + content?: string | TrendGenerationResult + status?: 'loading' | 'completed' | 'error' +} + +export const maxLogic = kea([ + path(['scenes', 'max', 'maxLogic']), + props({} as MaxLogicProps), + actions({ + askMax: (prompt: string) => ({ prompt }), + setThreadLoaded: true, + addMessage: (message: ThreadMessage) => ({ message }), + replaceMessage: (index: number, message: ThreadMessage) => ({ index, message }), + setMessageStatus: (index: number, status: ThreadMessage['status']) => ({ index, status }), + }), + reducers({ + thread: [ + [] as ThreadMessage[], + { + addMessage: (state, { message }) => [...state, message], + replaceMessage: (state, { message, index }) => [ + ...state.slice(0, index), + message, + ...state.slice(index + 1), + ], + setMessageStatus: (state, { index, status }) => [ + ...state.slice(0, index), + { + ...state[index], + status, + }, + ...state.slice(index + 1), + ], + }, + ], + threadLoading: [ + false, + { + askMax: () => true, + setThreadLoaded: () => false, + }, + ], + }), + listeners(({ actions, values, props }) => ({ + askMax: async ({ prompt }) => { + actions.addMessage({ role: 'user', content: prompt }) + const newIndex = values.thread.length + + try { + const response = await api.chat({ + session_id: props.sessionId, + messages: values.thread.map(({ role, content }) => ({ + role, + content: typeof content === 'string' ? content : JSON.stringify(content), + })), + }) + const reader = response.body?.getReader() + const decoder = new TextDecoder() + + if (reader) { + let firstChunk = true + + while (true) { + const { done, value } = await reader.read() + if (done) { + actions.setMessageStatus(newIndex, 'completed') + break + } + + const text = decoder.decode(value) + const parsedResponse = parseResponse(text) + + if (firstChunk) { + firstChunk = false + + if (parsedResponse) { + actions.addMessage({ role: 'assistant', content: parsedResponse, status: 'loading' }) + } + } else if (parsedResponse) { + actions.replaceMessage(newIndex, { + role: 'assistant', + content: parsedResponse, + status: 'loading', + }) + } + } + } + } catch { + actions.setMessageStatus(values.thread.length - 1 === newIndex ? newIndex : newIndex - 1, 'error') + } + + actions.setThreadLoaded() + }, + })), +]) + +/** + * Parses the generation result from the API. Some generation chunks might be sent in batches. + * @param response + */ +function parseResponse(response: string, recursive = true): TrendGenerationResult | null { + try { + const parsed = JSON.parse(response) + return parsed as TrendGenerationResult + } catch { + if (!recursive) { + return null + } + + const results: [number, number][] = [] + let pair: [number, number] = [0, 0] + let seq = 0 + + for (let i = 0; i < response.length; i++) { + const char = response[i] + + if (char === '{') { + if (seq === 0) { + pair[0] = i + } + + seq += 1 + } + + if (char === '}') { + seq -= 1 + if (seq === 0) { + pair[1] = i + } + } + + if (seq === 0) { + results.push(pair) + pair = [0, 0] + } + } + + const lastPair = results.pop() + + if (lastPair) { + const [left, right] = lastPair + return parseResponse(response.slice(left, right + 1), false) + } + + return null + } +} diff --git a/frontend/src/scenes/sceneTypes.ts b/frontend/src/scenes/sceneTypes.ts index 5f519137e32b0..adddb012a10b3 100644 --- a/frontend/src/scenes/sceneTypes.ts +++ b/frontend/src/scenes/sceneTypes.ts @@ -48,6 +48,7 @@ export enum Scene { DataWarehouseRedirect = 'DataWarehouseRedirect', OrganizationCreateFirst = 'OrganizationCreate', ProjectHomepage = 'ProjectHomepage', + Max = 'Max', ProjectCreateFirst = 'ProjectCreate', SystemStatus = 'SystemStatus', AsyncMigrations = 'AsyncMigrations', diff --git a/frontend/src/scenes/scenes.ts b/frontend/src/scenes/scenes.ts index 9b4019886e9b2..7581e424bd2fd 100644 --- a/frontend/src/scenes/scenes.ts +++ b/frontend/src/scenes/scenes.ts @@ -253,6 +253,12 @@ export const sceneConfigurations: Record = { projectBased: true, name: 'Homepage', }, + [Scene.Max]: { + projectBased: true, + name: 'Max', + layout: 'app-raw', + hideProjectNotice: true, // FIXME: Currently doesn't render well... + }, [Scene.IntegrationsRedirect]: { name: 'Integrations redirect', }, @@ -343,7 +349,7 @@ export const sceneConfigurations: Record = { }, [Scene.Notebook]: { projectBased: true, - hideProjectNotice: true, // Currently doesn't render well... + hideProjectNotice: true, // FIXME: Currently doesn't render well... name: 'Notebook', layout: 'app-raw', activityScope: ActivityScope.NOTEBOOK, @@ -517,6 +523,7 @@ export const routes: Record = { [urls.annotations()]: Scene.DataManagement, [urls.annotation(':id')]: Scene.DataManagement, [urls.projectHomepage()]: Scene.ProjectHomepage, + [urls.max()]: Scene.Max, [urls.projectCreateFirst()]: Scene.ProjectCreateFirst, [urls.organizationBilling()]: Scene.Billing, [urls.organizationCreateFirst()]: Scene.OrganizationCreateFirst, diff --git a/frontend/src/scenes/urls.ts b/frontend/src/scenes/urls.ts index ca6c98088952a..cc046586fc768 100644 --- a/frontend/src/scenes/urls.ts +++ b/frontend/src/scenes/urls.ts @@ -156,6 +156,7 @@ export const urls = { organizationCreateFirst: (): string => '/create-organization', projectCreateFirst: (): string => '/organization/create-project', projectHomepage: (): string => '/', + max: (): string => '/max', settings: (section: SettingSectionId | SettingLevelId = 'project', setting?: SettingId): string => combineUrl(`/settings/${section}`, undefined, setting).url, organizationCreationConfirm: (): string => '/organization/confirm-creation', diff --git a/package.json b/package.json index 8a67dc54ba8c3..44309818ccdb6 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@microlink/react-json-view": "^1.21.3", "@monaco-editor/react": "4.6.0", "@posthog/hogvm": "^1.0.44", - "@posthog/icons": "0.7.3", + "@posthog/icons": "0.8.1", "@posthog/plugin-scaffold": "^1.4.4", "@react-hook/size": "^2.1.2", "@rrweb/types": "2.0.0-alpha.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 833dec3dea675..813be57c694d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,8 +56,8 @@ dependencies: specifier: ^1.0.44 version: 1.0.44(luxon@3.5.0) '@posthog/icons': - specifier: 0.7.3 - version: 0.7.3(react-dom@18.2.0)(react@18.2.0) + specifier: 0.8.1 + version: 0.8.1(react-dom@18.2.0)(react@18.2.0) '@posthog/plugin-scaffold': specifier: ^1.4.4 version: 1.4.4 @@ -5422,8 +5422,8 @@ packages: luxon: 3.5.0 dev: false - /@posthog/icons@0.7.3(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-dw8qLS6aSBGGIjo/d24/yuLOgkFAov4C7yOhomMfhce/RwS+u96XXghVolioRHppnAn48pgGnBQIXEELGVEvPA==} + /@posthog/icons@0.8.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-/ryXgFnWGzHmwijHE/0gQcEyAD/WkKuwf3NCMG4ibmGMpEqm/d12/+Ccuf3Zj2VZuc+0atGCHkHOiSNJ8dw97A==} peerDependencies: react: '>=16.14.0' react-dom: '>=16.14.0' @@ -15427,7 +15427,7 @@ packages: image-size: 0.5.5 make-dir: 2.1.0 mime: 1.6.0 - native-request: 1.1.2 + native-request: 1.1.0 source-map: 0.6.1 dev: true @@ -16163,8 +16163,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /native-request@1.1.2: - resolution: {integrity: sha512-/etjwrK0J4Ebbcnt35VMWnfiUX/B04uwGJxyJInagxDqf2z5drSt/lsOvEMWGYunz1kaLZAFrV4NDAbOoDKvAQ==} + /native-request@1.1.0: + resolution: {integrity: sha512-uZ5rQaeRn15XmpgE0xoPL8YWqcX90VtCFglYwAgkvKM5e8fog+vePLAhHxuuv/gRkrQxIeh5U3q9sMNUrENqWw==} requiresBuild: true dev: true optional: true diff --git a/posthog/api/query.py b/posthog/api/query.py index 8c71b1465017a..7e6e145f8b5e3 100644 --- a/posthog/api/query.py +++ b/posthog/api/query.py @@ -1,34 +1,37 @@ +import json import re import uuid -from django.http import JsonResponse +from django.http import JsonResponse, StreamingHttpResponse from drf_spectacular.utils import OpenApiResponse from pydantic import BaseModel -from rest_framework import status -from rest_framework import viewsets -from posthog.api.utils import action -from rest_framework.exceptions import ValidationError, NotAuthenticated +from rest_framework import status, viewsets +from rest_framework.exceptions import NotAuthenticated, ValidationError +from rest_framework.renderers import BaseRenderer from rest_framework.request import Request from rest_framework.response import Response from sentry_sdk import capture_exception, set_tag +from ee.hogai.generate_trends_agent import Conversation, GenerateTrendsAgent from posthog.api.documentation import extend_schema from posthog.api.mixins import PydanticModelMixin +from posthog.api.monitoring import Feature, monitor from posthog.api.routing import TeamAndOrgViewSetMixin from posthog.api.services.query import process_query_model +from posthog.api.utils import action from posthog.clickhouse.client.execute_async import ( cancel_query, get_query_status, ) from posthog.clickhouse.query_tagging import tag_queries from posthog.errors import ExposedCHQueryError +from posthog.event_usage import report_user_action from posthog.hogql.ai import PromptUnclear, write_sql_from_prompt from posthog.hogql.errors import ExposedHogQLError from posthog.hogql_queries.query_runner import ExecutionMode, execution_mode_from_refresh from posthog.models.user import User from posthog.rate_limit import AIBurstRateThrottle, AISustainedRateThrottle, PersonalApiKeyRateThrottle from posthog.schema import QueryRequest, QueryResponseAlternative, QueryStatusResponse -from posthog.api.monitoring import monitor, Feature class QueryThrottle(PersonalApiKeyRateThrottle): @@ -36,6 +39,14 @@ class QueryThrottle(PersonalApiKeyRateThrottle): rate = "120/hour" +class ServerSentEventRenderer(BaseRenderer): + media_type = "text/event-stream" + format = "txt" + + def render(self, data, accepted_media_type=None, renderer_context=None): + return data + + class QueryViewSet(TeamAndOrgViewSetMixin, PydanticModelMixin, viewsets.ViewSet): # NOTE: Do we need to override the scopes for the "create" scope_object = "query" @@ -45,7 +56,7 @@ class QueryViewSet(TeamAndOrgViewSetMixin, PydanticModelMixin, viewsets.ViewSet) sharing_enabled_actions = ["retrieve"] def get_throttles(self): - if self.action == "draft_sql": + if self.action in ("draft_sql", "chat"): return [AIBurstRateThrottle(), AISustainedRateThrottle()] else: return [QueryThrottle()] @@ -144,6 +155,30 @@ def draft_sql(self, request: Request, *args, **kwargs) -> Response: raise ValidationError({"prompt": [str(e)]}, code="unclear") return Response({"sql": result}) + @action(detail=False, methods=["POST"], renderer_classes=[ServerSentEventRenderer]) + def chat(self, request: Request, *args, **kwargs): + assert request.user is not None + validated_body = Conversation.model_validate(request.data) + chain = GenerateTrendsAgent(self.team).bootstrap(validated_body.messages) + + def generate(): + last_message = None + for message in chain.stream({"question": validated_body.messages[0].content}): + if message: + last_message = message[0].model_dump_json() + yield last_message + + if not last_message: + yield json.dumps({"reasoning_steps": ["Schema validation failed"]}) + + report_user_action( + request.user, # type: ignore + "chat with ai", + {"prompt": validated_body.messages[-1].content, "response": last_message}, + ) + + return StreamingHttpResponse(generate(), content_type=ServerSentEventRenderer.media_type) + def handle_column_ch_error(self, error): if getattr(error, "message", None): match = re.search(r"There's no column.*in table", error.message) diff --git a/posthog/api/test/__snapshots__/test_api_docs.ambr b/posthog/api/test/__snapshots__/test_api_docs.ambr index 3703dc9ea6093..9b470bb936f43 100644 --- a/posthog/api/test/__snapshots__/test_api_docs.ambr +++ b/posthog/api/test/__snapshots__/test_api_docs.ambr @@ -80,6 +80,7 @@ '/home/runner/work/posthog/posthog/posthog/api/query.py: Warning [QueryViewSet]: could not derive type of path parameter "project_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', '/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py: Warning [QueryViewSet > ModelMetaclass]: Encountered 2 components with identical names "Person" and different classes and . This will very likely result in an incorrect schema. Try renaming one.', '/home/runner/work/posthog/posthog/posthog/api/query.py: Warning [QueryViewSet]: could not derive type of path parameter "id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/query.py: Error [QueryViewSet]: unable to guess serializer. This is graceful fallback handling for APIViews. Consider using GenericAPIView as view base class, if view is under your control. Either way you may want to add a serializer_class (or method). Ignoring view for now.', '/home/runner/work/posthog/posthog/ee/session_recordings/session_recording_playlist.py: Warning [SessionRecordingPlaylistViewSet]: could not derive type of path parameter "project_id" because model "posthog.session_recordings.models.session_recording_playlist.SessionRecordingPlaylist" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/ee/session_recordings/session_recording_playlist.py: Warning [SessionRecordingPlaylistViewSet]: could not derive type of path parameter "session_recording_id" because model "posthog.session_recordings.models.session_recording_playlist.SessionRecordingPlaylist" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/session_recordings/session_recording_api.py: Warning [SessionRecordingViewSet]: could not derive type of path parameter "project_id" because model "posthog.session_recordings.models.session_recording.SessionRecording" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', diff --git a/posthog/schema.py b/posthog/schema.py index f99badf4c1c84..bf7662b7a9e5b 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -2474,6 +2474,16 @@ class EventsQueryResponse(BaseModel): types: list[str] +class BreakdownFilter1(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + breakdown_hide_other_aggregation: Optional[bool] = None + breakdown_histogram_bin_count: Optional[int] = None + breakdown_limit: Optional[int] = None + breakdowns: Optional[list[Breakdown]] = Field(default=None, max_length=3) + + class FeaturePropertyFilter(BaseModel): model_config = ConfigDict( extra="forbid", @@ -4419,6 +4429,88 @@ class SessionsTimelineQuery(BaseModel): response: Optional[SessionsTimelineQueryResponse] = None +class AIActionsNode(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + custom_name: Optional[str] = None + event: Optional[str] = Field(default=None, description="The event or `null` for all events.") + fixedProperties: Optional[ + list[ + Union[ + EventPropertyFilter, + PersonPropertyFilter, + SessionPropertyFilter, + CohortPropertyFilter, + GroupPropertyFilter, + FeaturePropertyFilter, + ] + ] + ] = None + kind: Literal["EventsNode"] = "EventsNode" + math: Optional[ + Union[BaseMathType, PropertyMathType, CountPerActorMathType, Literal["unique_group"], Literal["hogql"]] + ] = None + math_group_type_index: Optional[MathGroupTypeIndex] = None + math_property: Optional[str] = None + name: Optional[str] = None + orderBy: Optional[list[str]] = Field(default=None, description="Columns to order by") + properties: Optional[ + list[ + Union[ + EventPropertyFilter, + PersonPropertyFilter, + SessionPropertyFilter, + CohortPropertyFilter, + GroupPropertyFilter, + FeaturePropertyFilter, + ] + ] + ] = None + response: Optional[dict[str, Any]] = None + + +class AIEventsNode(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + custom_name: Optional[str] = None + event: Optional[str] = Field(default=None, description="The event or `null` for all events.") + fixedProperties: Optional[ + list[ + Union[ + EventPropertyFilter, + PersonPropertyFilter, + SessionPropertyFilter, + CohortPropertyFilter, + GroupPropertyFilter, + FeaturePropertyFilter, + ] + ] + ] = None + kind: Literal["EventsNode"] = "EventsNode" + math: Optional[ + Union[BaseMathType, PropertyMathType, CountPerActorMathType, Literal["unique_group"], Literal["hogql"]] + ] = None + math_group_type_index: Optional[MathGroupTypeIndex] = None + math_property: Optional[str] = None + name: Optional[str] = None + orderBy: Optional[list[str]] = Field(default=None, description="Columns to order by") + properties: Optional[ + list[ + Union[ + EventPropertyFilter, + PersonPropertyFilter, + SessionPropertyFilter, + CohortPropertyFilter, + GroupPropertyFilter, + FeaturePropertyFilter, + ] + ] + ] = None + response: Optional[dict[str, Any]] = None + + class ActionsNode(BaseModel): model_config = ConfigDict( extra="forbid", @@ -4499,6 +4591,39 @@ class DatabaseSchemaViewTable(BaseModel): type: Literal["view"] = "view" +class ExperimentalAITrendsQuery(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + aggregation_group_type_index: Optional[int] = Field(default=None, description="Groups aggregation") + breakdownFilter: Optional[BreakdownFilter1] = Field(default=None, description="Breakdown of the events and actions") + compareFilter: Optional[CompareFilter] = Field(default=None, description="Compare to date range") + dateRange: Optional[InsightDateRange] = Field(default=None, description="Date range for the query") + filterTestAccounts: Optional[bool] = Field( + default=False, description="Exclude internal and test users by applying the respective filters" + ) + interval: Optional[IntervalType] = Field( + default=IntervalType.DAY, + description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`", + ) + kind: Literal["TrendsQuery"] = "TrendsQuery" + properties: Optional[ + list[ + Union[ + EventPropertyFilter, + PersonPropertyFilter, + SessionPropertyFilter, + CohortPropertyFilter, + GroupPropertyFilter, + FeaturePropertyFilter, + ] + ] + ] = Field(default=[], description="Property filters for all series") + samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") + series: list[Union[AIEventsNode, AIActionsNode]] = Field(..., description="Events and actions to include") + trendsFilter: Optional[TrendsFilter] = Field(default=None, description="Properties specific to the trends insight") + + class FunnelsFilter(BaseModel): model_config = ConfigDict( extra="forbid", diff --git a/requirements-dev.in b/requirements-dev.in index 8ab3ba93b3a2d..b125a97db3286 100644 --- a/requirements-dev.in +++ b/requirements-dev.in @@ -22,7 +22,7 @@ Faker==17.5.0 fakeredis[lua]==2.23.3 freezegun==1.2.2 inline-snapshot==0.10.2 -packaging==23.1 +packaging==24.1 black~=23.9.1 boto3-stubs[s3] types-markdown==3.3.9 diff --git a/requirements-dev.txt b/requirements-dev.txt index b12079e28c40f..0c4cf8b0d77f7 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -20,6 +20,7 @@ asgiref==3.7.2 # via # -c requirements.txt # django + # django-stubs asttokens==2.4.1 # via inline-snapshot async-timeout==4.0.2 @@ -37,7 +38,7 @@ black==23.9.1 # -r requirements-dev.in # datamodel-code-generator # inline-snapshot -boto3-stubs[s3]==1.34.84 +boto3-stubs==1.34.84 # via -r requirements-dev.in botocore-stubs==1.34.84 # via boto3-stubs @@ -62,7 +63,7 @@ click==8.1.7 # inline-snapshot colorama==0.4.4 # via pytest-watch -coverage[toml]==5.5 +coverage==5.5 # via pytest-cov cryptography==39.0.2 # via @@ -76,7 +77,9 @@ django==4.2.15 # django-stubs # django-stubs-ext django-stubs==5.0.4 - # via djangorestframework-stubs + # via + # -r requirements-dev.in + # djangorestframework-stubs django-stubs-ext==5.0.4 # via django-stubs djangorestframework-stubs==3.14.5 @@ -95,7 +98,7 @@ executing==2.0.1 # via inline-snapshot faker==17.5.0 # via -r requirements-dev.in -fakeredis[lua]==2.23.3 +fakeredis==2.23.3 # via -r requirements-dev.in flaky==3.7.0 # via -r requirements-dev.in @@ -154,6 +157,7 @@ multidict==6.0.2 # aiohttp # yarl mypy==1.11.1 + # via -r requirements-dev.in mypy-baseline==0.7.0 # via -r requirements-dev.in mypy-boto3-s3==1.34.65 @@ -167,7 +171,7 @@ openapi-schema-validator==0.6.2 # via openapi-spec-validator openapi-spec-validator==0.7.1 # via -r requirements-dev.in -packaging==23.1 +packaging==24.1 # via # -c requirements.txt # -r requirements-dev.in @@ -195,7 +199,7 @@ pycparser==2.20 # via # -c requirements.txt # cffi -pydantic[email]==2.5.3 +pydantic==2.5.3 # via # -c requirements.txt # datamodel-code-generator @@ -281,6 +285,7 @@ ruamel-yaml==0.18.6 ruamel-yaml-clib==0.2.8 # via ruamel-yaml ruff==0.6.1 + # via -r requirements-dev.in six==1.16.0 # via # -c requirements.txt @@ -317,7 +322,6 @@ types-python-dateutil==2.8.3 types-pytz==2023.3.0.0 # via # -r requirements-dev.in - # django-stubs # types-tzlocal types-pyyaml==6.0.1 # via diff --git a/requirements.in b/requirements.in index 2e0332d76ec58..17c4feb2f808d 100644 --- a/requirements.in +++ b/requirements.in @@ -45,12 +45,15 @@ gunicorn==20.1.0 infi-clickhouse-orm@ git+https://github.com/PostHog/infi.clickhouse_orm@9578c79f29635ee2c1d01b7979e89adab8383de2 kafka-python==2.0.2 kombu==5.3.2 +langchain==0.2.15 +langchain-openai==0.1.23 +langsmith==0.1.106 lzstring==1.0.4 natsort==8.4.0 nanoid==2.0.0 numpy==1.23.3 openpyxl==3.1.2 -orjson==3.9.10 +orjson==3.10.7 pandas==2.2.0 paramiko==3.4.0 Pillow==10.2.0 @@ -96,8 +99,8 @@ mimesis==5.2.1 more-itertools==9.0.0 django-two-factor-auth==1.14.0 phonenumberslite==8.13.6 -openai==1.10.0 -tiktoken==0.6.0 +openai==1.43.0 +tiktoken==0.7.0 nh3==0.2.14 hogql-parser==1.0.40 zxcvbn==4.4.28 diff --git a/requirements.txt b/requirements.txt index 484a579627303..c8d3e50b4256c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,6 +11,7 @@ aiohttp==3.9.3 # -r requirements.in # aiobotocore # geoip2 + # langchain # s3fs aioitertools==0.11.0 # via aiobotocore @@ -278,7 +279,9 @@ hogql-parser==1.0.40 httpcore==1.0.2 # via httpx httpx==0.26.0 - # via openai + # via + # langsmith + # openai humanize==4.9.0 # via dlt idna==2.8 @@ -300,14 +303,20 @@ isodate==0.6.1 # via # python3-saml # zeep +jiter==0.5.0 + # via openai jmespath==1.0.0 # via # boto3 # botocore joblib==1.3.2 # via scikit-learn +jsonpatch==1.33 + # via langchain-core jsonpath-ng==1.6.0 # via dlt +jsonpointer==3.0.0 + # via jsonpatch jsonschema==4.20.0 # via drf-spectacular jsonschema-specifications==2023.12.1 @@ -320,6 +329,22 @@ kombu==5.3.2 # via # -r requirements.in # celery +langchain==0.2.15 + # via -r requirements.in +langchain-core==0.2.36 + # via + # langchain + # langchain-openai + # langchain-text-splitters +langchain-openai==0.1.23 + # via -r requirements.in +langchain-text-splitters==0.2.2 + # via langchain +langsmith==0.1.106 + # via + # -r requirements.in + # langchain + # langchain-core lxml==4.9.4 # via # -r requirements.in @@ -354,6 +379,7 @@ nh3==0.2.14 numpy==1.23.3 # via # -r requirements.in + # langchain # pandas # pyarrow # scikit-learn @@ -362,23 +388,26 @@ oauthlib==3.1.0 # via # requests-oauthlib # social-auth-core -openai==1.10.0 +openai==1.43.0 # via # -r requirements.in + # langchain-openai # sentry-sdk openpyxl==3.1.2 # via -r requirements.in -orjson==3.9.10 +orjson==3.10.7 # via # -r requirements.in # dlt + # langsmith outcome==1.3.0.post0 # via trio -packaging==23.1 +packaging==24.1 # via # aiokafka # dlt # google-cloud-bigquery + # langchain-core # snowflake-connector-python # webdriver-manager pandas==2.2.0 @@ -443,6 +472,9 @@ pycparser==2.20 pydantic==2.5.3 # via # -r requirements.in + # langchain + # langchain-core + # langsmith # openai pydantic-core==2.14.6 # via pydantic @@ -502,6 +534,8 @@ pyyaml==6.0.1 # via # dlt # drf-spectacular + # langchain + # langchain-core qrcode==7.4.2 # via django-two-factor-auth redis==4.5.4 @@ -523,6 +557,8 @@ requests==2.32.0 # google-api-core # google-cloud-bigquery # infi-clickhouse-orm + # langchain + # langsmith # pdpyras # posthoganalytics # requests-file @@ -613,6 +649,7 @@ sortedcontainers==2.4.0 sqlalchemy==2.0.31 # via # -r requirements.in + # langchain # snowflake-sqlalchemy sqlparse==0.4.4 # via @@ -634,11 +671,14 @@ tenacity==8.2.3 # via # celery-redbeat # dlt + # langchain + # langchain-core threadpoolctl==3.3.0 # via scikit-learn -tiktoken==0.6.0 +tiktoken==0.7.0 # via # -r requirements.in + # langchain-openai # sentry-sdk token-bucket==0.3.0 # via -r requirements.in @@ -663,6 +703,7 @@ types-setuptools==69.0.0.0 typing-extensions==4.12.2 # via # dlt + # langchain-core # openai # psycopg # pydantic From 73fce744878d8ec0725fa4a0a7f842eb6d7c6a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Far=C3=ADas=20Santana?= Date: Wed, 4 Sep 2024 19:17:57 +0200 Subject: [PATCH 13/32] feat(batch-exports): Send file write to thread (#24792) --- posthog/temporal/batch_exports/temporary_file.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/posthog/temporal/batch_exports/temporary_file.py b/posthog/temporal/batch_exports/temporary_file.py index 75cde8a9b651b..079cce001d235 100644 --- a/posthog/temporal/batch_exports/temporary_file.py +++ b/posthog/temporal/batch_exports/temporary_file.py @@ -1,6 +1,7 @@ """This module contains a temporary file to stage data in batch exports.""" import abc +import asyncio import collections.abc import contextlib import csv @@ -390,7 +391,7 @@ async def write_record_batch(self, record_batch: pa.RecordBatch) -> None: column_names = record_batch.column_names column_names.pop(column_names.index("_inserted_at")) - self._write_record_batch(record_batch.select(column_names)) + await asyncio.to_thread(self._write_record_batch, record_batch.select(column_names)) self.last_inserted_at = last_inserted_at self.track_records_written(record_batch) From 989dbd9bd5c5c8f0a2c8b2af22134b4fe7fb117b Mon Sep 17 00:00:00 2001 From: Eric Duong Date: Wed, 4 Sep 2024 15:59:47 -0400 Subject: [PATCH 14/32] fix(data-warehouse): include views props in insights (#24795) --- .../scenes/data-management/database/databaseTableListLogic.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/scenes/data-management/database/databaseTableListLogic.ts b/frontend/src/scenes/data-management/database/databaseTableListLogic.ts index 409d9a2c03983..9718eb83c76b9 100644 --- a/frontend/src/scenes/data-management/database/databaseTableListLogic.ts +++ b/frontend/src/scenes/data-management/database/databaseTableListLogic.ts @@ -109,7 +109,9 @@ export const databaseTableListLogic = kea([ } return Object.values(database.tables) - .filter((n): n is DatabaseSchemaDataWarehouseTable => n.type === 'data_warehouse') + .filter( + (n): n is DatabaseSchemaDataWarehouseTable => n.type === 'data_warehouse' || n.type == 'view' + ) .reduce((acc, cur) => { acc[cur.name] = database.tables[cur.name] as DatabaseSchemaDataWarehouseTable return acc From 277fb2e3c2a556863f6429333b8014c9a6cd341c Mon Sep 17 00:00:00 2001 From: Oliver Browne Date: Thu, 5 Sep 2024 09:19:25 +0300 Subject: [PATCH 15/32] fix: use jemalloc everywhere we're rusty (#24796) --- rust/Cargo.lock | 16 +++++++++++++++- rust/Cargo.toml | 1 + rust/capture/Cargo.toml | 5 +---- rust/capture/src/main.rs | 7 +------ rust/common/alloc/Cargo.toml | 11 +++++++++++ rust/common/alloc/README.md | 12 ++++++++++++ rust/common/alloc/src/lib.rs | 12 ++++++++++++ rust/cyclotron-fetch/Cargo.toml | 1 + rust/cyclotron-fetch/src/main.rs | 2 ++ rust/cyclotron-janitor/Cargo.toml | 1 + rust/cyclotron-janitor/src/main.rs | 3 +-- rust/cyclotron-janitor/tests/janitor.rs | 6 ++---- rust/feature-flags/Cargo.toml | 1 + rust/feature-flags/src/main.rs | 2 ++ rust/hook-api/Cargo.toml | 1 + rust/hook-api/src/main.rs | 2 ++ rust/hook-janitor/Cargo.toml | 1 + rust/hook-janitor/src/main.rs | 2 ++ rust/hook-worker/Cargo.toml | 1 + rust/hook-worker/src/main.rs | 2 ++ rust/property-defs-rs/Cargo.toml | 1 + rust/property-defs-rs/src/main.rs | 2 ++ 22 files changed, 75 insertions(+), 17 deletions(-) create mode 100644 rust/common/alloc/Cargo.toml create mode 100644 rust/common/alloc/README.md create mode 100644 rust/common/alloc/src/lib.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 8b577220c3ae0..117d4bae8a717 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -620,6 +620,7 @@ dependencies = [ "axum-test-helper", "base64 0.22.0", "bytes", + "common-alloc", "envconfig", "flate2", "futures", @@ -639,7 +640,6 @@ dependencies = [ "serde_json", "serde_urlencoded", "thiserror", - "tikv-jemallocator", "time", "tokio", "tower", @@ -703,6 +703,13 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "common-alloc" +version = "0.1.0" +dependencies = [ + "tikv-jemallocator", +] + [[package]] name = "common-dns" version = "0.1.0" @@ -878,6 +885,7 @@ version = "0.1.0" dependencies = [ "axum 0.7.5", "chrono", + "common-alloc", "common-dns", "common-kafka", "common-metrics", @@ -907,6 +915,7 @@ version = "0.1.0" dependencies = [ "axum 0.7.5", "chrono", + "common-alloc", "common-kafka", "common-metrics", "cyclotron-core", @@ -1157,6 +1166,7 @@ dependencies = [ "axum 0.7.5", "axum-client-ip", "bytes", + "common-alloc", "envconfig", "maxminddb", "once_cell", @@ -1587,6 +1597,7 @@ name = "hook-api" version = "0.1.0" dependencies = [ "axum 0.7.5", + "common-alloc", "common-metrics", "envconfig", "eyre", @@ -1628,6 +1639,7 @@ version = "0.1.0" dependencies = [ "async-trait", "axum 0.7.5", + "common-alloc", "common-kafka", "common-metrics", "envconfig", @@ -1653,6 +1665,7 @@ version = "0.1.0" dependencies = [ "axum 0.7.5", "chrono", + "common-alloc", "common-dns", "common-kafka", "common-metrics", @@ -2848,6 +2861,7 @@ dependencies = [ "ahash", "axum 0.7.5", "chrono", + "common-alloc", "common-metrics", "envconfig", "futures", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 39fbcb8c48449..5c30dd1a8cf46 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -7,6 +7,7 @@ members = [ "common/health", "common/metrics", "common/dns", + "common/alloc", "feature-flags", "hook-api", "hook-common", diff --git a/rust/capture/Cargo.toml b/rust/capture/Cargo.toml index cc551cdac99a1..7b50fe760b742 100644 --- a/rust/capture/Cargo.toml +++ b/rust/capture/Cargo.toml @@ -7,10 +7,6 @@ edition = "2021" workspace = true [dependencies] - -[target.'cfg(not(target_env = "msvc"))'.dependencies] -tikv-jemallocator = "0.6" - anyhow = { workspace = true } async-trait = { workspace = true } axum = { workspace = true } @@ -21,6 +17,7 @@ envconfig = { workspace = true } flate2 = { workspace = true } governor = { workspace = true } health = { path = "../common/health" } +common-alloc = { path = "../common/alloc" } metrics = { workspace = true } metrics-exporter-prometheus = { workspace = true } opentelemetry = { workspace = true } diff --git a/rust/capture/src/main.rs b/rust/capture/src/main.rs index 14868f059f02b..150cf29835291 100644 --- a/rust/capture/src/main.rs +++ b/rust/capture/src/main.rs @@ -16,12 +16,7 @@ use tracing_subscriber::{EnvFilter, Layer}; use capture::config::Config; use capture::server::serve; -#[cfg(not(target_env = "msvc"))] -use tikv_jemallocator::Jemalloc; - -#[cfg(not(target_env = "msvc"))] -#[global_allocator] -static GLOBAL: Jemalloc = Jemalloc; +common_alloc::used!(); async fn shutdown() { let mut term = signal::unix::signal(signal::unix::SignalKind::terminate()) diff --git a/rust/common/alloc/Cargo.toml b/rust/common/alloc/Cargo.toml new file mode 100644 index 0000000000000..c000c381d3c1d --- /dev/null +++ b/rust/common/alloc/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "common-alloc" +version = "0.1.0" +edition = "2021" + +[lints] +workspace = true + +[dependencies] +[target.'cfg(not(target_env = "msvc"))'.dependencies] +tikv-jemallocator = "0.6" diff --git a/rust/common/alloc/README.md b/rust/common/alloc/README.md new file mode 100644 index 0000000000000..f35e8a6437ba7 --- /dev/null +++ b/rust/common/alloc/README.md @@ -0,0 +1,12 @@ +# What is this? + +We use jemalloc everywhere we can, for any binary that we expect to run in a long-lived process. The reason for this is that our workloads are: +- multi-threaded +- extremely prone to memory fragmentation (due to our heavy use of `serde_json`, or json generally) + +jemalloc helps reduce memory fragmentation hugely, to the point of solving production OOMs that would have made use of capture-rs for replay a non-starter with the default system allocator. + +At time of writing (2024-09-04), rust workspaces don't have good support for specifying dependencies on a per-target basis, so this crate does the work of pulling in jemalloc only when compiling for supported targets, and then exposes a simple macro to use jemalloc as the global allocator. Anyone writing a binary crate should put this macro at the top of their `main.rs`. Libraries should not make use of this crate. + +## Future work +Functions could be added to this crate to, in situations where jemalloc is in use, report a set of metrics about the allocator, as well as other functionality (health/liveness, a way to specify hooks to execute when memory usage exceeds a certain threshold, etc). Right now, it's prety barebones. \ No newline at end of file diff --git a/rust/common/alloc/src/lib.rs b/rust/common/alloc/src/lib.rs new file mode 100644 index 0000000000000..af560a96b3dc0 --- /dev/null +++ b/rust/common/alloc/src/lib.rs @@ -0,0 +1,12 @@ +#[cfg(target_env = "msvc")] +pub use std::alloc::System as DefaultAllocator; +#[cfg(not(target_env = "msvc"))] +pub use tikv_jemallocator::Jemalloc as DefaultAllocator; + +#[macro_export] +macro_rules! used { + () => { + #[global_allocator] + static GLOBAL: $crate::DefaultAllocator = $crate::DefaultAllocator; + }; +} diff --git a/rust/cyclotron-fetch/Cargo.toml b/rust/cyclotron-fetch/Cargo.toml index 69f6f4ac2adf1..8de85020ea106 100644 --- a/rust/cyclotron-fetch/Cargo.toml +++ b/rust/cyclotron-fetch/Cargo.toml @@ -19,6 +19,7 @@ cyclotron-core = { path = "../cyclotron-core" } common-metrics = { path = "../common/metrics" } common-dns = { path = "../common/dns" } common-kafka = { path = "../common/kafka" } +common-alloc = { path = "../common/alloc" } health = { path = "../common/health" } reqwest = { workspace = true } serde = { workspace = true } diff --git a/rust/cyclotron-fetch/src/main.rs b/rust/cyclotron-fetch/src/main.rs index 2013f1b6c7218..ebefa9f01d787 100644 --- a/rust/cyclotron-fetch/src/main.rs +++ b/rust/cyclotron-fetch/src/main.rs @@ -10,6 +10,8 @@ use health::HealthRegistry; use std::{future::ready, sync::Arc}; use tracing::{error, info}; +common_alloc::used!(); + async fn listen(app: Router, bind: String) -> Result<(), std::io::Error> { let listener = tokio::net::TcpListener::bind(bind).await?; diff --git a/rust/cyclotron-janitor/Cargo.toml b/rust/cyclotron-janitor/Cargo.toml index d6eb553d3e72f..15a0ae4e412f1 100644 --- a/rust/cyclotron-janitor/Cargo.toml +++ b/rust/cyclotron-janitor/Cargo.toml @@ -19,6 +19,7 @@ cyclotron-core = { path = "../cyclotron-core" } common-metrics = { path = "../common/metrics" } common-kafka = { path = "../common/kafka" } health = { path = "../common/health" } +common-alloc = { path = "../common/alloc" } time = { workspace = true } rdkafka = { workspace = true } diff --git a/rust/cyclotron-janitor/src/main.rs b/rust/cyclotron-janitor/src/main.rs index fa0f682601e61..a4a9274e08f3c 100644 --- a/rust/cyclotron-janitor/src/main.rs +++ b/rust/cyclotron-janitor/src/main.rs @@ -7,8 +7,7 @@ use health::{HealthHandle, HealthRegistry}; use std::{future::ready, time::Duration}; use tracing::{error, info}; -/// Most of this stuff is stolen pretty shamelessly from the rustyhook janitor. It'll diverge more -/// once we introduce the management command stuff, but for now it's a good starting point. +common_alloc::used!(); async fn cleanup_loop(janitor: Janitor, livenes: HealthHandle, interval_secs: u64) -> Result<()> { let mut interval = tokio::time::interval(Duration::from_secs(interval_secs)); diff --git a/rust/cyclotron-janitor/tests/janitor.rs b/rust/cyclotron-janitor/tests/janitor.rs index 7dceae4969c19..90afcfbdec45e 100644 --- a/rust/cyclotron-janitor/tests/janitor.rs +++ b/rust/cyclotron-janitor/tests/janitor.rs @@ -1,14 +1,12 @@ -use chrono::{DateTime, Duration, Timelike, Utc}; +use chrono::{Duration, Timelike, Utc}; use common_kafka::kafka_messages::app_metrics2::{ AppMetric2, Kind as AppMetric2Kind, Source as AppMetric2Source, }; use cyclotron_core::{JobInit, JobState, QueueManager, Worker}; use cyclotron_janitor::{config::JanitorSettings, janitor::Janitor}; use rdkafka::consumer::{Consumer, StreamConsumer}; -use rdkafka::types::{RDKafkaApiKey, RDKafkaRespErr}; use rdkafka::{ClientConfig, Message}; use sqlx::PgPool; -use std::str::FromStr; use uuid::Uuid; use common_kafka::{test::create_mock_kafka, APP_METRICS2_TOPIC}; @@ -58,7 +56,7 @@ async fn janitor_test(db: PgPool) { queue_name: queue_name.clone(), priority: 0, scheduled: now, - function_id: Some(uuid.clone()), + function_id: Some(uuid), vm_state: None, parameters: None, blob: None, diff --git a/rust/feature-flags/Cargo.toml b/rust/feature-flags/Cargo.toml index b43d09cc93d2f..3d898dfdbfa72 100644 --- a/rust/feature-flags/Cargo.toml +++ b/rust/feature-flags/Cargo.toml @@ -31,6 +31,7 @@ regex = "1.10.4" maxminddb = "0.17" sqlx = { workspace = true } uuid = { workspace = true } +common-alloc = { path = "../common/alloc" } [lints] workspace = true diff --git a/rust/feature-flags/src/main.rs b/rust/feature-flags/src/main.rs index 980db6973893f..46cc1be270b27 100644 --- a/rust/feature-flags/src/main.rs +++ b/rust/feature-flags/src/main.rs @@ -7,6 +7,8 @@ use tracing_subscriber::{EnvFilter, Layer}; use feature_flags::config::Config; use feature_flags::server::serve; +common_alloc::used!(); + async fn shutdown() { let mut term = signal::unix::signal(signal::unix::SignalKind::terminate()) .expect("failed to register SIGTERM handler"); diff --git a/rust/hook-api/Cargo.toml b/rust/hook-api/Cargo.toml index 7887e8e49a8e2..87057fa8c74fd 100644 --- a/rust/hook-api/Cargo.toml +++ b/rust/hook-api/Cargo.toml @@ -23,3 +23,4 @@ tracing = { workspace = true } tracing-subscriber = { workspace = true } url = { workspace = true } common-metrics = { path = "../common/metrics" } +common-alloc = { path = "../common/alloc" } diff --git a/rust/hook-api/src/main.rs b/rust/hook-api/src/main.rs index 1f84abb4e4665..0491d49eea3be 100644 --- a/rust/hook-api/src/main.rs +++ b/rust/hook-api/src/main.rs @@ -9,6 +9,8 @@ use hook_common::pgqueue::PgQueue; mod config; mod handlers; +common_alloc::used!(); + async fn listen(app: Router, bind: String) -> Result<()> { let listener = tokio::net::TcpListener::bind(bind).await?; diff --git a/rust/hook-janitor/Cargo.toml b/rust/hook-janitor/Cargo.toml index dba9bef7e7046..70d6e263296e6 100644 --- a/rust/hook-janitor/Cargo.toml +++ b/rust/hook-janitor/Cargo.toml @@ -26,3 +26,4 @@ tracing = { workspace = true } tracing-subscriber = { workspace = true } common-metrics = { path = "../common/metrics" } common-kafka = { path = "../common/kafka" } +common-alloc = { path = "../common/alloc" } diff --git a/rust/hook-janitor/src/main.rs b/rust/hook-janitor/src/main.rs index 6ca27fa6e6d6f..de8910bcff97b 100644 --- a/rust/hook-janitor/src/main.rs +++ b/rust/hook-janitor/src/main.rs @@ -17,6 +17,8 @@ mod config; mod handlers; mod webhooks; +common_alloc::used!(); + async fn listen(app: Router, bind: String) -> Result<()> { let listener = tokio::net::TcpListener::bind(bind).await?; diff --git a/rust/hook-worker/Cargo.toml b/rust/hook-worker/Cargo.toml index fdc6f150dfec9..4670116572a04 100644 --- a/rust/hook-worker/Cargo.toml +++ b/rust/hook-worker/Cargo.toml @@ -28,6 +28,7 @@ url = { version = "2.2" } common-metrics = { path = "../common/metrics" } common-dns = { path = "../common/dns" } common-kafka = { path = "../common/kafka" } +common-alloc = { path = "../common/alloc" } [dev-dependencies] httpmock = { workspace = true } diff --git a/rust/hook-worker/src/main.rs b/rust/hook-worker/src/main.rs index 0aeae27e0a3a0..7aa0845247a92 100644 --- a/rust/hook-worker/src/main.rs +++ b/rust/hook-worker/src/main.rs @@ -13,6 +13,8 @@ use hook_worker::config::Config; use hook_worker::error::WorkerError; use hook_worker::worker::WebhookWorker; +common_alloc::used!(); + #[tokio::main] async fn main() -> Result<(), WorkerError> { tracing_subscriber::fmt::init(); diff --git a/rust/property-defs-rs/Cargo.toml b/rust/property-defs-rs/Cargo.toml index 6deb3bc0c22f7..f0ec58d5a6fac 100644 --- a/rust/property-defs-rs/Cargo.toml +++ b/rust/property-defs-rs/Cargo.toml @@ -21,6 +21,7 @@ metrics = { workspace = true } chrono = { workspace = true } quick_cache = { workspace = true } common-metrics = { path = "../common/metrics" } +common-alloc = { path = "../common/alloc" } ahash = { workspace = true } uuid = { workspace = true } diff --git a/rust/property-defs-rs/src/main.rs b/rust/property-defs-rs/src/main.rs index 2fa7b94614081..044104b30cb9f 100644 --- a/rust/property-defs-rs/src/main.rs +++ b/rust/property-defs-rs/src/main.rs @@ -31,6 +31,8 @@ use tokio::{ use tracing::{info, warn}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer}; +common_alloc::used!(); + fn setup_tracing() { let log_layer: tracing_subscriber::filter::Filtered< tracing_subscriber::fmt::Layer, From 71df845e34644f80e16d030c4d63aab974e3f364 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Thu, 5 Sep 2024 07:57:02 +0100 Subject: [PATCH 16/32] fix: exclude push from auto-generated snippet (#24798) --- frontend/src/lib/components/JSSnippet.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/lib/components/JSSnippet.tsx b/frontend/src/lib/components/JSSnippet.tsx index 5c0c32bbdb9b4..05cbf0cfb6139 100644 --- a/frontend/src/lib/components/JSSnippet.tsx +++ b/frontend/src/lib/components/JSSnippet.tsx @@ -13,7 +13,7 @@ export function snippetFunctions(): string { if ( typeof posthogPrototype[key] === 'function' && !key.startsWith('_') && - !['constructor', 'toString'].includes(key) + !['constructor', 'toString', 'push'].includes(key) ) { methods.push(key) } From 5b4736830adaa19700601d59511384432d1e5da9 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 5 Sep 2024 11:03:02 +0200 Subject: [PATCH 17/32] fix: Calls stack loop for parsing session replay message (#24801) --- .../session-recording/utils.ts | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/plugin-server/src/main/ingestion-queues/session-recording/utils.ts b/plugin-server/src/main/ingestion-queues/session-recording/utils.ts index 94b930625b41d..470905f58ac2d 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/utils.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/utils.ts @@ -324,21 +324,29 @@ export const parseKafkaBatch = async ( continue } - const session_key = `${parsedMessage.team_id}:${parsedMessage.session_id}` - const existingMessage = parsedSessions.get(session_key) + const sessionKey = `${parsedMessage.team_id}:${parsedMessage.session_id}` + const existingMessage = parsedSessions.get(sessionKey) + if (existingMessage === undefined) { // First message for this session key, store it and continue looping for more - parsedSessions.set(session_key, parsedMessage) + parsedSessions.set(sessionKey, parsedMessage) continue } + // Shallow clone the eventsByWindowId object to make sure we don't mutate the original + const newEventsByWindowId: IncomingRecordingMessage['eventsByWindowId'] = Object.entries( + existingMessage.eventsByWindowId + ).reduce((acc, [windowId, events]) => { + acc[windowId] = [...events] + return acc + }, {} as IncomingRecordingMessage['eventsByWindowId']) + for (const [windowId, events] of Object.entries(parsedMessage.eventsByWindowId)) { - if (existingMessage.eventsByWindowId[windowId]) { - existingMessage.eventsByWindowId[windowId].push(...events) - } else { - existingMessage.eventsByWindowId[windowId] = events - } + newEventsByWindowId[windowId] = newEventsByWindowId[windowId] || [] + newEventsByWindowId[windowId].push(...events) } + + existingMessage.eventsByWindowId = newEventsByWindowId existingMessage.metadata.rawSize += parsedMessage.metadata.rawSize // Update the events ranges From 8f74645d33a87e53c1bae3452680b3ad8e880552 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Thu, 5 Sep 2024 10:05:48 +0100 Subject: [PATCH 18/32] fix: handle query errors when loading event properties (#24800) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- ...uccess--second-recording-in-list--dark.png | Bin 58863 -> 58530 bytes .../player/sessionRecordingDataLogic.ts | 49 ++++++++++++------ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png b/frontend/__snapshots__/replay-player-success--second-recording-in-list--dark.png index 1b8480c6221a393eee65ae92e5d676c0bf6cf9bc..3f48b36bd39f54be7ec95a52d1ae8d8efd057368 100644 GIT binary patch literal 58530 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

)ee_c>eYvnRyq4zHlQD?^h%u# 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≠AI-( zKh?(i8`*nvviIcZH;TpLXjx?Fn&4l$f7y|-`>{_rwyX$Tnz}9N=&^sKre_S$&By1Z z+)oeRZTflkTz^(Fc6dDAj8|Shkdyt>-KO}>iTWj9ALH)k8vkzGRL?0NWMt~+j}4K9 z=kkaCCV^2%Bof8OYaZbRhb=L( z^%|{a&t7)2@Q0Cuz5Ts=twx=KxqJWsu6g}0e@;nCm^g7l-si`6W@hQ~vsqVIRJtN? z>6%Fl&z=AP1PDn)K~&X2Jw1x7?0tRq@%HvQa&SMN&yS6ZXC=gE=ALV6>kb||CX0&L zmXes1yuG%s-49$`oMp1e*JjQ9>P%UA`2|*n2Cx=Ws42zeECXceSHH9qe5R08UBN&6;_m>SlOkv~IsMGodIdXw}-I zM-D`72%j?L`IK$x`o%Qd+*}tfm>;n&jHcC*8)E-^{RWFecXiz_EG`{C{^{UVEB5DP zA3A*O?745`@;2tENFs25*+;j1%csp%PPeZkPj%+TxTPt`wm2w)^TURXj= zsx_-uvU0VW+Pcs43#U(?W=Q9jmV1cu%?D9F000+=M8b9Ntc?s`OOjMlN@{Lifn~<+ z=^EPpt*d|V-~mAp9`5c=PL2dY{O?B9`&+h}(n2P5^E@aq_fE#oC`qN$IJQ z(o<|*ZHQLy zy1E3dT)yC~dCVJ6rBdI#SzTOu^0VB0a}VucZ$D?w8#7*cdGh4v-Q8SyJbvTt+r`Bv zPW|)CCku63Bjn|SWr#!~7GwPp!qM?rrrOVN-^fszke81rAHcdH%C{Egi}DvQTDUP* z)^-1WQu21DPzG=eqI>|r>RSMKM5ECdQd$8lfc0J6^%WMC78aG7@A?1$V2uy~0C1N6 z#!oQ3@LB)>fQ2E-2jHw;b8c}8M!{>Y=lCgK!AOA z0000009ZrQv|6oJD3las;*K|_C*F`GX~MGu0000005CVy%Lf1e007_`MEL*!00017 zgD4*W0001hYY^oF00000a1Ek-000000Iorl4*&oF0Khef@&Nz<006iKQ9b|w0002j Z{2v@_G?r+*j>iB1002ovPDHLkV1mZ)W)1)V literal 58863 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[ const { person } = values.sessionPlayerData let loadedProperties: Record = existingEvent.properties - // TODO: Move this to an optimised HogQL query when available... + try { - const res: any = await api.query({ - kind: 'EventsQuery', - select: ['properties', 'timestamp'], - orderBy: ['timestamp ASC'], - limit: 100, - personId: String(person?.id), - after: dayjs(event.timestamp).subtract(1000, 'ms').format(), - before: dayjs(event.timestamp).add(1000, 'ms').format(), - event: existingEvent.event, - }) + const query: HogQLQuery = { + kind: NodeKind.HogQLQuery, + query: hogql`SELECT properties, timestamp, uuid + FROM events + WHERE timestamp > ${dayjs(event.timestamp).subtract(1000, 'ms')} + AND timestamp < ${dayjs(event.timestamp).add(1000, 'ms')} + ${person?.id ? `AND person.id = ${person.id}` : ''} + AND event = ${event.event} + ORDER BY timestamp ASC`, + } + const response = await api.query(query) + if (response.error) { + throw new Error(response.error) + } - const result = res.results.find((x: any) => x[1] === event.timestamp) + // historically we compared timestamps here when finding properties for a particular event + // it's nicer to use the event id + // but since we were using timestamps, we might not be guaranteed to have the id? + // TODO - check if we can remove the timestamp comparison + const result = response.results.find((x: any) => { + if (event.id) { + return x[2] === event.id + } + captureMessage('event id not available for matching', { + tags: { feature: 'session-recording-load-full-event-data' }, + }) + return x[1] === event.timestamp + }) if (result) { loadedProperties = JSON.parse(result[0]) @@ -512,7 +529,9 @@ export const sessionRecordingDataLogic = kea([ } catch (e) { // NOTE: This is not ideal but should happen so rarely that it is tolerable. existingEvent.fullyLoaded = true - captureException(e) + captureException(e, { + tags: { feature: 'session-recording-load-full-event-data' }, + }) } // here we map the events list because we want the result to be a new instance to trigger downstream recalculation From bbdc69ba034efd6b24e9eb7a313b3889ce7eb3da Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 5 Sep 2024 11:56:58 +0200 Subject: [PATCH 19/32] feat(cdp): Add migration for Intercom plugin (#24799) --- posthog/cdp/templates/__init__.py | 3 +- .../templates/intercom/template_intercom.py | 58 +++++++++++-- .../intercom/test_template_intercom.py | 85 ++++++++++++++++++- 3 files changed, 136 insertions(+), 10 deletions(-) diff --git a/posthog/cdp/templates/__init__.py b/posthog/cdp/templates/__init__.py index ca1b3fcea137c..5f7fc637f6136 100644 --- a/posthog/cdp/templates/__init__.py +++ b/posthog/cdp/templates/__init__.py @@ -2,7 +2,7 @@ from .slack.template_slack import template as slack from .hubspot.template_hubspot import template as hubspot from .customerio.template_customerio import template as customerio, TemplateCustomerioMigrator -from .intercom.template_intercom import template as intercom +from .intercom.template_intercom import template as intercom, TemplateIntercomMigrator from .sendgrid.template_sendgrid import template as sendgrid from .clearbit.template_clearbit import template as clearbit from .posthog.template_posthog import template as posthog @@ -39,6 +39,7 @@ HOG_FUNCTION_MIGRATORS = { TemplateCustomerioMigrator.plugin_url: TemplateCustomerioMigrator, + TemplateIntercomMigrator.plugin_url: TemplateIntercomMigrator, } __all__ = ["HOG_FUNCTION_TEMPLATES", "HOG_FUNCTION_TEMPLATES_BY_ID"] diff --git a/posthog/cdp/templates/intercom/template_intercom.py b/posthog/cdp/templates/intercom/template_intercom.py index a8b1bf3d1aed9..fd97f2605759f 100644 --- a/posthog/cdp/templates/intercom/template_intercom.py +++ b/posthog/cdp/templates/intercom/template_intercom.py @@ -1,4 +1,6 @@ -from posthog.cdp.templates.hog_function_template import HogFunctionTemplate +from copy import deepcopy +import dataclasses +from posthog.cdp.templates.hog_function_template import HogFunctionTemplate, HogFunctionTemplateMigrator template: HogFunctionTemplate = HogFunctionTemplate( @@ -8,19 +10,15 @@ description="Send events and contact information to Intercom", icon_url="/static/services/intercom.png", hog=""" -let accessToken := inputs.access_token -let host := inputs.host -let email := inputs.email - -if (empty(email)) { +if (empty(inputs.email)) { print('`email` input is empty. Skipping.') return } -let res := fetch(f'https://{host}/events', { +let res := fetch(f'https://{inputs.host}/events', { 'method': 'POST', 'headers': { - 'Authorization': f'Bearer {accessToken}', + 'Authorization': f'Bearer {inputs.access_token}', 'Content-Type': 'application/json', 'Accept': 'application/json' }, @@ -89,3 +87,47 @@ "filter_test_accounts": True, }, ) + + +class TemplateIntercomMigrator(HogFunctionTemplateMigrator): + plugin_url = "https://github.com/PostHog/posthog-intercom-plugin" + + @classmethod + def migrate(cls, obj): + hf = deepcopy(dataclasses.asdict(template)) + + useEuropeanDataStorage = obj.config.get("useEuropeanDataStorage", "No") + intercomApiKey = obj.config.get("intercomApiKey", "") + triggeringEvents = obj.config.get("triggeringEvents", "$identify") + ignoredEmailDomains = obj.config.get("ignoredEmailDomains", "") + + hf["filters"] = {} + + events_to_filter = [event.strip() for event in triggeringEvents.split(",") if event.strip()] + domains_to_filter = [domain.strip() for domain in ignoredEmailDomains.split(",") if domain.strip()] + + if domains_to_filter: + hf["filters"]["properties"] = [ + { + "key": "email", + "value": domain, + "operator": "not_icontains", + "type": "person", + } + for domain in domains_to_filter + ] + + if events_to_filter: + hf["filters"]["events"] = [ + {"id": event, "name": event, "type": "events", "order": 0} for event in events_to_filter + ] + + hf["inputs"] = { + "access_token": {"value": intercomApiKey}, + "host": {"value": "api.eu.intercom.com"} + if useEuropeanDataStorage == "Yes" + else {"value": "api.intercom.io"}, + "email": {"value": "{person.properties.email}"}, + } + + return hf diff --git a/posthog/cdp/templates/intercom/test_template_intercom.py b/posthog/cdp/templates/intercom/test_template_intercom.py index 9d9ec4aedb39a..f76f48f1d5485 100644 --- a/posthog/cdp/templates/intercom/test_template_intercom.py +++ b/posthog/cdp/templates/intercom/test_template_intercom.py @@ -1,5 +1,8 @@ +from inline_snapshot import snapshot from posthog.cdp.templates.helpers import BaseHogFunctionTemplateTest -from posthog.cdp.templates.intercom.template_intercom import template as template_intercom +from posthog.cdp.templates.intercom.template_intercom import template as template_intercom, TemplateIntercomMigrator +from posthog.models.plugin import PluginConfig +from posthog.test.base import BaseTest class TestTemplateIntercom(BaseHogFunctionTemplateTest): @@ -77,3 +80,83 @@ def test_logs_other_errors(self): }, ) ] + + +class TestTemplateMigration(BaseTest): + def get_plugin_config(self, config: dict): + _config = { + "intercomApiKey": "INTERCOM_API_KEY", + "triggeringEvents": "$identify", + "ignoredEmailDomains": "", + "useEuropeanDataStorage": "No", + } + + _config.update(config) + return PluginConfig(enabled=True, order=0, config=_config) + + def test_full_function(self): + obj = self.get_plugin_config({}) + + template = TemplateIntercomMigrator.migrate(obj) + assert template["inputs"] == snapshot( + { + "access_token": {"value": "INTERCOM_API_KEY"}, + "host": {"value": "api.intercom.io"}, + "email": {"value": "{person.properties.email}"}, + } + ) + assert template["filters"] == snapshot( + {"events": [{"id": "$identify", "name": "$identify", "type": "events", "order": 0}]} + ) + + def test_eu_host(self): + obj = self.get_plugin_config( + { + "useEuropeanDataStorage": "Yes", + } + ) + + template = TemplateIntercomMigrator.migrate(obj) + assert template["inputs"] == snapshot( + { + "access_token": {"value": "INTERCOM_API_KEY"}, + "host": {"value": "api.eu.intercom.com"}, + "email": {"value": "{person.properties.email}"}, + } + ) + + def test_triggering_events(self): + obj = self.get_plugin_config( + { + "triggeringEvents": "$identify,$pageview, custom event, ", + } + ) + + template = TemplateIntercomMigrator.migrate(obj) + assert template["filters"] == snapshot( + { + "events": [ + {"id": "$identify", "name": "$identify", "type": "events", "order": 0}, + {"id": "$pageview", "name": "$pageview", "type": "events", "order": 0}, + {"id": "custom event", "name": "custom event", "type": "events", "order": 0}, + ] + } + ) + + def test_ignore_domains(self): + obj = self.get_plugin_config( + { + "ignoredEmailDomains": "test.com, other.com, ", + } + ) + + template = TemplateIntercomMigrator.migrate(obj) + assert template["filters"] == snapshot( + { + "properties": [ + {"key": "email", "value": "test.com", "operator": "not_icontains", "type": "person"}, + {"key": "email", "value": "other.com", "operator": "not_icontains", "type": "person"}, + ], + "events": [{"id": "$identify", "name": "$identify", "type": "events", "order": 0}], + } + ) From 70c6ce8885ca5f94ec2f8f9b8cf88d867295217a Mon Sep 17 00:00:00 2001 From: Marius Andra Date: Thu, 5 Sep 2024 12:07:12 +0200 Subject: [PATCH 20/32] feat(hog): fix elements matching (#24331) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- .../hogFunctionConfigurationLogic.tsx | 21 ++- hogvm/__tests__/__snapshots__/arrays.hoge | 5 +- hogvm/__tests__/__snapshots__/arrays.stdout | 5 + hogvm/__tests__/__snapshots__/strings.hoge | 7 +- hogvm/__tests__/__snapshots__/strings.stdout | 8 + hogvm/__tests__/arrays.hog | 7 + hogvm/__tests__/strings.hog | 8 + hogvm/python/stl/__init__.py | 21 +++ hogvm/python/stl/bytecode.py | 1 + hogvm/stl/src/arrayCount.hog | 9 + hogvm/typescript/package.json | 2 +- hogvm/typescript/src/stl/bytecode.ts | 1 + hogvm/typescript/src/stl/stl.ts | 33 ++++ package.json | 2 +- plugin-server/package.json | 2 +- plugin-server/pnpm-lock.yaml | 8 +- plugin-server/src/cdp/types.ts | 18 +- plugin-server/src/cdp/utils.ts | 105 +++++++++--- plugin-server/tests/cdp/examples.ts | 161 ++++++++++++++++++ plugin-server/tests/cdp/hog-executor.test.ts | 150 ++++++++++++++++ pnpm-lock.yaml | 14 +- posthog/hogql/property.py | 31 ++-- posthog/hogql/test/test_property.py | 18 ++ 23 files changed, 567 insertions(+), 70 deletions(-) create mode 100644 hogvm/stl/src/arrayCount.hog diff --git a/frontend/src/scenes/pipeline/hogfunctions/hogFunctionConfigurationLogic.tsx b/frontend/src/scenes/pipeline/hogfunctions/hogFunctionConfigurationLogic.tsx index dacfed655a513..2c46f62d4bf4b 100644 --- a/frontend/src/scenes/pipeline/hogfunctions/hogFunctionConfigurationLogic.tsx +++ b/frontend/src/scenes/pipeline/hogfunctions/hogFunctionConfigurationLogic.tsx @@ -36,6 +36,7 @@ import { PipelineTab, PropertyFilterType, PropertyGroupFilter, + PropertyGroupFilterValue, } from '~/types' import { EmailTemplate } from './email-templater/emailTemplaterLogic' @@ -448,10 +449,14 @@ export const hogFunctionConfigurationLogic = kea [s.configuration], (configuration): TrendsQuery => { - const properties: PropertyGroupFilter = { + const seriesProperties: PropertyGroupFilterValue = { type: FilterLogicalOperator.Or, values: [], } + const properties: PropertyGroupFilter = { + type: FilterLogicalOperator.And, + values: [seriesProperties], + } for (const event of configuration.filters?.events ?? []) { const eventProperties: AnyPropertyFilter[] = [...(event.properties ?? [])] if (event.id) { @@ -466,7 +471,7 @@ export const hogFunctionConfigurationLogic = kea 0) { + const globalProperties: PropertyGroupFilterValue = { + type: FilterLogicalOperator.And, + values: [], + } + for (const property of configuration.filters?.properties ?? []) { + globalProperties.values.push(property as AnyPropertyFilter) + } + properties.values.push(globalProperties) + } return { kind: NodeKind.TrendsQuery, diff --git a/hogvm/__tests__/__snapshots__/arrays.hoge b/hogvm/__tests__/__snapshots__/arrays.hoge index 4afcc23ad537a..37cfb21b32bde 100644 --- a/hogvm/__tests__/__snapshots__/arrays.hoge +++ b/hogvm/__tests__/__snapshots__/arrays.hoge @@ -24,4 +24,7 @@ 35, 32, "------", 2, "print", 1, 35, 36, 2, 33, 0, 2, "has", 2, 2, "print", 1, 35, 36, 2, 33, 2, 2, "has", 2, 2, "print", 1, 35, 36, 2, 32, "banana", 2, "has", 2, 2, "print", 1, 35, 32, "banananas", 32, "banana", 2, "has", 2, 2, "print", 1, 35, 32, "banananas", 32, "foo", 2, "has", 2, 2, "print", 1, 35, 32, "1", 32, "2", 43, 2, 32, "1", 2, "has", -2, 2, "print", 1, 35, 35, 35, 35] +2, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 43, 3, 33, 1, 2, "indexOf", 2, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 43, 3, +33, 2, 2, "indexOf", 2, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 43, 3, 33, 3, 2, "indexOf", 2, 2, "print", 1, 35, 33, 1, +33, 2, 33, 3, 43, 3, 33, 4, 2, "indexOf", 2, 2, "print", 1, 35, 52, "lambda", 1, 0, 6, 33, 2, 36, 0, 13, 38, 53, 0, 33, +1, 33, 2, 33, 3, 33, 4, 33, 5, 43, 5, 2, "arrayCount", 2, 2, "print", 1, 35, 35, 35, 35] diff --git a/hogvm/__tests__/__snapshots__/arrays.stdout b/hogvm/__tests__/__snapshots__/arrays.stdout index d582bb4c45219..84e5d1b160aff 100644 --- a/hogvm/__tests__/__snapshots__/arrays.stdout +++ b/hogvm/__tests__/__snapshots__/arrays.stdout @@ -46,3 +46,8 @@ false false false true +1 +2 +3 +0 +3 diff --git a/hogvm/__tests__/__snapshots__/strings.hoge b/hogvm/__tests__/__snapshots__/strings.hoge index 0c3118d3a043e..2143350e53df1 100644 --- a/hogvm/__tests__/__snapshots__/strings.hoge +++ b/hogvm/__tests__/__snapshots__/strings.hoge @@ -8,4 +8,9 @@ "print", 1, 35, 32, "banana", 32, "n", 2, "like", 2, 2, "print", 1, 35, 32, "banana", 32, "naan", 2, "like", 2, 2, "print", 1, 35, 32, "banana", 32, "N", 2, "ilike", 2, 2, "print", 1, 35, 32, "banana", 32, "n", 2, "ilike", 2, 2, "print", 1, 35, 32, "banana", 32, "naan", 2, "ilike", 2, 2, "print", 1, 35, 32, "banana", 32, "N", 2, "notLike", 2, 2, -"print", 1, 35, 32, "banana", 32, "NO", 2, "notILike", 2, 2, "print", 1, 35] +"print", 1, 35, 32, "banana", 32, "NO", 2, "notILike", 2, 2, "print", 1, 35, 32, "abc", 32, "a", 2, "position", 2, 2, +"print", 1, 35, 32, "abc", 32, "b", 2, "position", 2, 2, "print", 1, 35, 32, "abc", 32, "c", 2, "position", 2, 2, +"print", 1, 35, 32, "abc", 32, "d", 2, "position", 2, 2, "print", 1, 35, 32, "AbC", 32, "a", 2, +"positionCaseInsensitive", 2, 2, "print", 1, 35, 32, "AbC", 32, "b", 2, "positionCaseInsensitive", 2, 2, "print", 1, 35, +32, "AbC", 32, "c", 2, "positionCaseInsensitive", 2, 2, "print", 1, 35, 32, "AbC", 32, "d", 2, +"positionCaseInsensitive", 2, 2, "print", 1, 35] diff --git a/hogvm/__tests__/__snapshots__/strings.stdout b/hogvm/__tests__/__snapshots__/strings.stdout index 4c5bfc110b5b7..57808971dd3f3 100644 --- a/hogvm/__tests__/__snapshots__/strings.stdout +++ b/hogvm/__tests__/__snapshots__/strings.stdout @@ -16,3 +16,11 @@ true false true true +1 +2 +3 +0 +1 +2 +3 +0 diff --git a/hogvm/__tests__/arrays.hog b/hogvm/__tests__/arrays.hog index 6f934807566d9..67d07c451a1ff 100644 --- a/hogvm/__tests__/arrays.hog +++ b/hogvm/__tests__/arrays.hog @@ -64,3 +64,10 @@ print(has(arr, 'banana')) print(has('banananas', 'banana')) print(has('banananas', 'foo')) print(has(['1', '2'], '1')) + +print(indexOf([1,2,3], 1)) // 1 +print(indexOf([1,2,3], 2)) // 2 +print(indexOf([1,2,3], 3)) // 3 +print(indexOf([1,2,3], 4)) // 0 + +print(arrayCount(x -> x > 2, [1,2,3,4,5])) // 3 \ No newline at end of file diff --git a/hogvm/__tests__/strings.hog b/hogvm/__tests__/strings.hog index 322e08bdc51ef..e8d0eab7b8e93 100644 --- a/hogvm/__tests__/strings.hog +++ b/hogvm/__tests__/strings.hog @@ -16,3 +16,11 @@ print(ilike('banana', 'n')) print(ilike('banana', 'naan')) print(notLike('banana', 'N')) print(notILike('banana', 'NO')) +print(position('abc', 'a')) // 1 +print(position('abc', 'b')) // 2 +print(position('abc', 'c')) // 3 +print(position('abc', 'd')) // 0 +print(positionCaseInsensitive('AbC', 'a')) // 1 +print(positionCaseInsensitive('AbC', 'b')) // 2 +print(positionCaseInsensitive('AbC', 'c')) // 3 +print(positionCaseInsensitive('AbC', 'd')) // 0 diff --git a/hogvm/python/stl/__init__.py b/hogvm/python/stl/__init__.py index feaae8a899aeb..a20b39d8c00bf 100644 --- a/hogvm/python/stl/__init__.py +++ b/hogvm/python/stl/__init__.py @@ -386,6 +386,20 @@ def _typeof(args: list[Any], team: Optional["Team"], stdout: Optional[list[str]] "replaceAll": STLFunction( fn=lambda args, team, stdout, timeout: args[0].replace(args[1], args[2]), minArgs=3, maxArgs=3 ), + "position": STLFunction( + fn=lambda args, team, stdout, timeout: (args[0].index(str(args[1])) + 1) + if isinstance(args[0], str) and str(args[1]) in args[0] + else 0, + minArgs=2, + maxArgs=2, + ), + "positionCaseInsensitive": STLFunction( + fn=lambda args, team, stdout, timeout: (args[0].lower().index(str(args[1]).lower()) + 1) + if isinstance(args[0], str) and str(args[1]).lower() in args[0].lower() + else 0, + minArgs=2, + maxArgs=2, + ), "trim": STLFunction(fn=trim, minArgs=1, maxArgs=2), "trimLeft": STLFunction(fn=trimLeft, minArgs=1, maxArgs=2), "trimRight": STLFunction(fn=trimRight, minArgs=1, maxArgs=2), @@ -398,6 +412,13 @@ def _typeof(args: list[Any], team: Optional["Team"], stdout: Optional[list[str]] ), "keys": STLFunction(fn=keys, minArgs=1, maxArgs=1), "values": STLFunction(fn=values, minArgs=1, maxArgs=1), + "indexOf": STLFunction( + fn=lambda args, team, stdout, timeout: (args[0].index(args[1]) + 1) + if isinstance(args[0], list) and args[1] in args[0] + else 0, + minArgs=2, + maxArgs=2, + ), "arrayPushBack": STLFunction(fn=arrayPushBack, minArgs=2, maxArgs=2), "arrayPushFront": STLFunction(fn=arrayPushFront, minArgs=2, maxArgs=2), "arrayPopBack": STLFunction(fn=arrayPopBack, minArgs=1, maxArgs=1), diff --git a/hogvm/python/stl/bytecode.py b/hogvm/python/stl/bytecode.py index c84573e89e300..748128e075dce 100644 --- a/hogvm/python/stl/bytecode.py +++ b/hogvm/python/stl/bytecode.py @@ -1,6 +1,7 @@ # This file is generated by hogvm/stl/compile.py # fmt: off BYTECODE_STL: dict[str, tuple[list[str], list]] = { + "arrayCount": (["func", "arr"], [33, 0, 36, 1, 36, 3, 2, "values", 1, 33, 1, 36, 4, 2, "length", 1, 31, 36, 6, 36, 5, 16, 40, 31, 36, 4, 36, 5, 45, 37, 7, 36, 7, 36, 0, 54, 1, 40, 7, 33, 1, 36, 2, 6, 37, 2, 36, 5, 33, 1, 6, 37, 5, 39, -38, 35, 35, 35, 35, 35, 36, 2, 38, 35]), "arrayExists": (["func", "arr"], [36, 1, 36, 2, 2, "values", 1, 33, 1, 36, 3, 2, "length", 1, 31, 36, 5, 36, 4, 16, 40, 26, 36, 3, 36, 4, 45, 37, 6, 36, 6, 36, 0, 54, 1, 40, 2, 29, 38, 36, 4, 33, 1, 6, 37, 4, 39, -33, 35, 35, 35, 35, 35, 30, 38]), "arrayFilter": (["func", "arr"], [43, 0, 36, 1, 36, 3, 2, "values", 1, 33, 1, 36, 4, 2, "length", 1, 31, 36, 6, 36, 5, 16, 40, 33, 36, 4, 36, 5, 45, 37, 7, 36, 7, 36, 0, 54, 1, 40, 9, 36, 2, 36, 7, 2, "arrayPushBack", 2, 37, 2, 36, 5, 33, 1, 6, 37, 5, 39, -40, 35, 35, 35, 35, 35, 36, 2, 38, 35]), "arrayMap": (["func", "arr"], [43, 0, 36, 1, 36, 3, 2, "values", 1, 33, 1, 36, 4, 2, "length", 1, 31, 36, 6, 36, 5, 16, 40, 29, 36, 4, 36, 5, 45, 37, 7, 36, 2, 36, 7, 36, 0, 54, 1, 2, "arrayPushBack", 2, 37, 2, 36, 5, 33, 1, 6, 37, 5, 39, -36, 35, 35, 35, 35, 35, 36, 2, 38, 35]), diff --git a/hogvm/stl/src/arrayCount.hog b/hogvm/stl/src/arrayCount.hog new file mode 100644 index 0000000000000..da2cac89c27fa --- /dev/null +++ b/hogvm/stl/src/arrayCount.hog @@ -0,0 +1,9 @@ +fn arrayCount(func, arr) { + let count := 0 + for (let i in arr) { + if (func(i)) { + count := count + 1 + } + } + return count +} diff --git a/hogvm/typescript/package.json b/hogvm/typescript/package.json index 8a52d73906343..c02fa2faf7f9c 100644 --- a/hogvm/typescript/package.json +++ b/hogvm/typescript/package.json @@ -1,6 +1,6 @@ { "name": "@posthog/hogvm", - "version": "1.0.44", + "version": "1.0.46", "description": "PostHog Hog Virtual Machine", "types": "dist/index.d.ts", "source": "src/index.ts", diff --git a/hogvm/typescript/src/stl/bytecode.ts b/hogvm/typescript/src/stl/bytecode.ts index d966188adaeaa..50e417c8ccb90 100644 --- a/hogvm/typescript/src/stl/bytecode.ts +++ b/hogvm/typescript/src/stl/bytecode.ts @@ -1,5 +1,6 @@ // This file is generated by hogvm/stl/compile.py export const BYTECODE_STL: Record = { + "arrayCount": [["func", "arr"], [33, 0, 36, 1, 36, 3, 2, "values", 1, 33, 1, 36, 4, 2, "length", 1, 31, 36, 6, 36, 5, 16, 40, 31, 36, 4, 36, 5, 45, 37, 7, 36, 7, 36, 0, 54, 1, 40, 7, 33, 1, 36, 2, 6, 37, 2, 36, 5, 33, 1, 6, 37, 5, 39, -38, 35, 35, 35, 35, 35, 36, 2, 38, 35]], "arrayExists": [["func", "arr"], [36, 1, 36, 2, 2, "values", 1, 33, 1, 36, 3, 2, "length", 1, 31, 36, 5, 36, 4, 16, 40, 26, 36, 3, 36, 4, 45, 37, 6, 36, 6, 36, 0, 54, 1, 40, 2, 29, 38, 36, 4, 33, 1, 6, 37, 4, 39, -33, 35, 35, 35, 35, 35, 30, 38]], "arrayFilter": [["func", "arr"], [43, 0, 36, 1, 36, 3, 2, "values", 1, 33, 1, 36, 4, 2, "length", 1, 31, 36, 6, 36, 5, 16, 40, 33, 36, 4, 36, 5, 45, 37, 7, 36, 7, 36, 0, 54, 1, 40, 9, 36, 2, 36, 7, 2, "arrayPushBack", 2, 37, 2, 36, 5, 33, 1, 6, 37, 5, 39, -40, 35, 35, 35, 35, 35, 36, 2, 38, 35]], "arrayMap": [["func", "arr"], [43, 0, 36, 1, 36, 3, 2, "values", 1, 33, 1, 36, 4, 2, "length", 1, 31, 36, 6, 36, 5, 16, 40, 29, 36, 4, 36, 5, 45, 37, 7, 36, 2, 36, 7, 36, 0, 54, 1, 2, "arrayPushBack", 2, 37, 2, 36, 5, 33, 1, 6, 37, 5, 39, -36, 35, 35, 35, 35, 35, 36, 2, 38, 35]], diff --git a/hogvm/typescript/src/stl/stl.ts b/hogvm/typescript/src/stl/stl.ts index 1e8282730900b..bb2fcb5280a6b 100644 --- a/hogvm/typescript/src/stl/stl.ts +++ b/hogvm/typescript/src/stl/stl.ts @@ -294,6 +294,28 @@ export const STL: Record = { minArgs: 3, maxArgs: 3, }, + position: { + fn: ([str, elem]) => { + if (typeof str === 'string') { + return str.indexOf(String(elem)) + 1 + } else { + return 0 + } + }, + minArgs: 2, + maxArgs: 2, + }, + positionCaseInsensitive: { + fn: ([str, elem]) => { + if (typeof str === 'string') { + return str.toLowerCase().indexOf(String(elem).toLowerCase()) + 1 + } else { + return 0 + } + }, + minArgs: 2, + maxArgs: 2, + }, trim: { fn: ([str, char]) => { if (char === null || char === undefined) { @@ -418,6 +440,17 @@ export const STL: Record = { minArgs: 1, maxArgs: 1, }, + indexOf: { + fn: ([arrOrString, elem]) => { + if (Array.isArray(arrOrString)) { + return arrOrString.indexOf(elem) + 1 + } else { + return 0 + } + }, + minArgs: 2, + maxArgs: 2, + }, arrayPushBack: { fn: ([arr, item]) => { if (!Array.isArray(arr)) { diff --git a/package.json b/package.json index 44309818ccdb6..f6837fc45cf67 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "@medv/finder": "^3.1.0", "@microlink/react-json-view": "^1.21.3", "@monaco-editor/react": "4.6.0", - "@posthog/hogvm": "^1.0.44", + "@posthog/hogvm": "^1.0.46", "@posthog/icons": "0.8.1", "@posthog/plugin-scaffold": "^1.4.4", "@react-hook/size": "^2.1.2", diff --git a/plugin-server/package.json b/plugin-server/package.json index 75a137b2e1924..b6b9147b14bbf 100644 --- a/plugin-server/package.json +++ b/plugin-server/package.json @@ -53,7 +53,7 @@ "@maxmind/geoip2-node": "^3.4.0", "@posthog/clickhouse": "^1.7.0", "@posthog/cyclotron": "file:../rust/cyclotron-node", - "@posthog/hogvm": "^1.0.44", + "@posthog/hogvm": "^1.0.46", "@posthog/plugin-scaffold": "1.4.4", "@sentry/node": "^7.49.0", "@sentry/profiling-node": "^0.3.0", diff --git a/plugin-server/pnpm-lock.yaml b/plugin-server/pnpm-lock.yaml index 08f08046ad14c..dd40fb3bf24e3 100644 --- a/plugin-server/pnpm-lock.yaml +++ b/plugin-server/pnpm-lock.yaml @@ -47,8 +47,8 @@ dependencies: specifier: file:../rust/cyclotron-node version: file:../rust/cyclotron-node '@posthog/hogvm': - specifier: ^1.0.44 - version: 1.0.44(luxon@3.4.4) + specifier: ^1.0.46 + version: 1.0.46(luxon@3.4.4) '@posthog/plugin-scaffold': specifier: 1.4.4 version: 1.4.4 @@ -3116,8 +3116,8 @@ packages: engines: {node: '>=12'} dev: false - /@posthog/hogvm@1.0.44(luxon@3.4.4): - resolution: {integrity: sha512-Ss7gTPyvPyviNipVQOqnsCa66IMmMf+DEg7iX/vQMcWDuFwvHNbdze1iwFVoXCjLci+h8SW2rOMPB0S5A2jJXg==} + /@posthog/hogvm@1.0.46(luxon@3.4.4): + resolution: {integrity: sha512-oTXytxHImxcAUYvK+QVI5nRc3YnVSbn01rFlOrpeTYjW5oqYKMR8nYsjhHGLt5p0pnfeBhmQjBM5mJtVs5bA2Q==} peerDependencies: luxon: ^3.4.4 dependencies: diff --git a/plugin-server/src/cdp/types.ts b/plugin-server/src/cdp/types.ts index 3c4eed47c6d41..9d277bc4edfa8 100644 --- a/plugin-server/src/cdp/types.ts +++ b/plugin-server/src/cdp/types.ts @@ -47,20 +47,6 @@ export interface HogFunctionFilters { bytecode?: HogBytecode } -// We have a "parsed" clickhous event type to make it easier to work with calls from kafka as well as those from the frontend -export interface ParsedClickhouseEvent { - uuid: string - event: string - team_id: number - distinct_id: string - person_id?: string - timestamp: string - created_at: string - properties: Record - person_created_at?: string - person_properties: Record -} - export type GroupType = { id: string // the "key" of the group type: string @@ -105,6 +91,10 @@ export type HogFunctionFilterGlobals = { event: string timestamp: string elements_chain: string + elements_chain_href: string + elements_chain_texts: string[] + elements_chain_ids: string[] + elements_chain_elements: string[] properties: Record person?: { diff --git a/plugin-server/src/cdp/utils.ts b/plugin-server/src/cdp/utils.ts index 158814718dc0a..375baa91a94e3 100644 --- a/plugin-server/src/cdp/utils.ts +++ b/plugin-server/src/cdp/utils.ts @@ -1,6 +1,7 @@ // NOTE: PostIngestionEvent is our context event - it should never be sent directly to an output, but rather transformed into a lightweight schema import { DateTime } from 'luxon' +import RE2 from 're2' import { gunzip, gzip } from 'zlib' import { RawClickHouseEvent, Team, TimestampFormat } from '../types' @@ -15,7 +16,6 @@ import { HogFunctionInvocationSerialized, HogFunctionLogEntrySerialized, HogFunctionType, - ParsedClickhouseEvent, } from './types' export const PERSON_DEFAULT_DISPLAY_NAME_PROPERTIES = [ @@ -39,26 +39,6 @@ const getPersonDisplayName = (team: Team, distinctId: string, properties: Record return (customIdentifier || distinctId)?.trim() } -export function convertToParsedClickhouseEvent(event: RawClickHouseEvent): ParsedClickhouseEvent { - const properties = event.properties ? JSON.parse(event.properties) : {} - if (event.elements_chain) { - properties['$elements_chain'] = event.elements_chain - } - - return { - uuid: event.uuid, - event: event.event, - team_id: event.team_id, - distinct_id: event.distinct_id, - person_id: event.person_id, - timestamp: clickHouseTimestampToISO(event.timestamp), - created_at: clickHouseTimestampToISO(event.created_at), - properties: properties, - person_created_at: event.person_created_at ? clickHouseTimestampToISO(event.person_created_at) : undefined, - person_properties: event.person_properties ? JSON.parse(event.person_properties) : {}, - } -} - // that we can keep to as a contract export function convertToHogFunctionInvocationGlobals( event: RawClickHouseEvent, @@ -108,6 +88,46 @@ export function convertToHogFunctionInvocationGlobals( return context } +function getElementsChainHref(elementsChain: string): string { + // Adapted from SQL: extract(elements_chain, '(?::|\")href="(.*?)"'), + const hrefRegex = new RE2(/(?::|")href="(.*?)"/) + const hrefMatch = hrefRegex.exec(elementsChain) + return hrefMatch ? hrefMatch[1] : '' +} + +function getElementsChainTexts(elementsChain: string): string[] { + // Adapted from SQL: arrayDistinct(extractAll(elements_chain, '(?::|\")text="(.*?)"')), + const textRegex = new RE2(/(?::|")text="(.*?)"/g) + const textMatches = new Set() + let textMatch + while ((textMatch = textRegex.exec(elementsChain)) !== null) { + textMatches.add(textMatch[1]) + } + return Array.from(textMatches) +} + +function getElementsChainIds(elementsChain: string): string[] { + // Adapted from SQL: arrayDistinct(extractAll(elements_chain, '(?::|\")attr_id="(.*?)"')), + const idRegex = new RE2(/(?::|")attr_id="(.*?)"/g) + const idMatches = new Set() + let idMatch + while ((idMatch = idRegex.exec(elementsChain)) !== null) { + idMatches.add(idMatch[1]) + } + return Array.from(idMatches) +} + +function getElementsChainElements(elementsChain: string): string[] { + // Adapted from SQL: arrayDistinct(extractAll(elements_chain, '(?:^|;)(a|button|form|input|select|textarea|label)(?:\\.|$|:)')) + const elementRegex = new RE2(/(?:^|;)(a|button|form|input|select|textarea|label)(?:\.|$|:)/g) + const elementMatches = new Set() + let elementMatch + while ((elementMatch = elementRegex.exec(elementsChain)) !== null) { + elementMatches.add(elementMatch[1]) + } + return Array.from(elementMatches) +} + export function convertToHogFunctionFilterGlobal(globals: HogFunctionInvocationGlobals): HogFunctionFilterGlobals { const groups: Record = {} @@ -117,14 +137,53 @@ export function convertToHogFunctionFilterGlobal(globals: HogFunctionInvocationG } } - return { + const elementsChain = globals.event.properties['$elements_chain'] + const response = { event: globals.event.name, - elements_chain: globals.event.properties['$elements_chain'], + elements_chain: elementsChain, + elements_chain_href: '', + elements_chain_texts: [] as string[], + elements_chain_ids: [] as string[], + elements_chain_elements: [] as string[], timestamp: globals.event.timestamp, properties: globals.event.properties, person: globals.person ? { properties: globals.person.properties } : undefined, ...groups, + } satisfies HogFunctionFilterGlobals + + // The elements_chain_* fields are stored as materialized columns in ClickHouse. + // We use the same formula to calculate them here. + if (elementsChain) { + const cache: Record = {} + Object.defineProperties(response, { + elements_chain_href: { + get: () => { + cache.elements_chain_href ??= getElementsChainHref(elementsChain) + return cache.elements_chain_href + }, + }, + elements_chain_texts: { + get: () => { + cache.elements_chain_texts ??= getElementsChainTexts(elementsChain) + return cache.elements_chain_texts + }, + }, + elements_chain_ids: { + get: () => { + cache.elements_chain_ids ??= getElementsChainIds(elementsChain) + return cache.elements_chain_ids + }, + }, + elements_chain_elements: { + get: () => { + cache.elements_chain_elements ??= getElementsChainElements(elementsChain) + return cache.elements_chain_elements + }, + }, + }) } + + return response } export const convertToCaptureEvent = (event: HogFunctionCapturedEvent, team: Team): any => { diff --git a/plugin-server/tests/cdp/examples.ts b/plugin-server/tests/cdp/examples.ts index c662e31aae187..a3f696c32187c 100644 --- a/plugin-server/tests/cdp/examples.ts +++ b/plugin-server/tests/cdp/examples.ts @@ -417,6 +417,167 @@ export const HOG_FILTERS_EXAMPLES: Record> = { diff --git a/plugin-server/tests/cdp/hog-executor.test.ts b/plugin-server/tests/cdp/hog-executor.test.ts index dc6350e0bb3d2..7740078fe6268 100644 --- a/plugin-server/tests/cdp/hog-executor.test.ts +++ b/plugin-server/tests/cdp/hog-executor.test.ts @@ -233,6 +233,156 @@ describe('Hog Executor', () => { expect(resultsShouldMatch.matchingFunctions).toHaveLength(1) expect(resultsShouldMatch.nonMatchingFunctions).toHaveLength(0) }) + + it('can use elements_chain_texts', () => { + const fn = createHogFunction({ + ...HOG_EXAMPLES.simple_fetch, + ...HOG_INPUTS_EXAMPLES.simple_fetch, + ...HOG_FILTERS_EXAMPLES.elements_text_filter, + }) + + mockFunctionManager.getTeamHogFunctions.mockReturnValue([fn]) + const elementsChain = (buttonText: string) => + `span.LemonButton__content:attr__class="LemonButton__content"nth-child="2"nth-of-type="2"text="${buttonText}";span.LemonButton__chrome:attr__class="LemonButton__chrome"nth-child="1"nth-of-type="1";button.LemonButton.LemonButton--has-icon.LemonButton--secondary.LemonButton--status-default:attr__class="LemonButton LemonButton--secondary LemonButton--status-default LemonButton--has-icon"attr__type="button"nth-child="1"nth-of-type="1"text="${buttonText}";div.flex.gap-4.items-center:attr__class="flex gap-4 items-center"nth-child="1"nth-of-type="1";div.flex.flex-wrap.gap-4.justify-between:attr__class="flex gap-4 justify-between flex-wrap"nth-child="3"nth-of-type="3";div.flex.flex-1.flex-col.gap-4.h-full.relative.w-full:attr__class="relative w-full flex flex-col gap-4 flex-1 h-full"nth-child="1"nth-of-type="1";div.LemonTabs__content:attr__class="LemonTabs__content"nth-child="2"nth-of-type="1";div.LemonTabs.LemonTabs--medium:attr__class="LemonTabs LemonTabs--medium"attr__style="--lemon-tabs-slider-width: 48px; --lemon-tabs-slider-offset: 0px;"nth-child="1"nth-of-type="1";div.Navigation3000__scene:attr__class="Navigation3000__scene"nth-child="2"nth-of-type="2";main:nth-child="2"nth-of-type="1";div.Navigation3000:attr__class="Navigation3000"nth-child="1"nth-of-type="1";div:attr__id="root"attr_id="root"nth-child="3"nth-of-type="1";body.overflow-hidden:attr__class="overflow-hidden"attr__theme="light"nth-child="2"nth-of-type="1"` + + const hogGlobals1 = createHogExecutionGlobals({ + groups: {}, + event: { + uuid: 'uuid', + name: '$autocapture', + distinct_id: 'distinct_id', + url: 'http://localhost:8000/events/1', + properties: { + $lib_version: '1.2.3', + $elements_chain: elementsChain('Not our text'), + }, + timestamp: new Date().toISOString(), + }, + }) + + const resultsShouldntMatch = executor.findMatchingFunctions(hogGlobals1) + expect(resultsShouldntMatch.matchingFunctions).toHaveLength(0) + expect(resultsShouldntMatch.nonMatchingFunctions).toHaveLength(1) + + const hogGlobals2 = createHogExecutionGlobals({ + groups: {}, + event: { + uuid: 'uuid', + name: '$autocapture', + distinct_id: 'distinct_id', + url: 'http://localhost:8000/events/1', + properties: { + $lib_version: '1.2.3', + $elements_chain: elementsChain('Reload'), + }, + timestamp: new Date().toISOString(), + }, + }) + + const resultsShouldMatch = executor.findMatchingFunctions(hogGlobals2) + expect(resultsShouldMatch.matchingFunctions).toHaveLength(1) + expect(resultsShouldMatch.nonMatchingFunctions).toHaveLength(0) + }) + + it('can use elements_chain_href', () => { + const fn = createHogFunction({ + ...HOG_EXAMPLES.simple_fetch, + ...HOG_INPUTS_EXAMPLES.simple_fetch, + ...HOG_FILTERS_EXAMPLES.elements_href_filter, + }) + + mockFunctionManager.getTeamHogFunctions.mockReturnValue([fn]) + const elementsChain = (link: string) => + `span.LemonButton__content:attr__class="LemonButton__content"attr__href="${link}"href="${link}"nth-child="2"nth-of-type="2"text="Activity";span.LemonButton__chrome:attr__class="LemonButton__chrome"nth-child="1"nth-of-type="1";a.LemonButton.LemonButton--full-width.LemonButton--has-icon.LemonButton--secondary.LemonButton--status-alt.Link.NavbarButton:attr__class="Link LemonButton LemonButton--secondary LemonButton--status-alt LemonButton--full-width LemonButton--has-icon NavbarButton"attr__data-attr="menu-item-activity"attr__href="${link}"href="${link}"nth-child="1"nth-of-type="1"text="Activity";li.w-full:attr__class="w-full"nth-child="6"nth-of-type="6";ul:nth-child="1"nth-of-type="1";div.Navbar3000__top.ScrollableShadows__inner:attr__class="ScrollableShadows__inner Navbar3000__top"nth-child="1"nth-of-type="1";div.ScrollableShadows.ScrollableShadows--vertical:attr__class="ScrollableShadows ScrollableShadows--vertical"nth-child="1"nth-of-type="1";div.Navbar3000__content:attr__class="Navbar3000__content"nth-child="1"nth-of-type="1";nav.Navbar3000:attr__class="Navbar3000"nth-child="1"nth-of-type="1";div.Navigation3000:attr__class="Navigation3000"nth-child="1"nth-of-type="1";div:attr__id="root"attr_id="root"nth-child="3"nth-of-type="1";body.overflow-hidden:attr__class="overflow-hidden"attr__theme="light"nth-child="2"nth-of-type="1"` + + const hogGlobals1 = createHogExecutionGlobals({ + groups: {}, + event: { + uuid: 'uuid', + name: '$autocapture', + distinct_id: 'distinct_id', + url: 'http://localhost:8000/events/1', + properties: { + $lib_version: '1.2.3', + $elements_chain: elementsChain('/project/1/not-a-link'), + }, + timestamp: new Date().toISOString(), + }, + }) + + const resultsShouldntMatch = executor.findMatchingFunctions(hogGlobals1) + expect(resultsShouldntMatch.matchingFunctions).toHaveLength(0) + expect(resultsShouldntMatch.nonMatchingFunctions).toHaveLength(1) + + const hogGlobals2 = createHogExecutionGlobals({ + groups: {}, + event: { + uuid: 'uuid', + name: '$autocapture', + distinct_id: 'distinct_id', + url: 'http://localhost:8000/events/1', + properties: { + $lib_version: '1.2.3', + $elements_chain: elementsChain('/project/1/activity/explore'), + }, + timestamp: new Date().toISOString(), + }, + }) + + const resultsShouldMatch = executor.findMatchingFunctions(hogGlobals2) + expect(resultsShouldMatch.matchingFunctions).toHaveLength(1) + expect(resultsShouldMatch.nonMatchingFunctions).toHaveLength(0) + }) + + it('can use elements_chain_tags and _ids', () => { + const fn = createHogFunction({ + ...HOG_EXAMPLES.simple_fetch, + ...HOG_INPUTS_EXAMPLES.simple_fetch, + ...HOG_FILTERS_EXAMPLES.elements_tag_and_id_filter, + }) + + mockFunctionManager.getTeamHogFunctions.mockReturnValue([fn]) + const elementsChain = (id: string) => + `a.Link.font-semibold.text-text-3000.text-xl:attr__class="Link font-semibold text-xl text-text-3000"attr__href="/project/1/dashboard/1"attr__id="${id}"attr_id="${id}"href="/project/1/dashboard/1"nth-child="1"nth-of-type="1"text="My App Dashboard";div.ProjectHomepage__dashboardheader__title:attr__class="ProjectHomepage__dashboardheader__title"nth-child="1"nth-of-type="1";div.ProjectHomepage__dashboardheader:attr__class="ProjectHomepage__dashboardheader"nth-child="2"nth-of-type="2";div.ProjectHomepage:attr__class="ProjectHomepage"nth-child="1"nth-of-type="1";div.Navigation3000__scene:attr__class="Navigation3000__scene"nth-child="2"nth-of-type="2";main:nth-child="2"nth-of-type="1";div.Navigation3000:attr__class="Navigation3000"nth-child="1"nth-of-type="1";div:attr__id="root"attr_id="root"nth-child="3"nth-of-type="1";body.overflow-hidden:attr__class="overflow-hidden"attr__theme="light"nth-child="2"nth-of-type="1"` + + const hogGlobals1 = createHogExecutionGlobals({ + groups: {}, + event: { + uuid: 'uuid', + name: '$autocapture', + distinct_id: 'distinct_id', + url: 'http://localhost:8000/events/1', + properties: { + $lib_version: '1.2.3', + $elements_chain: elementsChain('notfound'), + }, + timestamp: new Date().toISOString(), + }, + }) + + const resultsShouldntMatch = executor.findMatchingFunctions(hogGlobals1) + expect(resultsShouldntMatch.matchingFunctions).toHaveLength(0) + expect(resultsShouldntMatch.nonMatchingFunctions).toHaveLength(1) + + const hogGlobals2 = createHogExecutionGlobals({ + groups: {}, + event: { + uuid: 'uuid', + name: '$autocapture', + distinct_id: 'distinct_id', + url: 'http://localhost:8000/events/1', + properties: { + $lib_version: '1.2.3', + $elements_chain: elementsChain('homelink'), + }, + timestamp: new Date().toISOString(), + }, + }) + + const resultsShouldMatch = executor.findMatchingFunctions(hogGlobals2) + expect(resultsShouldMatch.matchingFunctions).toHaveLength(1) + expect(resultsShouldMatch.nonMatchingFunctions).toHaveLength(0) + }) }) describe('async functions', () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 813be57c694d7..653bfb354e482 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,8 +53,8 @@ dependencies: specifier: 4.6.0 version: 4.6.0(monaco-editor@0.49.0)(react-dom@18.2.0)(react@18.2.0) '@posthog/hogvm': - specifier: ^1.0.44 - version: 1.0.44(luxon@3.5.0) + specifier: ^1.0.46 + version: 1.0.46(luxon@3.5.0) '@posthog/icons': specifier: 0.8.1 version: 0.8.1(react-dom@18.2.0)(react@18.2.0) @@ -5414,8 +5414,8 @@ packages: resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} dev: false - /@posthog/hogvm@1.0.44(luxon@3.5.0): - resolution: {integrity: sha512-Ss7gTPyvPyviNipVQOqnsCa66IMmMf+DEg7iX/vQMcWDuFwvHNbdze1iwFVoXCjLci+h8SW2rOMPB0S5A2jJXg==} + /@posthog/hogvm@1.0.46(luxon@3.5.0): + resolution: {integrity: sha512-oTXytxHImxcAUYvK+QVI5nRc3YnVSbn01rFlOrpeTYjW5oqYKMR8nYsjhHGLt5p0pnfeBhmQjBM5mJtVs5bA2Q==} peerDependencies: luxon: ^3.4.4 dependencies: @@ -18298,7 +18298,7 @@ packages: react: '>=15' dependencies: react: 18.2.0 - unlayer-types: 1.65.0 + unlayer-types: 1.75.0 dev: false /react-error-boundary@3.1.4(react@18.2.0): @@ -20832,8 +20832,8 @@ packages: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} - /unlayer-types@1.65.0: - resolution: {integrity: sha512-fIeh/TtUhQ16A0oW3mHkcDekvhIbZbN+h0qVgBuVxjGnYME/Ma3saFRO4eKJll0YNyalvb9MdmSz0nyTgr/1/w==} + /unlayer-types@1.75.0: + resolution: {integrity: sha512-yB4TeimlZPKkAGIIE3Acs9e5YHjCpeGcoybq/E8w4lzNTI5EybI9Z9rwIBXhNK0miNarxEIO7rJUWB+Yeve80g==} dev: false /unpipe@1.0.0: diff --git a/posthog/hogql/property.py b/posthog/hogql/property.py index bce1453e561f8..65db42700c958 100644 --- a/posthog/hogql/property.py +++ b/posthog/hogql/property.py @@ -550,23 +550,26 @@ def action_to_expr(action: Action) -> ast.Expr: if step.text is not None: value = step.text if step.text_matching == "regex": - match = ast.CompareOperationOp.Regex + exprs.append( + parse_expr( + "arrayExists(x -> x =~ {value}, elements_chain_texts)", + {"value": ast.Constant(value=value)}, + ) + ) elif step.text_matching == "contains": - match = ast.CompareOperationOp.ILike - value = f"%{value}%" + exprs.append( + parse_expr( + "arrayExists(x -> x ilike {value}, elements_chain_texts)", + {"value": ast.Constant(value=f"%{value}%")}, + ) + ) else: - match = ast.CompareOperationOp.Eq - - exprs.append( - parse_expr( - "arrayExists(x -> {match}, elements_chain_texts)", - { - "match": ast.CompareOperation( - op=match, left=ast.Field(chain=["x"]), right=ast.Constant(value=value) - ) - }, + exprs.append( + parse_expr( + "arrayExists(x -> x = {value}, elements_chain_texts)", + {"value": ast.Constant(value=value)}, + ) ) - ) if step.url: if step.url_matching == "exact": expr = parse_expr( diff --git a/posthog/hogql/test/test_property.py b/posthog/hogql/test/test_property.py index 02aa63b9cb856..fb2f2f230973d 100644 --- a/posthog/hogql/test/test_property.py +++ b/posthog/hogql/test/test_property.py @@ -649,6 +649,24 @@ def test_action_to_expr(self): self._parse_expr("event = '$autocapture' and arrayExists(x -> x =~ 'blabla', elements_chain_texts)"), ) + action7 = Action.objects.create( + team=self.team, + steps_json=[{"event": "$autocapture", "text": "blabla", "text_matching": "contains"}], + ) + self.assertEqual( + clear_locations(action_to_expr(action7)), + self._parse_expr("event = '$autocapture' and arrayExists(x -> x ilike '%blabla%', elements_chain_texts)"), + ) + + action8 = Action.objects.create( + team=self.team, + steps_json=[{"event": "$autocapture", "text": "blabla", "text_matching": "exact"}], + ) + self.assertEqual( + clear_locations(action_to_expr(action8)), + self._parse_expr("event = '$autocapture' and arrayExists(x -> x = 'blabla', elements_chain_texts)"), + ) + def test_cohort_filter_static(self): cohort = Cohort.objects.create( team=self.team, From bb02c7986582b6fd18f7d696eb6391b222636da9 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 5 Sep 2024 12:48:24 +0200 Subject: [PATCH 21/32] fix: Swap to concat for blobby events (#24805) --- .../ingestion-queues/session-recording/utils.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/plugin-server/src/main/ingestion-queues/session-recording/utils.ts b/plugin-server/src/main/ingestion-queues/session-recording/utils.ts index 470905f58ac2d..16b336d8f952c 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/utils.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/utils.ts @@ -333,20 +333,12 @@ export const parseKafkaBatch = async ( continue } - // Shallow clone the eventsByWindowId object to make sure we don't mutate the original - const newEventsByWindowId: IncomingRecordingMessage['eventsByWindowId'] = Object.entries( - existingMessage.eventsByWindowId - ).reduce((acc, [windowId, events]) => { - acc[windowId] = [...events] - return acc - }, {} as IncomingRecordingMessage['eventsByWindowId']) - for (const [windowId, events] of Object.entries(parsedMessage.eventsByWindowId)) { - newEventsByWindowId[windowId] = newEventsByWindowId[windowId] || [] - newEventsByWindowId[windowId].push(...events) + existingMessage.eventsByWindowId[windowId] = (existingMessage.eventsByWindowId[windowId] || []).concat( + events + ) } - existingMessage.eventsByWindowId = newEventsByWindowId existingMessage.metadata.rawSize += parsedMessage.metadata.rawSize // Update the events ranges From 7ffc3cc3cce6f23e953c9bb3960d5a1c07681512 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Thu, 5 Sep 2024 12:46:43 +0100 Subject: [PATCH 22/32] fix: event property loading (#24807) --- .../player/sessionRecordingDataLogic.ts | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts index d3f2fd1aff2e6..d5035a871c430 100644 --- a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts +++ b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts @@ -487,38 +487,33 @@ export const sessionRecordingDataLogic = kea([ return values.sessionEventsData } - const { person } = values.sessionPlayerData + if (!event.id) { + captureMessage('event id not available for matching', { + tags: { feature: 'session-recording-load-full-event-data' }, + extra: { event }, + }) + return values.sessionEventsData + } let loadedProperties: Record = existingEvent.properties try { const query: HogQLQuery = { kind: NodeKind.HogQLQuery, - query: hogql`SELECT properties, timestamp, uuid + query: hogql`SELECT properties, uuid FROM events WHERE timestamp > ${dayjs(event.timestamp).subtract(1000, 'ms')} AND timestamp < ${dayjs(event.timestamp).add(1000, 'ms')} - ${person?.id ? `AND person.id = ${person.id}` : ''} AND event = ${event.event} - ORDER BY timestamp ASC`, + AND uuid = ${event.id}`, } const response = await api.query(query) if (response.error) { throw new Error(response.error) } - // historically we compared timestamps here when finding properties for a particular event - // it's nicer to use the event id - // but since we were using timestamps, we might not be guaranteed to have the id? - // TODO - check if we can remove the timestamp comparison const result = response.results.find((x: any) => { - if (event.id) { - return x[2] === event.id - } - captureMessage('event id not available for matching', { - tags: { feature: 'session-recording-load-full-event-data' }, - }) - return x[1] === event.timestamp + return x[1] === event.id }) if (result) { From f32e23f6871fbbee53ce36015b3c495e0a6f4814 Mon Sep 17 00:00:00 2001 From: Marcus Hof <13001502+MarconLP@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:00:13 +0200 Subject: [PATCH 23/32] feat(cdp): rudderstack hog function (#24556) --- frontend/public/services/rudderstack.png | Bin 0 -> 4809 bytes posthog/cdp/templates/__init__.py | 2 + .../rudderstack/template_rudderstack.py | 126 ++++++++++++++++++ .../rudderstack/test_template_rudderstack.py | 107 +++++++++++++++ 4 files changed, 235 insertions(+) create mode 100644 frontend/public/services/rudderstack.png create mode 100644 posthog/cdp/templates/rudderstack/template_rudderstack.py create mode 100644 posthog/cdp/templates/rudderstack/test_template_rudderstack.py diff --git a/frontend/public/services/rudderstack.png b/frontend/public/services/rudderstack.png new file mode 100644 index 0000000000000000000000000000000000000000..11ebb99b677b5862873f2d4c42b06a412c171ccd GIT binary patch literal 4809 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 Date: Thu, 5 Sep 2024 15:13:10 +0200 Subject: [PATCH 24/32] feat(cdp): add loops hog function (#24713) --- frontend/public/services/loops.png | Bin 0 -> 13692 bytes posthog/cdp/templates/__init__.py | 2 + posthog/cdp/templates/loops/template_loops.py | 49 ++++++++++++++ .../templates/loops/test_template_loops.py | 61 ++++++++++++++++++ .../test/__snapshots__/test_in_cohort.ambr | 8 +-- 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 frontend/public/services/loops.png create mode 100644 posthog/cdp/templates/loops/template_loops.py create mode 100644 posthog/cdp/templates/loops/test_template_loops.py diff --git a/frontend/public/services/loops.png b/frontend/public/services/loops.png new file mode 100644 index 0000000000000000000000000000000000000000..822763a10e1081d0ec3ec20087779281b32e5333 GIT binary patch literal 13692 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 literal 0 HcmV?d00001 diff --git a/posthog/cdp/templates/__init__.py b/posthog/cdp/templates/__init__.py index 32725b5a57367..f1f0243c08cd5 100644 --- a/posthog/cdp/templates/__init__.py +++ b/posthog/cdp/templates/__init__.py @@ -14,6 +14,7 @@ ) from .zapier.template_zapier import template as zapier from .mailgun.template_mailgun import template_mailgun_send_email as mailgun +from .loops.template_loops import template as loops from .rudderstack.template_rudderstack import template as rudderstack @@ -33,6 +34,7 @@ mailjet_update_contact_list, clearbit, mailgun, + loops, rudderstack, ] diff --git a/posthog/cdp/templates/loops/template_loops.py b/posthog/cdp/templates/loops/template_loops.py new file mode 100644 index 0000000000000..01230f7727328 --- /dev/null +++ b/posthog/cdp/templates/loops/template_loops.py @@ -0,0 +1,49 @@ +from posthog.cdp.templates.hog_function_template import HogFunctionTemplate + + +template: HogFunctionTemplate = HogFunctionTemplate( + status="beta", + id="template-loops", + name="Send events to Loops", + description="Passes PostHog events to Loops.so", + icon_url="/static/services/loops.png", + hog=""" +let apiKey := inputs.apiKey + +let payload := { + 'userId': event.distinct_id, + 'eventName': event.name == '$set' ? '$identify' : event.name, + 'email': person.properties.email +} +for (let key, value in person.properties) { + payload[key] := value +} +fetch('https://app.loops.so/api/v1/events/send', { + 'method': 'POST', + 'headers': { + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {apiKey}', + }, + 'body': payload +}) +""".strip(), + inputs_schema=[ + { + "key": "apiKey", + "type": "string", + "label": "Loops API Key", + "description": "Loops API Key", + "default": "", + "secret": True, + "required": True, + } + ], + filters={ + "events": [ + {"id": "$identify", "name": "$identify", "type": "events", "order": 0}, + {"id": "$set", "name": "$set", "type": "events", "order": 1}, + ], + "actions": [], + "filter_test_accounts": True, + }, +) diff --git a/posthog/cdp/templates/loops/test_template_loops.py b/posthog/cdp/templates/loops/test_template_loops.py new file mode 100644 index 0000000000000..c6d48b5228b14 --- /dev/null +++ b/posthog/cdp/templates/loops/test_template_loops.py @@ -0,0 +1,61 @@ +from inline_snapshot import snapshot +from posthog.cdp.templates.helpers import BaseHogFunctionTemplateTest +from posthog.cdp.templates.loops.template_loops import template as template_loops + + +class TestTemplateLoops(BaseHogFunctionTemplateTest): + template = template_loops + + def _inputs(self, **kwargs): + inputs = {"apiKey": "1cac089e00a708680bdb1ed9f082d5bf"} + inputs.update(kwargs) + return inputs + + def test_function_works(self): + self.run_function( + inputs=self._inputs(), + globals={ + "event": {"distinct_id": "66e614bd-d9f2-491e-9e2c-eeab3090f72f", "name": "$pageview"}, + "person": { + "properties": {"email": "max@posthog.com", "name": "Max", "company": "PostHog"}, + }, + }, + ) + + assert self.get_mock_fetch_calls()[0] == snapshot( + ( + "https://app.loops.so/api/v1/events/send", + { + "method": "POST", + "headers": { + "Content-Type": "application/json", + "Authorization": "Bearer 1cac089e00a708680bdb1ed9f082d5bf", + }, + "body": { + "userId": "66e614bd-d9f2-491e-9e2c-eeab3090f72f", + "eventName": "$pageview", + "email": "max@posthog.com", + "name": "Max", + "company": "PostHog", + }, + }, + ) + ) + + def test_automatic_action_mapping(self): + for event_name, expected_action in [ + ("$identify", "$identify"), + ("$set", "$identify"), + ("$pageview", "$pageview"), + ("$create_alias", "$create_alias"), + ("$autocapture", "$autocapture"), + ("custom", "custom"), + ]: + self.run_function( + inputs=self._inputs(), + globals={ + "event": {"name": event_name, "properties": {"url": "https://example.com", "$browser": "Chrome"}}, + }, + ) + + assert self.get_mock_fetch_calls()[0][1]["body"]["eventName"] == expected_action diff --git a/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr b/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr index 66203f817267f..369f18ab9d118 100644 --- a/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr +++ b/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr @@ -31,7 +31,7 @@ FROM events LEFT JOIN ( SELECT person_static_cohort.person_id AS cohort_person_id, 1 AS matched, person_static_cohort.cohort_id AS cohort_id FROM person_static_cohort - WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [13]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) + WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [2]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) WHERE and(equals(events.team_id, 420), 1, ifNull(equals(__in_cohort.matched, 1), 0)) LIMIT 100 SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1, format_csv_allow_double_quotes=0, max_ast_elements=4000000, max_expanded_ast_elements=4000000, max_bytes_before_external_group_by=0 @@ -42,7 +42,7 @@ FROM events LEFT JOIN ( SELECT person_id AS cohort_person_id, 1 AS matched, cohort_id FROM static_cohort_people - WHERE in(cohort_id, [13])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) + WHERE in(cohort_id, [2])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) WHERE and(1, equals(__in_cohort.matched, 1)) LIMIT 100 ''' @@ -55,7 +55,7 @@ FROM events LEFT JOIN ( SELECT person_static_cohort.person_id AS cohort_person_id, 1 AS matched, person_static_cohort.cohort_id AS cohort_id FROM person_static_cohort - WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [14]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) + WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [3]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) WHERE and(equals(events.team_id, 420), 1, ifNull(equals(__in_cohort.matched, 1), 0)) LIMIT 100 SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1, format_csv_allow_double_quotes=0, max_ast_elements=4000000, max_expanded_ast_elements=4000000, max_bytes_before_external_group_by=0 @@ -66,7 +66,7 @@ FROM events LEFT JOIN ( SELECT person_id AS cohort_person_id, 1 AS matched, cohort_id FROM static_cohort_people - WHERE in(cohort_id, [14])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) + WHERE in(cohort_id, [3])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) WHERE and(1, equals(__in_cohort.matched, 1)) LIMIT 100 ''' From 2d410143e2c9cb05519bc73a86686cb785dbd769 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 5 Sep 2024 15:29:27 +0200 Subject: [PATCH 25/32] feat: Added new heartbeat (#24810) --- posthog/tasks/tasks.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/posthog/tasks/tasks.py b/posthog/tasks/tasks.py index f2bf138177a35..68cad94b93d81 100644 --- a/posthog/tasks/tasks.py +++ b/posthog/tasks/tasks.py @@ -8,6 +8,7 @@ from django.utils import timezone from prometheus_client import Gauge from redis import Redis +import requests from structlog import get_logger from posthog.clickhouse.client.limit import limit_concurrency, CeleryConcurrencyLimitExceeded @@ -180,11 +181,7 @@ def pg_row_count() -> None: "log_entries", ] -HEARTBEAT_EVENT_TO_INGESTION_LAG_METRIC = { - "heartbeat": "ingestion", - "heartbeat_buffer": "ingestion_buffer", - "heartbeat_api": "ingestion_api", -} +HEARTBEAT_EVENT_TO_INGESTION_LAG_METRIC = {"heartbeat": "ingestion", "$heartbeat": "ingestion_api"} @shared_task(ignore_result=True) @@ -192,9 +189,8 @@ def ingestion_lag() -> None: from statshog.defaults.django import statsd from posthog.client import sync_execute + from posthog.models.team.team import Team - # Requires https://github.com/PostHog/posthog-heartbeat-plugin to be enabled on team 2 - # Note that it runs every minute, and we compare it with now(), so there's up to 60s delay query = """ SELECT event, date_diff('second', max(timestamp), now()) FROM events @@ -204,11 +200,13 @@ def ingestion_lag() -> None: GROUP BY event """ + team_ids = settings.INGESTION_LAG_METRIC_TEAM_IDS + try: results = sync_execute( query, { - "team_ids": settings.INGESTION_LAG_METRIC_TEAM_IDS, + "team_ids": team_ids, "events": list(HEARTBEAT_EVENT_TO_INGESTION_LAG_METRIC.keys()), }, ) @@ -226,6 +224,17 @@ def ingestion_lag() -> None: except: pass + for team in Team.objects.filter(pk__in=team_ids): + requests.post( + settings.SITE_URL + "/e", + json={ + "event": "$heartbeat", + "distinct_id": "posthog-celery-heartbeat", + "token": team.api_token, + "properties": {"$timestamp": timezone.now().isoformat()}, + }, + ) + @shared_task(ignore_result=True, queue=CeleryQueue.SESSION_REPLAY_GENERAL.value) def replay_count_metrics() -> None: From 3dcbdc99a4eeb32e99e267a32c91299ef491be31 Mon Sep 17 00:00:00 2001 From: Ben White Date: Thu, 5 Sep 2024 16:45:27 +0200 Subject: [PATCH 26/32] chore: Removed some logging (#24788) --- plugin-server/src/cdp/cdp-consumers.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/plugin-server/src/cdp/cdp-consumers.ts b/plugin-server/src/cdp/cdp-consumers.ts index 499b030e61564..8c4eec5e11951 100644 --- a/plugin-server/src/cdp/cdp-consumers.ts +++ b/plugin-server/src/cdp/cdp-consumers.ts @@ -237,8 +237,6 @@ abstract class CdpConsumerBase { await runInstrumentedFunction({ statsKey: `cdpConsumer.handleEachBatch.produceResults`, func: async () => { - console.log('Processing invocations results', results.length) - await Promise.all( results.map(async (result) => { // Tricky: We want to pull all the logs out as we don't want them to be passed around to any subsequent functions @@ -635,12 +633,6 @@ export class CdpFunctionCallbackConsumer extends CdpConsumerBase { }) ) - invocations.forEach((item) => { - if (!item.hogFunction?.id) { - console.error('No hog function id', item) - } - }) - return invocations }, }) From c26b3dc48710bf8db6648b3e2906c5e60f8b5601 Mon Sep 17 00:00:00 2001 From: Tom Owers Date: Thu, 5 Sep 2024 16:37:58 +0100 Subject: [PATCH 27/32] feat(data-warehouse): Added vitally Source (#24806) --- frontend/public/services/vitally.png | Bin 0 -> 103217 bytes .../data-warehouse/new/sourceWizardLogic.tsx | 39 ++ .../DataWarehouseManagedSourcesTable.tsx | 4 +- frontend/src/types.ts | 1 + latest_migrations.manifest | 2 +- mypy-baseline.txt | 9 + ...66_alter_externaldatasource_source_type.py | 30 ++ .../data_imports/pipelines/schemas.py | 8 + .../pipelines/vitally/__init__.py | 360 ++++++++++++++++++ .../pipelines/vitally/settings.py | 108 ++++++ .../workflow_activities/import_data.py | 21 + posthog/warehouse/api/external_data_source.py | 34 ++ .../warehouse/models/external_data_schema.py | 4 +- .../warehouse/models/external_data_source.py | 1 + 14 files changed, 618 insertions(+), 3 deletions(-) create mode 100644 frontend/public/services/vitally.png create mode 100644 posthog/migrations/0466_alter_externaldatasource_source_type.py create mode 100644 posthog/temporal/data_imports/pipelines/vitally/__init__.py create mode 100644 posthog/temporal/data_imports/pipelines/vitally/settings.py diff --git a/frontend/public/services/vitally.png b/frontend/public/services/vitally.png new file mode 100644 index 0000000000000000000000000000000000000000..867ed5e10e9080df1cfe5ab4d4464b59f00561d3 GIT binary patch literal 103217 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 loVATl9cv = { ], caption: 'Select an existing Salesforce account to link to PostHog or create a new connection', }, + Vitally: { + name: 'Vitally', + fields: [ + { + name: 'secret_token', + label: 'Secret token', + type: 'text', + required: true, + placeholder: 'sk_live_...', + }, + { + type: 'select', + name: 'region', + label: 'Vitally region', + required: true, + defaultValue: 'EU', + options: [ + { + label: 'EU', + value: 'EU', + }, + { + label: 'US', + value: 'US', + fields: [ + { + name: 'subdomain', + label: 'Vitally subdomain', + type: 'text', + required: true, + placeholder: '', + }, + ], + }, + ], + }, + ], + caption: '', + }, } export const buildKeaFormDefaultFromSourceDetails = ( diff --git a/frontend/src/scenes/data-warehouse/settings/DataWarehouseManagedSourcesTable.tsx b/frontend/src/scenes/data-warehouse/settings/DataWarehouseManagedSourcesTable.tsx index d18657892fd22..4d1fc0f20b4cd 100644 --- a/frontend/src/scenes/data-warehouse/settings/DataWarehouseManagedSourcesTable.tsx +++ b/frontend/src/scenes/data-warehouse/settings/DataWarehouseManagedSourcesTable.tsx @@ -14,6 +14,7 @@ import IconSalesforce from 'public/services/salesforce.png' import IconSnowflake from 'public/services/snowflake.png' import IconMSSQL from 'public/services/sql-azure.png' import IconStripe from 'public/services/stripe.png' +import IconVitally from 'public/services/vitally.png' import IconZendesk from 'public/services/zendesk.png' import { urls } from 'scenes/urls' @@ -189,6 +190,7 @@ export function RenderDataWarehouseSourceIcon({ azure: Iconazure, Salesforce: IconSalesforce, MSSQL: IconMSSQL, + Vitally: IconVitally, }[type] return ( @@ -203,7 +205,7 @@ export function RenderDataWarehouseSourceIcon({ } > - {type} + {type}

diff --git a/frontend/src/types.ts b/frontend/src/types.ts index a4e8187d755de..61d6072f17d21 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -3861,6 +3861,7 @@ export const externalDataSources = [ 'Zendesk', 'Snowflake', 'Salesforce', + 'Vitally', ] as const export type ExternalDataSourceType = (typeof externalDataSources)[number] diff --git a/latest_migrations.manifest b/latest_migrations.manifest index 85b48ed0ed16f..54f01686c7aee 100644 --- a/latest_migrations.manifest +++ b/latest_migrations.manifest @@ -5,7 +5,7 @@ contenttypes: 0002_remove_content_type_name ee: 0016_rolemembership_organization_member otp_static: 0002_throttling otp_totp: 0002_auto_20190420_0723 -posthog: 0465_datawarehouse_stripe_account +posthog: 0466_alter_externaldatasource_source_type sessions: 0001_initial social_django: 0010_uid_db_index two_factor: 0007_auto_20201201_1019 diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 9e25498b357dd..42c3ab53b0a9c 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -42,6 +42,15 @@ posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argume posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible default for argument "resolved_param" (default has type "ResolvedParam | None", argument has type "ResolvedParam") [assignment] posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument "module" to "SourceInfo" has incompatible type Module | None; expected Module [arg-type] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/utils.py:0: error: No overload variant of "asdict" matches argument type "type[DataclassInstance]" [call-overload] posthog/utils.py:0: note: Possible overload variants: posthog/utils.py:0: note: def asdict(obj: DataclassInstance) -> dict[str, Any] diff --git a/posthog/migrations/0466_alter_externaldatasource_source_type.py b/posthog/migrations/0466_alter_externaldatasource_source_type.py new file mode 100644 index 0000000000000..4a4b2f522f68b --- /dev/null +++ b/posthog/migrations/0466_alter_externaldatasource_source_type.py @@ -0,0 +1,30 @@ +# Generated by Django 4.2.15 on 2024-09-05 10:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("posthog", "0465_datawarehouse_stripe_account"), + ] + + operations = [ + migrations.AlterField( + model_name="externaldatasource", + name="source_type", + field=models.CharField( + choices=[ + ("Stripe", "Stripe"), + ("Hubspot", "Hubspot"), + ("Postgres", "Postgres"), + ("Zendesk", "Zendesk"), + ("Snowflake", "Snowflake"), + ("Salesforce", "Salesforce"), + ("MySQL", "MySQL"), + ("MSSQL", "MSSQL"), + ("Vitally", "Vitally"), + ], + max_length=128, + ), + ), + ] diff --git a/posthog/temporal/data_imports/pipelines/schemas.py b/posthog/temporal/data_imports/pipelines/schemas.py index 0acd00e8bd6f3..15214f939b78a 100644 --- a/posthog/temporal/data_imports/pipelines/schemas.py +++ b/posthog/temporal/data_imports/pipelines/schemas.py @@ -17,6 +17,11 @@ INCREMENTAL_ENDPOINTS as SALESFORCE_INCREMENTAL_ENDPOINTS, INCREMENTAL_FIELDS as SALESFORCE_INCREMENTAL_FIELDS, ) +from posthog.temporal.data_imports.pipelines.vitally.settings import ( + ENDPOINTS as VITALLY_ENDPOINTS, + INCREMENTAL_ENDPOINTS as VITALLY_INCREMENTAL_ENDPOINTS, + INCREMENTAL_FIELDS as VITALLY_INCREMENTAL_FIELDS, +) PIPELINE_TYPE_SCHEMA_DEFAULT_MAPPING = { ExternalDataSource.Type.STRIPE: STRIPE_ENDPOINTS, @@ -29,6 +34,7 @@ ExternalDataSource.Type.SALESFORCE: SALESFORCE_ENDPOINTS, ExternalDataSource.Type.MYSQL: (), ExternalDataSource.Type.MSSQL: (), + ExternalDataSource.Type.VITALLY: VITALLY_ENDPOINTS, } PIPELINE_TYPE_INCREMENTAL_ENDPOINTS_MAPPING = { @@ -40,6 +46,7 @@ ExternalDataSource.Type.SALESFORCE: SALESFORCE_INCREMENTAL_ENDPOINTS, ExternalDataSource.Type.MYSQL: (), ExternalDataSource.Type.MSSQL: (), + ExternalDataSource.Type.VITALLY: VITALLY_INCREMENTAL_ENDPOINTS, } PIPELINE_TYPE_INCREMENTAL_FIELDS_MAPPING: dict[ExternalDataSource.Type, dict[str, list[IncrementalField]]] = { @@ -51,4 +58,5 @@ ExternalDataSource.Type.SALESFORCE: SALESFORCE_INCREMENTAL_FIELDS, ExternalDataSource.Type.MYSQL: {}, ExternalDataSource.Type.MSSQL: {}, + ExternalDataSource.Type.VITALLY: VITALLY_INCREMENTAL_FIELDS, } diff --git a/posthog/temporal/data_imports/pipelines/vitally/__init__.py b/posthog/temporal/data_imports/pipelines/vitally/__init__.py new file mode 100644 index 0000000000000..8c526017db38d --- /dev/null +++ b/posthog/temporal/data_imports/pipelines/vitally/__init__.py @@ -0,0 +1,360 @@ +import base64 +from dateutil import parser +from typing import Any, Optional +import dlt +from dlt.sources.helpers.rest_client.paginators import BasePaginator +from dlt.sources.helpers.requests import Response, Request +import requests +from posthog.temporal.data_imports.pipelines.rest_source import RESTAPIConfig, rest_api_resources +from posthog.temporal.data_imports.pipelines.rest_source.typing import EndpointResource + + +def get_resource(name: str, is_incremental: bool) -> EndpointResource: + resources: dict[str, EndpointResource] = { + "Organizations": { + "name": "Organizations", + "table_name": "organizations", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/organizations", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + "Accounts": { + "name": "Accounts", + "table_name": "accounts", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/accounts", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + "Users": { + "name": "Users", + "table_name": "users", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/users", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + "Conversations": { + "name": "Conversations", + "table_name": "conversations", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/conversations", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + "Notes": { + "name": "Notes", + "table_name": "notes", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/notes", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + "Projects": { + "name": "Projects", + "table_name": "projects", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/projects", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + "Tasks": { + "name": "Tasks", + "table_name": "tasks", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/tasks", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + "NPS_Responses": { + "name": "NPS_Responses", + "table_name": "nps_responses", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/npsResponses", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + "Custom_Objects": { + "name": "Custom_Objects", + "table_name": "custom_objects", + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + "endpoint": { + "data_selector": "results", + "path": "/resources/customObjects", + "params": { + "limit": 100, + "sortBy": "updatedAt", + "updatedAt": { + "type": "incremental", + "cursor_path": "updatedAt", + "initial_value": "1970-01-01", # type: ignore + "convert": lambda x: parser.parse(x).timestamp(), + } + if is_incremental + else None, + }, + }, + "table_format": "delta", + }, + } + + return resources[name] + + +class VitallyPaginator(BasePaginator): + def __init__(self) -> None: + super().__init__() + + def update_state(self, response: Response, data: Optional[list[Any]] = None) -> None: + res = response.json() + + current_source = dlt.current.get_source() + resources = current_source.resources + current_resource = next(iter(resources.values())) + incremental = current_resource.incremental.incremental + + self._cursor = None + + if not res: + self._has_next_page = False + return + + if incremental: + updated_at_str = res["results"][0]["updatedAt"] + updated_at = parser.parse(updated_at_str).timestamp() + start_value = parser.parse(incremental.start_value).timestamp() + + if start_value >= updated_at: + self._has_next_page = False + return + + if res["next"]: + self._has_next_page = True + self._cursor = res["next"] + else: + self._has_next_page = False + + def update_request(self, request: Request) -> None: + if request.params is None: + request.params = {} + + request.params["from"] = self._cursor + + +def get_base_url(region: str, subdomain: Optional[str]) -> str: + if region == "US" and subdomain: + return f"https://{subdomain}.rest.vitally.io/" + + return "https://rest.vitally-eu.io/" + + +@dlt.source(max_table_nesting=0) +def vitally_source( + secret_token: str, + region: str, + subdomain: Optional[str], + endpoint: str, + team_id: int, + job_id: str, + is_incremental: bool = False, +): + config: RESTAPIConfig = { + "client": { + "base_url": get_base_url(region, subdomain), + "auth": { + "type": "http_basic", + "username": secret_token, + "password": "", + }, + "paginator": VitallyPaginator(), + }, + "resource_defaults": { + "primary_key": "id", + "write_disposition": { + "disposition": "merge", + "strategy": "upsert", + } + if is_incremental + else "replace", + }, + "resources": [get_resource(endpoint, is_incremental)], + } + + yield from rest_api_resources(config, team_id, job_id) + + +def validate_credentials(secret_token: str, region: str, subdomain: Optional[str]) -> bool: + basic_token = base64.b64encode(f"{secret_token}:".encode("ascii")).decode("ascii") + res = requests.get( + f"{get_base_url(region, subdomain)}resources/users?limit=1", + headers={"Authorization": f"Basic {basic_token}"}, + ) + + return res.status_code == 200 diff --git a/posthog/temporal/data_imports/pipelines/vitally/settings.py b/posthog/temporal/data_imports/pipelines/vitally/settings.py new file mode 100644 index 0000000000000..a16d9565f5d1c --- /dev/null +++ b/posthog/temporal/data_imports/pipelines/vitally/settings.py @@ -0,0 +1,108 @@ +from posthog.warehouse.types import IncrementalField, IncrementalFieldType + +ENDPOINTS = ( + "Organizations", + "Accounts", + "Users", + "Conversations", + "Notes", + "Projects", + "Tasks", + "NPS_Responses", + "Custom_Objects", +) + +INCREMENTAL_ENDPOINTS = ( + "Organizations", + "Accounts", + "Users", + "Conversations", + "Notes", + "Projects", + "Tasks", + "NPS_Responses", + "Custom_Objects", +) + +INCREMENTAL_FIELDS: dict[str, list[IncrementalField]] = { + "Organizations": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "Accounts": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "Users": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "Conversations": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "Notes": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "Projects": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "Tasks": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "NPS_Responses": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "Custom_Fields": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], + "Custom_Objects": [ + { + "label": "updated_at", + "type": IncrementalFieldType.DateTime, + "field": "updated_at", + "field_type": IncrementalFieldType.DateTime, + } + ], +} diff --git a/posthog/temporal/data_imports/workflow_activities/import_data.py b/posthog/temporal/data_imports/workflow_activities/import_data.py index 6ce4237f53711..73706e1191589 100644 --- a/posthog/temporal/data_imports/workflow_activities/import_data.py +++ b/posthog/temporal/data_imports/workflow_activities/import_data.py @@ -283,6 +283,27 @@ async def import_data_activity(inputs: ImportDataActivityInputs): is_incremental=schema.is_incremental, ) + return await _run( + job_inputs=job_inputs, + source=source, + logger=logger, + inputs=inputs, + schema=schema, + reset_pipeline=reset_pipeline, + ) + elif model.pipeline.source_type == ExternalDataSource.Type.VITALLY: + from posthog.temporal.data_imports.pipelines.vitally import vitally_source + + source = vitally_source( + secret_token=model.pipeline.job_inputs.get("secret_token"), + region=model.pipeline.job_inputs.get("region"), + subdomain=model.pipeline.job_inputs.get("subdomain"), + endpoint=schema.name, + team_id=inputs.team_id, + job_id=inputs.run_id, + is_incremental=schema.is_incremental, + ) + return await _run( job_inputs=job_inputs, source=source, diff --git a/posthog/warehouse/api/external_data_source.py b/posthog/warehouse/api/external_data_source.py index 2e3f66de9c630..24439fcecdc19 100644 --- a/posthog/warehouse/api/external_data_source.py +++ b/posthog/warehouse/api/external_data_source.py @@ -24,6 +24,7 @@ from posthog.hogql.database.database import create_hogql_database from posthog.temporal.data_imports.pipelines.stripe import validate_credentials as validate_stripe_credentials from posthog.temporal.data_imports.pipelines.zendesk import validate_credentials as validate_zendesk_credentials +from posthog.temporal.data_imports.pipelines.vitally import validate_credentials as validate_vitally_credentials from posthog.temporal.data_imports.pipelines.schemas import ( PIPELINE_TYPE_INCREMENTAL_ENDPOINTS_MAPPING, PIPELINE_TYPE_INCREMENTAL_FIELDS_MAPPING, @@ -280,6 +281,8 @@ def create(self, request: Request, *args: Any, **kwargs: Any) -> Response: new_source_model = self._handle_zendesk_source(request, *args, **kwargs) elif source_type == ExternalDataSource.Type.SALESFORCE: new_source_model = self._handle_salesforce_source(request, *args, **kwargs) + elif source_type == ExternalDataSource.Type.VITALLY: + new_source_model = self._handle_vitally_source(request, *args, **kwargs) elif source_type in [ ExternalDataSource.Type.POSTGRES, ExternalDataSource.Type.MYSQL, @@ -395,6 +398,28 @@ def _handle_stripe_source(self, request: Request, *args: Any, **kwargs: Any) -> return new_source_model + def _handle_vitally_source(self, request: Request, *args: Any, **kwargs: Any) -> ExternalDataSource: + payload = request.data["payload"] + secret_token = payload.get("secret_token") + region = payload.get("region") + subdomain = payload.get("subdomain", None) + prefix = request.data.get("prefix", None) + source_type = request.data["source_type"] + + # TODO: remove dummy vars + new_source_model = ExternalDataSource.objects.create( + source_id=str(uuid.uuid4()), + connection_id=str(uuid.uuid4()), + destination_id=str(uuid.uuid4()), + team=self.team, + status="Running", + source_type=source_type, + job_inputs={"secret_token": secret_token, "region": region, "subdomain": subdomain}, + prefix=prefix, + ) + + return new_source_model + def _handle_zendesk_source(self, request: Request, *args: Any, **kwargs: Any) -> ExternalDataSource: payload = request.data["payload"] api_key = payload.get("api_key") @@ -690,6 +715,15 @@ def database_schema(self, request: Request, *arg: Any, **kwargs: Any): status=status.HTTP_400_BAD_REQUEST, data={"message": "Invalid credentials: Zendesk credentials are incorrect"}, ) + elif source_type == ExternalDataSource.Type.VITALLY: + secret_token = request.data.get("secret_token", "") + region = request.data.get("region", "") + subdomain = request.data.get("subdomain", "") + if not validate_vitally_credentials(subdomain=subdomain, secret_token=secret_token, region=region): + return Response( + status=status.HTTP_400_BAD_REQUEST, + data={"message": "Invalid credentials: Zendesk credentials are incorrect"}, + ) # Get schemas and validate SQL credentials if source_type in [ diff --git a/posthog/warehouse/models/external_data_schema.py b/posthog/warehouse/models/external_data_schema.py index 83f16eaa9aa1f..a3ba7730aaaa3 100644 --- a/posthog/warehouse/models/external_data_schema.py +++ b/posthog/warehouse/models/external_data_schema.py @@ -90,7 +90,9 @@ def aget_schema_if_exists(schema_name: str, team_id: int, source_id: uuid.UUID) @database_sync_to_async def aget_schema_by_id(schema_id: str, team_id: int) -> ExternalDataSchema | None: - return ExternalDataSchema.objects.prefetch_related("source").get(id=schema_id, team_id=team_id) + return ( + ExternalDataSchema.objects.prefetch_related("source").exclude(deleted=True).get(id=schema_id, team_id=team_id) + ) @database_sync_to_async diff --git a/posthog/warehouse/models/external_data_source.py b/posthog/warehouse/models/external_data_source.py index 6f9fe14e01dd9..14dd7c99dd88c 100644 --- a/posthog/warehouse/models/external_data_source.py +++ b/posthog/warehouse/models/external_data_source.py @@ -23,6 +23,7 @@ class Type(models.TextChoices): SALESFORCE = "Salesforce", "Salesforce" MYSQL = "MySQL", "MySQL" MSSQL = "MSSQL", "MSSQL" + VITALLY = "Vitally", "Vitally" class Status(models.TextChoices): RUNNING = "Running", "Running" From 1bf80d4c38d2a35bdb3959d8801d6b3851552afc Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Thu, 5 Sep 2024 17:49:41 +0200 Subject: [PATCH 28/32] fix(insights): Clear "data warehouse not supported in funnels" error (#24809) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- posthog/api/test/test_query.py | 35 +++++++++++++++++++ .../hogql_queries/insights/funnels/base.py | 8 +++-- .../insights/funnels/funnel_event_query.py | 10 +++++- .../hogql_queries/insights/utils/entities.py | 17 ++++++--- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/posthog/api/test/test_query.py b/posthog/api/test/test_query.py index 78339bd3f30c2..e5a85099efd08 100644 --- a/posthog/api/test/test_query.py +++ b/posthog/api/test/test_query.py @@ -11,8 +11,10 @@ from posthog.models.utils import UUIDT from posthog.schema import ( CachedEventsQueryResponse, + DataWarehouseNode, EventPropertyFilter, EventsQuery, + FunnelsQuery, HogQLPropertyFilter, HogQLQuery, PersonPropertyFilter, @@ -731,6 +733,39 @@ def test_invalid_query_kind(self): api_response.content, ) + def test_funnel_query_with_data_warehouse_node_temporarily_raises(self): + # As of September 2024, funnels don't support data warehouse tables YET, so we want a helpful error message + api_response = self.client.post( + f"/api/projects/{self.team.id}/query/", + { + "query": FunnelsQuery( + series=[ + DataWarehouseNode( + id="xyz", + table_name="xyz", + id_field="id", + distinct_id_field="customer_email", + timestamp_field="created", + ), + DataWarehouseNode( + id="abc", + table_name="abc", + id_field="id", + distinct_id_field="customer_email", + timestamp_field="timestamp", + ), + ], + ).model_dump() + }, + ) + self.assertEqual(api_response.status_code, 400) + self.assertDictEqual( + api_response.json(), + self.validation_error_response( + "Data warehouse tables are not supported in funnels just yet. For now, please try this funnel without the data warehouse-based step." + ), + ) + def test_missing_query(self): api_response = self.client.post(f"/api/projects/{self.team.id}/query/", {"query": {}}) self.assertEqual(api_response.status_code, 400) diff --git a/posthog/hogql_queries/insights/funnels/base.py b/posthog/hogql_queries/insights/funnels/base.py index 477c205dd968c..84ddf66eafccd 100644 --- a/posthog/hogql_queries/insights/funnels/base.py +++ b/posthog/hogql_queries/insights/funnels/base.py @@ -299,7 +299,9 @@ def _serialize_step( action_id = step.event type = "events" elif isinstance(step, DataWarehouseNode): - raise NotImplementedError("DataWarehouseNode is not supported in funnels") + raise ValidationError( + "Data warehouse tables are not supported in funnels just yet. For now, please try this funnel without the data warehouse-based step." + ) else: action = Action.objects.get(pk=step.id) name = action.name @@ -584,7 +586,9 @@ def _build_step_query( action = Action.objects.get(pk=int(entity.id), team=self.context.team) event_expr = action_to_expr(action) elif isinstance(entity, DataWarehouseNode): - raise NotImplementedError("DataWarehouseNode is not supported in funnels") + raise ValidationError( + "Data warehouse tables are not supported in funnels just yet. For now, please try this funnel without the data warehouse-based step." + ) elif entity.event is None: # all events event_expr = ast.Constant(value=1) diff --git a/posthog/hogql_queries/insights/funnels/funnel_event_query.py b/posthog/hogql_queries/insights/funnels/funnel_event_query.py index 8acb0f7dea87b..c4cb9507534ef 100644 --- a/posthog/hogql_queries/insights/funnels/funnel_event_query.py +++ b/posthog/hogql_queries/insights/funnels/funnel_event_query.py @@ -7,7 +7,13 @@ from posthog.hogql_queries.utils.query_date_range import QueryDateRange from posthog.models.action.action import Action from posthog.models.property.property import PropertyName -from posthog.schema import ActionsNode, EventsNode, FunnelExclusionActionsNode, FunnelExclusionEventsNode +from posthog.schema import ( + ActionsNode, + DataWarehouseNode, + EventsNode, + FunnelExclusionActionsNode, + FunnelExclusionEventsNode, +) from rest_framework.exceptions import ValidationError @@ -143,6 +149,8 @@ def _entity_expr(self, skip_entity_filter: bool) -> ast.Expr | None: events.update(action.get_step_events()) except Action.DoesNotExist: raise ValidationError(f"Action ID {node.id} does not exist!") + elif isinstance(node, DataWarehouseNode): + continue # Data warehouse nodes aren't based on events else: raise ValidationError("Series and exclusions must be compose of action and event nodes") diff --git a/posthog/hogql_queries/insights/utils/entities.py b/posthog/hogql_queries/insights/utils/entities.py index 794ce6170da11..b14653b338035 100644 --- a/posthog/hogql_queries/insights/utils/entities.py +++ b/posthog/hogql_queries/insights/utils/entities.py @@ -1,6 +1,7 @@ from posthog.schema import ( ActionsNode, CohortPropertyFilter, + DataWarehouseNode, EmptyPropertyFilter, EventsNode, FunnelExclusionActionsNode, @@ -9,16 +10,16 @@ ) from posthog.types import AnyPropertyFilter, EntityNode, ExclusionEntityNode from collections import Counter -from rest_framework.exceptions import ValidationError def is_equal_type(a: EntityNode, b: EntityNode | ExclusionEntityNode) -> bool: if isinstance(a, EventsNode): return isinstance(b, EventsNode) or isinstance(b, FunnelExclusionEventsNode) - elif isinstance(a, ActionsNode): + if isinstance(a, ActionsNode): return isinstance(b, ActionsNode) or isinstance(b, FunnelExclusionActionsNode) - else: - raise ValidationError(detail=f"Type comparision for {type(a)} and {type(b)} not implemented.") + if isinstance(a, DataWarehouseNode): + return isinstance(b, DataWarehouseNode) + raise ValueError(detail=f"Type comparison for {type(a)} and {type(b)} not implemented.") def is_equal(a: EntityNode, b: EntityNode | ExclusionEntityNode, compare_properties=True) -> bool: @@ -44,6 +45,14 @@ def is_equal(a: EntityNode, b: EntityNode | ExclusionEntityNode, compare_propert ): return False + # different data source + if ( + isinstance(a, DataWarehouseNode) + and isinstance(b, DataWarehouseNode) + and (a.id != b.id or a.id_field != b.id_field) + ): + return False + # different properties if compare_properties and _sorted_property_reprs(a.properties) != _sorted_property_reprs(b.properties): return False From acda90e363f4f5867747fc0fcaab1c97748b3b49 Mon Sep 17 00:00:00 2001 From: timgl Date: Thu, 5 Sep 2024 16:52:01 +0100 Subject: [PATCH 29/32] fix: Fix UUID typing issues (#24815) --- ee/billing/quota_limiting.py | 2 +- ee/billing/test/test_quota_limiting.py | 6 ++-- .../session_recording_playlist.py | 2 +- mypy-baseline.txt | 29 ------------------- posthog/api/email_verification.py | 2 +- posthog/api/test/batch_exports/operations.py | 17 ++++++----- posthog/models/utils.py | 2 +- posthog/plugins/plugin_server_api.py | 7 +++-- posthog/tasks/email.py | 3 +- posthog/tasks/stop_surveys_reached_target.py | 4 +-- posthog/tasks/update_survey_iteration.py | 2 +- 11 files changed, 25 insertions(+), 51 deletions(-) diff --git a/ee/billing/quota_limiting.py b/ee/billing/quota_limiting.py index f91811d866a40..e5f3d641b5364 100644 --- a/ee/billing/quota_limiting.py +++ b/ee/billing/quota_limiting.py @@ -134,7 +134,7 @@ def org_quota_limited_until( if posthoganalytics.feature_enabled( QUOTA_LIMIT_DATA_RETENTION_FLAG, - organization.id, + str(organization.id), groups={"organization": str(organization.id)}, group_properties={"organization": {"id": str(organization.id)}}, ): diff --git a/ee/billing/test/test_quota_limiting.py b/ee/billing/test/test_quota_limiting.py index 926e3441c4f73..fedf7b15a54ec 100644 --- a/ee/billing/test/test_quota_limiting.py +++ b/ee/billing/test/test_quota_limiting.py @@ -69,9 +69,9 @@ def test_quota_limiting_feature_flag_enabled(self, patch_feature_enabled, patch_ quota_limited_orgs, quota_limiting_suspended_orgs = update_all_org_billing_quotas() patch_feature_enabled.assert_called_with( QUOTA_LIMIT_DATA_RETENTION_FLAG, - self.organization.id, + str(self.organization.id), groups={"organization": org_id}, - group_properties={"organization": {"id": org_id}}, + group_properties={"organization": {"id": str(org_id)}}, ) patch_capture.assert_called_once_with( org_id, @@ -101,7 +101,7 @@ def test_quota_limiting_feature_flag_enabled(self, patch_feature_enabled, patch_ quota_limited_orgs, quota_limiting_suspended_orgs = update_all_org_billing_quotas() patch_feature_enabled.assert_called_with( QUOTA_LIMIT_DATA_RETENTION_FLAG, - self.organization.id, + str(self.organization.id), groups={"organization": org_id}, group_properties={"organization": {"id": org_id}}, ) diff --git a/ee/session_recordings/session_recording_playlist.py b/ee/session_recordings/session_recording_playlist.py index 28d3353c0576f..8947e1c270ee4 100644 --- a/ee/session_recordings/session_recording_playlist.py +++ b/ee/session_recordings/session_recording_playlist.py @@ -258,7 +258,7 @@ def modify_recordings( return response.Response({"success": True}) if request.method == "DELETE": - playlist_item = SessionRecordingPlaylistItem.objects.get(playlist=playlist, recording=session_recording_id) # type: ignore + playlist_item = SessionRecordingPlaylistItem.objects.get(playlist=playlist, recording=session_recording_id) if playlist_item: playlist_item.delete() diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 42c3ab53b0a9c..149978d16ec83 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -112,8 +112,6 @@ posthog/models/filters/base_filter.py:0: error: "HogQLContext" has no attribute posthog/models/team/team.py:0: error: Statement is unreachable [unreachable] posthog/models/team/team.py:0: error: Statement is unreachable [unreachable] posthog/models/hog_functions/hog_function.py:0: error: Argument 1 to "get" of "dict" has incompatible type "str | None"; expected "str" [arg-type] -posthog/models/hog_functions/hog_function.py:0: error: Argument 2 to "get_hog_function_status" has incompatible type "UUID"; expected "str" [arg-type] -posthog/models/hog_functions/hog_function.py:0: error: Argument 2 to "patch_hog_function_status" has incompatible type "UUID"; expected "str" [arg-type] posthog/models/user.py:0: error: Incompatible types in assignment (expression has type "type[User]", base class "BaseManager" defined the type as "type[_T]") [assignment] posthog/models/user.py:0: error: Cannot override class variable (previously declared on base class "AbstractBaseUser") with instance variable [misc] posthog/models/user.py:0: error: Incompatible types in assignment (expression has type "None", base class "AbstractUser" defined the type as "CharField[str | int | Combinable, str]") [assignment] @@ -259,7 +257,6 @@ posthog/hogql/printer.py:0: error: "FieldOrTable" has no attribute "name" [attr posthog/hogql/printer.py:0: error: "FieldOrTable" has no attribute "name" [attr-defined] posthog/hogql/printer.py:0: error: Argument 2 to "_get_materialized_column" of "_Printer" has incompatible type "str | int"; expected "str" [arg-type] posthog/hogql/printer.py:0: error: Argument 1 to "_print_identifier" of "_Printer" has incompatible type "str | None"; expected "str" [arg-type] -posthog/user_permissions.py:0: error: Key expression in dictionary comprehension has incompatible type "UUID"; expected type "int" [misc] posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "Level | None") [return-value] posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "Level | None") [return-value] posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "RestrictionLevel") [return-value] @@ -267,7 +264,6 @@ posthog/tasks/update_survey_iteration.py:0: error: Incompatible types in assignm posthog/tasks/update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] posthog/tasks/update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] posthog/tasks/update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "save" [union-attr] -posthog/tasks/update_survey_iteration.py:0: error: Incompatible type for "key" of "FeatureFlag" (got "UUID", expected "str | int | Combinable") [misc] posthog/permissions.py:0: error: Argument 2 to "feature_enabled" has incompatible type "str | None"; expected "str" [arg-type] posthog/models/event/util.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "datetime") [assignment] posthog/models/event/util.py:0: error: Module has no attribute "utc" [attr-defined] @@ -288,7 +284,6 @@ posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] posthog/api/shared.py:0: error: Incompatible return value type (got "int | None", expected "Level | None") [return-value] -ee/billing/quota_limiting.py:0: error: Argument 2 to "feature_enabled" has incompatible type "UUID"; expected "str" [arg-type] ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] ee/billing/quota_limiting.py:0: error: "object" has no attribute "get" [attr-defined] ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] @@ -334,7 +329,6 @@ posthog/models/property/util.py:0: error: Argument 1 to "append" of "list" has i posthog/models/property/util.py:0: error: Argument 1 to "append" of "list" has incompatible type "str | int"; expected "str" [arg-type] posthog/api/utils.py:0: error: Incompatible types in assignment (expression has type "type[EventDefinition]", variable has type "type[EnterpriseEventDefinition]") [assignment] posthog/api/utils.py:0: error: Argument 1 to "UUID" has incompatible type "int | str"; expected "str | None" [arg-type] -posthog/api/email_verification.py:0: error: Argument 2 to "feature_enabled" has incompatible type "UUID"; expected "str" [arg-type] posthog/queries/trends/util.py:0: error: Argument 1 to "translate_hogql" has incompatible type "str | None"; expected "str" [arg-type] posthog/hogql/property.py:0: error: Incompatible type for lookup 'id': (got "str | int | list[str]", expected "str | int") [misc] posthog/hogql/property.py:0: error: Incompatible type for lookup 'pk': (got "str | float", expected "str | int") [misc] @@ -378,18 +372,12 @@ ee/clickhouse/queries/funnels/funnel_correlation.py:0: error: Statement is unrea posthog/api/insight.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] posthog/api/dashboards/dashboard.py:0: error: Argument 1 to "dashboard_queryset" of "DashboardTile" has incompatible type "DashboardTile_RelatedManager"; expected "QuerySet[Any, Any]" [arg-type] posthog/api/person.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] -posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument 1 to "loads" has incompatible type "str | None"; expected "str | bytes | bytearray" [arg-type] -posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument "user" to "log_activity" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type] -posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument "user" to "log_activity" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type] -posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Cannot determine type of "group_properties_filter_group" [has-type] posthog/caching/insight_caching_state.py:0: error: Argument "params" to "execute" of "CursorWrapper" has incompatible type "list[object]"; expected "Sequence[bool | int | float | Decimal | str | <6 more items> | None] | Mapping[str, bool | int | float | Decimal | str | <6 more items> | None] | None" [arg-type] posthog/api/cohort.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] -posthog/api/cohort.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/api/cohort.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/cohort.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] posthog/caching/insights_api.py:0: error: Unsupported operand types for >= ("datetime" and "None") [operator] posthog/caching/insights_api.py:0: note: Right operand is of type "datetime | None" @@ -397,8 +385,6 @@ posthog/api/feature_flag.py:0: error: Item "Sequence[Any]" of "Any | Sequence[An posthog/api/feature_flag.py:0: error: Item "None" of "Any | Sequence[Any] | None" has no attribute "filters" [union-attr] posthog/api/feature_flag.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] posthog/api/feature_flag.py:0: error: Argument 2 to "get_all_feature_flags" has incompatible type "str | None"; expected "str" [arg-type] -posthog/api/feature_flag.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/api/feature_flag.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/hogql_queries/web_analytics/web_analytics_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/hogql_queries/web_analytics/web_analytics_query_runner.py:0: error: Argument 1 to "append" of "list" has incompatible type "EventPropertyFilter"; expected "Expr" [arg-type] posthog/hogql_queries/insights/trends/trends_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] @@ -422,8 +408,6 @@ posthog/hogql_queries/insights/lifecycle_query_runner.py:0: error: Item "SelectU posthog/hogql_queries/insights/lifecycle_query_runner.py:0: error: Item "None" of "JoinExpr | Any | None" has no attribute "sample" [union-attr] posthog/hogql_queries/insights/funnels/funnels_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/survey.py:0: error: Incompatible types in assignment (expression has type "Any | Sequence[Any] | None", variable has type "Survey | None") [assignment] -posthog/api/survey.py:0: error: Argument "item_id" to "log_activity" has incompatible type "UUID"; expected "int | str | UUIDT | None" [arg-type] -posthog/api/survey.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/survey.py:0: error: Item "list[_ErrorFullDetails]" of "_FullDetailDict | list[_ErrorFullDetails] | dict[str, _ErrorFullDetails]" has no attribute "get" [union-attr] posthog/api/survey.py:0: error: Item "object" of "object | Any" has no attribute "__iter__" (not iterable) [union-attr] posthog/hogql_queries/web_analytics/web_overview.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] @@ -454,9 +438,6 @@ posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "tiles" [union-attr] posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "tiles" [union-attr] posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "delete" [union-attr] -posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] @@ -616,7 +597,6 @@ posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | Non posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | None" for "dict[str, int]"; expected type "str" [index] posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | None" for "dict[str, int]"; expected type "str" [index] posthog/api/notebook.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "str | None") [assignment] -posthog/api/exports.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "DataWarehouseCredential | Combinable | None") [assignment] posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "str | int | Combinable") [assignment] posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "dict[str, dict[str, str | bool]] | dict[str, str]", variable has type "dict[str, dict[str, str]]") [assignment] @@ -787,9 +767,6 @@ posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/tests/batch_exports/test_batch_exports.py:0: error: TypedDict key must be a string literal; expected one of ("_timestamp", "created_at", "distinct_id", "elements", "elements_chain", ...) [literal-required] -posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] -posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] -posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] posthog/session_recordings/session_recording_api.py:0: error: Argument "team_id" to "get_realtime_snapshots" has incompatible type "int"; expected "str" [arg-type] posthog/session_recordings/session_recording_api.py:0: error: Value of type variable "SupportsRichComparisonT" of "sorted" cannot be "str | None" [type-var] posthog/session_recordings/session_recording_api.py:0: error: Argument 1 to "get" of "dict" has incompatible type "str | None"; expected "str" [arg-type] @@ -831,10 +808,8 @@ posthog/warehouse/external_data_source/source.py:0: error: Argument 1 to "_creat posthog/temporal/tests/batch_exports/test_redshift_batch_export_workflow.py:0: error: Incompatible types in assignment (expression has type "str | int", variable has type "int") [assignment] posthog/api/sharing.py:0: error: Item "None" of "list[Any] | None" has no attribute "__iter__" (not iterable) [union-attr] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] posthog/api/plugin.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str | int | Combinable") [assignment] posthog/api/plugin.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str | int | Combinable") [assignment] @@ -844,10 +819,7 @@ posthog/api/plugin.py:0: error: Incompatible type for "file_name" of "PluginAtta posthog/api/plugin.py:0: error: Incompatible type for "file_size" of "PluginAttachment" (got "int | None", expected "float | int | str | Combinable") [misc] posthog/api/plugin.py:0: error: Item "None" of "IO[Any] | None" has no attribute "read" [union-attr] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] @@ -916,7 +888,6 @@ posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "s posthog/api/test/batch_exports/test_update.py:0: error: Unsupported target for indexed assignment ("Collection[str]") [index] posthog/api/test/batch_exports/test_update.py:0: error: Unsupported target for indexed assignment ("Collection[str]") [index] posthog/api/test/batch_exports/test_update.py:0: error: Dict entry 1 has incompatible type "str": "dict[str, Collection[str]]"; expected "str": "str" [dict-item] -posthog/api/test/batch_exports/test_update.py:0: error: Argument 3 to "get_batch_export_ok" has incompatible type "UUID"; expected "int" [arg-type] posthog/api/test/batch_exports/test_update.py:0: error: Value of type "BatchExport" is not indexable [index] posthog/api/test/batch_exports/test_update.py:0: error: Value of type "BatchExport" is not indexable [index] posthog/api/test/batch_exports/test_update.py:0: error: Value of type "BatchExport" is not indexable [index] diff --git a/posthog/api/email_verification.py b/posthog/api/email_verification.py index e22a298fe44a0..83c12d1dfe1e9 100644 --- a/posthog/api/email_verification.py +++ b/posthog/api/email_verification.py @@ -14,7 +14,7 @@ def is_email_verification_disabled(user: User) -> bool: # using disabled here so that the default state (if no flag exists) is that verification defaults to ON. return user.organization is not None and posthoganalytics.feature_enabled( VERIFICATION_DISABLED_FLAG, - user.organization.id, + str(user.organization.id), groups={"organization": str(user.organization.id)}, group_properties={"organization": {"id": str(user.organization.id)}}, ) diff --git a/posthog/api/test/batch_exports/operations.py b/posthog/api/test/batch_exports/operations.py index 5ac814deab1e2..20f7d2761e2bf 100644 --- a/posthog/api/test/batch_exports/operations.py +++ b/posthog/api/test/batch_exports/operations.py @@ -1,5 +1,6 @@ from django.test.client import Client as TestClient from rest_framework import status +from posthog.models.utils import UUIDT def create_batch_export(client: TestClient, team_id: int, batch_export_data: dict | str): @@ -16,17 +17,17 @@ def create_batch_export_ok(client: TestClient, team_id: int, batch_export_data: return response.json() -def pause_batch_export(client: TestClient, team_id: int, batch_export_id: int): +def pause_batch_export(client: TestClient, team_id: int, batch_export_id: UUIDT): return client.post(f"/api/projects/{team_id}/batch_exports/{batch_export_id}/pause") -def pause_batch_export_ok(client: TestClient, team_id: int, batch_export_id: int): +def pause_batch_export_ok(client: TestClient, team_id: int, batch_export_id: UUIDT): response = pause_batch_export(client, team_id, batch_export_id) assert response.status_code == status.HTTP_200_OK, response.json() return response.json() -def unpause_batch_export(client: TestClient, team_id: int, batch_export_id: int, backfill: bool = False): +def unpause_batch_export(client: TestClient, team_id: int, batch_export_id: UUIDT, backfill: bool = False): return client.post( f"/api/projects/{team_id}/batch_exports/{batch_export_id}/unpause", {"backfill": backfill}, @@ -34,17 +35,17 @@ def unpause_batch_export(client: TestClient, team_id: int, batch_export_id: int, ) -def unpause_batch_export_ok(client: TestClient, team_id: int, batch_export_id: int, backfill: bool = False): +def unpause_batch_export_ok(client: TestClient, team_id: int, batch_export_id: UUIDT, backfill: bool = False): response = unpause_batch_export(client, team_id, batch_export_id, backfill) assert response.status_code == status.HTTP_200_OK, response.json() return response.json() -def get_batch_export(client: TestClient, team_id: int, batch_export_id: int): +def get_batch_export(client: TestClient, team_id: int, batch_export_id: UUIDT): return client.get(f"/api/projects/{team_id}/batch_exports/{batch_export_id}") -def get_batch_export_ok(client: TestClient, team_id: int, batch_export_id: int): +def get_batch_export_ok(client: TestClient, team_id: int, batch_export_id: UUIDT): response = get_batch_export(client, team_id, batch_export_id) assert response.status_code == status.HTTP_200_OK, response.json() return response.json() @@ -63,11 +64,11 @@ def get_batch_export_runs_ok(client: TestClient, team_id: int, batch_export_id: return response.json() -def delete_batch_export(client: TestClient, team_id: int, batch_export_id: int): +def delete_batch_export(client: TestClient, team_id: int, batch_export_id: UUIDT): return client.delete(f"/api/projects/{team_id}/batch_exports/{batch_export_id}") -def delete_batch_export_ok(client: TestClient, team_id: int, batch_export_id: int): +def delete_batch_export_ok(client: TestClient, team_id: int, batch_export_id: UUIDT): response = delete_batch_export(client, team_id, batch_export_id) assert response.status_code == status.HTTP_204_NO_CONTENT, response return response diff --git a/posthog/models/utils.py b/posthog/models/utils.py index e9498ce32990e..3dc7e83940b9a 100644 --- a/posthog/models/utils.py +++ b/posthog/models/utils.py @@ -164,7 +164,7 @@ class Meta: class UUIDModel(models.Model): """Base Django Model with default autoincremented ID field replaced with UUIDT.""" - id = models.UUIDField(primary_key=True, default=UUIDT, editable=False) + id: models.UUIDField = models.UUIDField(primary_key=True, default=UUIDT, editable=False) class Meta: abstract = True diff --git a/posthog/plugins/plugin_server_api.py b/posthog/plugins/plugin_server_api.py index fd18e49d16ed7..ef6b312ba874c 100644 --- a/posthog/plugins/plugin_server_api.py +++ b/posthog/plugins/plugin_server_api.py @@ -4,6 +4,7 @@ import structlog from posthog.redis import get_client from posthog.settings import CDP_FUNCTION_EXECUTOR_API_URL, PLUGINS_RELOAD_PUBSUB_CHANNEL, PLUGINS_RELOAD_REDIS_URL +from posthog.models.utils import UUIDT logger = structlog.get_logger(__name__) @@ -62,7 +63,7 @@ def populate_plugin_capabilities_on_workers(plugin_id: str): def create_hog_invocation_test( team_id: int, - hog_function_id: str, + hog_function_id: UUIDT, globals: dict, configuration: dict, mock_async_functions: bool, @@ -78,13 +79,13 @@ def create_hog_invocation_test( ) -def get_hog_function_status(team_id: int, hog_function_id: str) -> requests.Response: +def get_hog_function_status(team_id: int, hog_function_id: UUIDT) -> requests.Response: return requests.get( CDP_FUNCTION_EXECUTOR_API_URL + f"/api/projects/{team_id}/hog_functions/{hog_function_id}/status" ) -def patch_hog_function_status(team_id: int, hog_function_id: str, state: int) -> requests.Response: +def patch_hog_function_status(team_id: int, hog_function_id: UUIDT, state: int) -> requests.Response: return requests.patch( CDP_FUNCTION_EXECUTOR_API_URL + f"/api/projects/{team_id}/hog_functions/{hog_function_id}/status", json={"state": state}, diff --git a/posthog/tasks/email.py b/posthog/tasks/email.py index 925dce44493d1..ee9229109b832 100644 --- a/posthog/tasks/email.py +++ b/posthog/tasks/email.py @@ -20,6 +20,7 @@ Team, User, ) +from posthog.models.utils import UUIDT from posthog.user_permissions import UserPermissions logger = structlog.get_logger(__name__) @@ -159,7 +160,7 @@ def send_fatal_plugin_error( def send_batch_export_run_failure( - batch_export_run_id: str, + batch_export_run_id: UUIDT, ) -> None: logger = structlog.get_logger(__name__) diff --git a/posthog/tasks/stop_surveys_reached_target.py b/posthog/tasks/stop_surveys_reached_target.py index 5432a45d84b19..dc8f99ee3cff0 100644 --- a/posthog/tasks/stop_surveys_reached_target.py +++ b/posthog/tasks/stop_surveys_reached_target.py @@ -1,16 +1,16 @@ from itertools import groupby from django.db.models import Q from django.utils import timezone -from uuid import UUID from datetime import datetime from posthog.clickhouse.client.connection import Workload from posthog.client import sync_execute from posthog.models import Survey +from posthog.models.utils import UUIDT def _get_surveys_response_counts( - surveys_ids: list[UUID], team_id: int, earliest_survey_creation_date: datetime + surveys_ids: list[UUIDT], team_id: int, earliest_survey_creation_date: datetime ) -> dict[str, int]: data = sync_execute( """ diff --git a/posthog/tasks/update_survey_iteration.py b/posthog/tasks/update_survey_iteration.py index 5218a99010252..2c6096b19261b 100644 --- a/posthog/tasks/update_survey_iteration.py +++ b/posthog/tasks/update_survey_iteration.py @@ -58,7 +58,7 @@ def _get_targeting_flag(survey: Survey) -> ForeignKey | ForeignKey | Any: team=survey.team, created_by=survey.created_by, active=True, - key=survey.id, + key=str(survey.id), filters=user_submitted_dismissed_filter, ) new_flag.save() From 20e65c64c88bf4383fcfe6f66434264f19f620da Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Thu, 5 Sep 2024 17:38:05 +0100 Subject: [PATCH 30/32] chore: allow exporting mobile recordings while impersonating a user (#24816) --- .../src/scenes/session-recordings/player/PlayerMetaLinks.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx b/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx index a58bc3e739ead..b677c8fec155e 100644 --- a/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx +++ b/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx @@ -170,7 +170,7 @@ const MenuActions = (): JSX.Element => { useActions(sessionRecordingPlayerLogic) const { fetchSimilarRecordings } = useActions(sessionRecordingDataLogic(logicProps)) - const hasMobileExport = useFeatureFlag('SESSION_REPLAY_EXPORT_MOBILE_DATA') + const hasMobileExport = window.IMPERSONATED_SESSION || useFeatureFlag('SESSION_REPLAY_EXPORT_MOBILE_DATA') const hasSimilarRecordings = useFeatureFlag('REPLAY_SIMILAR_RECORDINGS') const onDelete = (): void => { From 6f6a80af973147f4a4d512e5331164ab185ec998 Mon Sep 17 00:00:00 2001 From: Raquel Smith Date: Thu, 5 Sep 2024 10:59:04 -0700 Subject: [PATCH 31/32] feat(onboarding-templates): create custom variable selector panel (#24770) --- .../lemon-ui/LemonCollapse/LemonCollapse.tsx | 7 +- .../dashboardTemplateVariablesLogic.ts | 61 +++++- .../DashboardTemplateConfigureStep.tsx | 20 +- .../DashboardTemplateVariables.tsx | 186 ++++++++++++++++++ frontend/src/types.ts | 1 + 5 files changed, 267 insertions(+), 8 deletions(-) create mode 100644 frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateVariables.tsx diff --git a/frontend/src/lib/lemon-ui/LemonCollapse/LemonCollapse.tsx b/frontend/src/lib/lemon-ui/LemonCollapse/LemonCollapse.tsx index 32b569226dcaa..ed3bd39277311 100644 --- a/frontend/src/lib/lemon-ui/LemonCollapse/LemonCollapse.tsx +++ b/frontend/src/lib/lemon-ui/LemonCollapse/LemonCollapse.tsx @@ -96,6 +96,7 @@ interface LemonCollapsePanelProps { onChange: (isExpanded: boolean) => void className?: string dataAttr?: string + onHeaderClick?: () => void } function LemonCollapsePanel({ @@ -106,13 +107,17 @@ function LemonCollapsePanel({ className, dataAttr, onChange, + onHeaderClick, }: LemonCollapsePanelProps): JSX.Element { const { height: contentHeight, ref: contentRef } = useResizeObserver({ box: 'border-box' }) return (
onChange(!isExpanded)} + onClick={() => { + onHeaderClick && onHeaderClick() + onChange(!isExpanded) + }} icon={isExpanded ? : } className="LemonCollapsePanel__header" {...(dataAttr ? { 'data-attr': dataAttr } : {})} diff --git a/frontend/src/scenes/dashboard/dashboardTemplateVariablesLogic.ts b/frontend/src/scenes/dashboard/dashboardTemplateVariablesLogic.ts index 39b45617e66ac..da23d22466d25 100644 --- a/frontend/src/scenes/dashboard/dashboardTemplateVariablesLogic.ts +++ b/frontend/src/scenes/dashboard/dashboardTemplateVariablesLogic.ts @@ -1,4 +1,4 @@ -import { actions, kea, path, props, propsChanged, reducers } from 'kea' +import { actions, kea, listeners, path, props, propsChanged, reducers, selectors } from 'kea' import { isEmptyObject } from 'lib/utils' import { DashboardTemplateVariableType, FilterType, Optional } from '~/types' @@ -24,6 +24,11 @@ export const dashboardTemplateVariablesLogic = kea ({ index }), + incrementActiveVariableIndex: true, + possiblyIncrementActiveVariableIndex: true, + resetVariable: (variableId: string) => ({ variableId }), + goToNextUntouchedActiveVariableIndex: true, }), reducers({ variables: [ @@ -41,14 +46,64 @@ export const dashboardTemplateVariablesLogic = kea { if (v.name === variableName && filterGroup?.events?.length && filterGroup.events[0]) { - return { ...v, default: filterGroup.events[0] } + return { ...v, default: filterGroup.events[0], touched: true } } - return v + return { ...v } + }) + }, + resetVariable: (state, { variableId }) => { + return state.map((v: DashboardTemplateVariableType) => { + if (v.id === variableId) { + return { ...v, default: FALLBACK_EVENT, touched: false } + } + return { ...v } }) }, }, ], + activeVariableIndex: [ + 0, + { + setActiveVariableIndex: (_, { index }) => index, + incrementActiveVariableIndex: (state) => state + 1, + }, + ], }), + selectors(() => ({ + activeVariable: [ + (s) => [s.variables, s.activeVariableIndex], + (variables: DashboardTemplateVariableType[], activeVariableIndex: number) => { + return variables[activeVariableIndex] + }, + ], + allVariablesAreTouched: [ + (s) => [s.variables], + (variables: DashboardTemplateVariableType[]) => { + return variables.every((v) => v.touched) + }, + ], + })), + listeners(({ actions, props, values }) => ({ + possiblyIncrementActiveVariableIndex: () => { + if (props.variables.length > 0 && values.activeVariableIndex < props.variables.length - 1) { + actions.incrementActiveVariableIndex() + } + }, + goToNextUntouchedActiveVariableIndex: () => { + let nextIndex = values.variables.findIndex((v, i) => !v.touched && i > values.activeVariableIndex) + if (nextIndex !== -1) { + actions.setActiveVariableIndex(nextIndex) + return + } + if (nextIndex == -1) { + nextIndex = values.variables.findIndex((v) => !v.touched) + if (nextIndex == -1) { + nextIndex = values.activeVariableIndex + } + } + actions.setActiveVariableIndex(nextIndex) + }, + })), propsChanged(({ actions, props }, oldProps) => { if (props.variables !== oldProps.variables) { actions.setVariables(props.variables) diff --git a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx index 1f67ee2abd399..2bed8e8a07d2f 100644 --- a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx +++ b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateConfigureStep.tsx @@ -1,17 +1,17 @@ import { IconArrowRight } from '@posthog/icons' -import { LemonButton, LemonCard, LemonSkeleton } from '@posthog/lemon-ui' +import { LemonButton, LemonCard, LemonSkeleton, Link } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { authorizedUrlListLogic, AuthorizedUrlListType } from 'lib/components/AuthorizedUrlList/authorizedUrlListLogic' import { IframedToolbarBrowser } from 'lib/components/IframedToolbarBrowser/IframedToolbarBrowser' import { iframedToolbarBrowserLogic } from 'lib/components/IframedToolbarBrowser/iframedToolbarBrowserLogic' import { useRef, useState } from 'react' -import { DashboardTemplateVariables } from 'scenes/dashboard/DashboardTemplateVariables' import { dashboardTemplateVariablesLogic } from 'scenes/dashboard/dashboardTemplateVariablesLogic' import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic' import { OnboardingStepKey } from '../onboardingLogic' import { OnboardingStep } from '../OnboardingStep' import { sdksLogic } from '../sdks/sdksLogic' +import { DashboardTemplateVariables } from './DashboardTemplateVariables' import { onboardingTemplateConfigLogic } from './onboardingTemplateConfigLogic' export const OnboardingDashboardTemplateConfigureStep = ({ @@ -23,11 +23,14 @@ export const OnboardingDashboardTemplateConfigureStep = ({ const { activeDashboardTemplate } = useValues(onboardingTemplateConfigLogic) const { createDashboardFromTemplate } = useActions(newDashboardLogic) const { isLoading } = useValues(newDashboardLogic) - const { variables } = useValues(dashboardTemplateVariablesLogic) const { snippetHosts } = useValues(sdksLogic) const { addUrl } = useActions(authorizedUrlListLogic({ actionId: null, type: AuthorizedUrlListType.TOOLBAR_URLS })) const { setBrowserUrl } = useActions(iframedToolbarBrowserLogic({ iframeRef, clearBrowserUrlOnUnmount: true })) const { browserUrl } = useValues(iframedToolbarBrowserLogic({ iframeRef, clearBrowserUrlOnUnmount: true })) + const theDashboardTemplateVariablesLogic = dashboardTemplateVariablesLogic({ + variables: activeDashboardTemplate?.variables || [], + }) + const { variables, allVariablesAreTouched } = useValues(theDashboardTemplateVariablesLogic) const [isSubmitting, setIsSubmitting] = useState(false) @@ -105,7 +108,15 @@ export const OnboardingDashboardTemplateConfigureStep = ({ )}
- +

+ For each action below, select an element on your site that indicates when that action is + taken, or enter a custom event name that you'll send using{' '} + + posthog.capture() + {' '} + (no need to send it now) . +

+ Create dashboard diff --git a/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateVariables.tsx b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateVariables.tsx new file mode 100644 index 0000000000000..e22f822eedcfe --- /dev/null +++ b/frontend/src/scenes/onboarding/productAnalyticsSteps/DashboardTemplateVariables.tsx @@ -0,0 +1,186 @@ +import { IconCheckCircle, IconInfo, IconTrash } from '@posthog/icons' +import { LemonBanner, LemonButton, LemonCollapse, LemonInput, LemonLabel } from '@posthog/lemon-ui' +import { useActions, useValues } from 'kea' +import { useEffect, useState } from 'react' +import { dashboardTemplateVariablesLogic } from 'scenes/dashboard/dashboardTemplateVariablesLogic' +import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic' + +import { DashboardTemplateVariableType } from '~/types' + +function VariableSelector({ + variable, + hasSelectedSite, +}: { + variable: DashboardTemplateVariableType + hasSelectedSite: boolean +}): JSX.Element { + const { activeDashboardTemplate } = useValues(newDashboardLogic) + const theDashboardTemplateVariablesLogic = dashboardTemplateVariablesLogic({ + variables: activeDashboardTemplate?.variables || [], + }) + const { setVariable, resetVariable, goToNextUntouchedActiveVariableIndex, incrementActiveVariableIndex } = + useActions(theDashboardTemplateVariablesLogic) + const { allVariablesAreTouched, variables, activeVariableIndex } = useValues(theDashboardTemplateVariablesLogic) + const [customEventName, setCustomEventName] = useState(null) + const [showCustomEventField, setShowCustomEventField] = useState(false) + + const FALLBACK_EVENT = { + id: '$other_event', + math: 'dau', + type: 'events', + } + + return ( +
+
+

+ {variable.description} +

+
+ {variable.touched && !customEventName && ( +
+
+ {' '} + Selected +

.md-invite-button

+
+
+ } + type="tertiary" + size="small" + onClick={() => resetVariable(variable.id)} + /> +
+
+ )} + {showCustomEventField && ( +
+ Custom event name +

+ Set the name that you'll use for a custom event (eg. a backend event) instead of selecting an + event from your site. You can change this later if needed. +

+
+ { + if (v) { + setCustomEventName(v) + setVariable(variable.name, { + events: [{ id: v, math: 'dau', type: 'events' }], + }) + } else { + setCustomEventName(null) + resetVariable(variable.id) + } + }} + onBlur={() => { + if (customEventName) { + setVariable(variable.name, { + events: [{ id: customEventName, math: 'dau', type: 'events' }], + }) + } else { + resetVariable(variable.id) + setShowCustomEventField(false) + } + }} + /> +
+ } + type="tertiary" + size="small" + onClick={() => { + resetVariable(variable.id) + setCustomEventName(null) + setShowCustomEventField(false) + }} + /> +
+
+
+ )} + {!hasSelectedSite ? ( + Please select a site to continue. + ) : ( +
+ {variable.touched ? ( + <> + {!allVariablesAreTouched || + (allVariablesAreTouched && variables.length !== activeVariableIndex + 1) ? ( + + !allVariablesAreTouched + ? goToNextUntouchedActiveVariableIndex() + : variables.length !== activeVariableIndex + 1 + ? incrementActiveVariableIndex() + : null + } + > + Continue + + ) : null} + + ) : ( +
+ { + setShowCustomEventField(false) + setVariable(variable.name, { events: [FALLBACK_EVENT] }) + }} + > + Select from site + + setShowCustomEventField(true)}> + Use custom event + +
+ )} +
+ )} +
+ ) +} + +export function DashboardTemplateVariables({ hasSelectedSite }: { hasSelectedSite: boolean }): JSX.Element { + const { activeDashboardTemplate } = useValues(newDashboardLogic) + const theDashboardTemplateVariablesLogic = dashboardTemplateVariablesLogic({ + variables: activeDashboardTemplate?.variables || [], + }) + const { variables, activeVariableIndex } = useValues(theDashboardTemplateVariablesLogic) + const { setVariables, setActiveVariableIndex } = useActions(theDashboardTemplateVariablesLogic) + + // TODO: onboarding-dashboard-templates: this is a hack, I'm not sure why it's not set properly initially. + useEffect(() => { + setVariables(activeDashboardTemplate?.variables || []) + }, [activeDashboardTemplate]) + + return ( +
+ ({ + key: v.id, + header: ( +
+ {v.name} + {v.touched && } +
+ ), + content: , + className: 'p-4 bg-white', + onHeaderClick: () => { + setActiveVariableIndex(i) + }, + }))} + embedded + size="small" + /> +
+ ) +} diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 61d6072f17d21..d1aaa92a6007f 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -1800,6 +1800,7 @@ export interface DashboardTemplateVariableType { type: 'event' default: Record required: boolean + touched?: boolean } export type DashboardLayoutSize = 'sm' | 'xs' From 7fa73a86af7a170aed027da79570a4214ffbdf34 Mon Sep 17 00:00:00 2001 From: Sandy Spicer Date: Thu, 5 Sep 2024 11:40:33 -0700 Subject: [PATCH 32/32] feat(insights): launch funnels as a Clickhouse UDF behind a feature flag (#23587) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- .github/actions/run-backend-tests/action.yml | 6 + .github/workflows/ci-backend.yml | 1 + docker-compose.dev-full.yml | 2 + docker-compose.dev.yml | 5 + .../docker-entrypoint-initdb.d/init-db.sh | 1 + docker/clickhouse/entrypoint.sh | 207 + docker/clickhouse/user_defined_function.xml | 287 ++ ...--funnel-top-to-bottom-breakdown--dark.png | Bin 96783 -> 96992 bytes frontend/src/lib/constants.tsx | 1 + frontend/src/queries/schema.json | 12 + frontend/src/queries/schema.ts | 5 +- posthog/hogql/constants.py | 2 + posthog/hogql/functions/mapping.py | 11 +- .../test/__snapshots__/test_in_cohort.ambr | 8 +- .../insights/funnels/__init__.py | 1 + .../hogql_queries/insights/funnels/base.py | 105 +- .../insights/funnels/funnel_query_context.py | 7 +- .../funnels/funnel_time_to_convert.py | 3 +- .../insights/funnels/funnel_trends.py | 124 +- .../insights/funnels/funnel_trends_udf.py | 163 + .../insights/funnels/funnel_udf.py | 184 + .../insights/funnels/funnels_query_runner.py | 19 +- .../test_breakdowns_by_current_url.ambr | 213 - .../__snapshots__/test_funnel_strict.ambr | 1127 +++++ .../__snapshots__/test_funnel_strict_udf.ambr | 2066 ++++++++ .../__snapshots__/test_funnel_trends.ambr | 362 ++ .../__snapshots__/test_funnel_trends_udf.ambr | 602 +++ .../test/__snapshots__/test_funnel_udf.ambr | 1887 ++++++++ .../insights/funnels/test/test_funnel.py | 29 +- .../funnels/test/test_funnel_strict.py | 29 +- .../funnels/test/test_funnel_strict_udf.py | 28 + .../funnels/test/test_funnel_trends.py | 22 +- .../funnels/test/test_funnel_trends_udf.py | 8 + .../insights/funnels/test/test_funnel_udf.py | 66 + .../hogql_queries/insights/funnels/utils.py | 5 +- posthog/hogql_queries/insights/utils/utils.py | 5 + .../legacy_compatibility/feature_flag.py | 21 + posthog/schema.py | 4 + posthog/test/user_scripts/__init__.py | 0 .../user_scripts/test_aggregate_funnel.py | 4206 +++++++++++++++++ posthog/user_scripts/aggregate_funnel.py | 144 + .../user_scripts/aggregate_funnel_array.py | 9 + .../aggregate_funnel_array_trends.py | 9 + .../aggregate_funnel_array_trends_test.py | 13 + .../user_scripts/aggregate_funnel_cohort.py | 9 + .../aggregate_funnel_cohort_trends.py | 9 + posthog/user_scripts/aggregate_funnel_test.py | 13 + .../user_scripts/aggregate_funnel_trends.py | 131 + posthog/utils.py | 1 + requirements.in | 2 +- requirements.txt | 2 +- 51 files changed, 11868 insertions(+), 308 deletions(-) create mode 100755 docker/clickhouse/entrypoint.sh create mode 100644 docker/clickhouse/user_defined_function.xml create mode 100644 posthog/hogql_queries/insights/funnels/funnel_trends_udf.py create mode 100644 posthog/hogql_queries/insights/funnels/funnel_udf.py delete mode 100644 posthog/hogql_queries/insights/funnels/test/__snapshots__/test_breakdowns_by_current_url.ambr create mode 100644 posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_strict_udf.ambr create mode 100644 posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_trends_udf.ambr create mode 100644 posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_udf.ambr create mode 100644 posthog/hogql_queries/insights/funnels/test/test_funnel_strict_udf.py create mode 100644 posthog/hogql_queries/insights/funnels/test/test_funnel_trends_udf.py create mode 100644 posthog/hogql_queries/insights/funnels/test/test_funnel_udf.py create mode 100644 posthog/test/user_scripts/__init__.py create mode 100644 posthog/test/user_scripts/test_aggregate_funnel.py create mode 100755 posthog/user_scripts/aggregate_funnel.py create mode 100755 posthog/user_scripts/aggregate_funnel_array.py create mode 100755 posthog/user_scripts/aggregate_funnel_array_trends.py create mode 100755 posthog/user_scripts/aggregate_funnel_array_trends_test.py create mode 100755 posthog/user_scripts/aggregate_funnel_cohort.py create mode 100755 posthog/user_scripts/aggregate_funnel_cohort_trends.py create mode 100755 posthog/user_scripts/aggregate_funnel_test.py create mode 100755 posthog/user_scripts/aggregate_funnel_trends.py diff --git a/.github/actions/run-backend-tests/action.yml b/.github/actions/run-backend-tests/action.yml index 7bbe4b5147942..34c0a34cebeda 100644 --- a/.github/actions/run-backend-tests/action.yml +++ b/.github/actions/run-backend-tests/action.yml @@ -167,6 +167,12 @@ runs: --durations=100 --durations-min=1.0 --store-durations \ $PYTEST_ARGS + # Uncomment this code to create an ssh-able console so you can debug issues with github actions + # (Consider changing the timeout in ci-backend.yml to have more time) + # - name: Setup tmate session + # if: failure() + # uses: mxschmitt/action-tmate@v3 + - name: Run /decide read replica tests id: run-decide-read-replica-tests if: ${{ inputs.segment == 'Core' && inputs.group == 1 && inputs.person-on-events != 'true' }} diff --git a/.github/workflows/ci-backend.yml b/.github/workflows/ci-backend.yml index 6155740676e03..fb15ed052a75a 100644 --- a/.github/workflows/ci-backend.yml +++ b/.github/workflows/ci-backend.yml @@ -224,6 +224,7 @@ jobs: django: needs: changes + # increase for tmate testing timeout-minutes: 30 name: Django tests – ${{ matrix.segment }} (persons-on-events ${{ matrix.person-on-events && 'on' || 'off' }}), Py ${{ matrix.python-version }}, ${{ matrix.clickhouse-server-image }} (${{matrix.group}}/${{ matrix.concurrency }}) diff --git a/docker-compose.dev-full.yml b/docker-compose.dev-full.yml index 96db120b76660..606d5f6a3bc9f 100644 --- a/docker-compose.dev-full.yml +++ b/docker-compose.dev-full.yml @@ -47,6 +47,8 @@ services: - ./docker/clickhouse/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d - ./docker/clickhouse/config.xml:/etc/clickhouse-server/config.xml - ./docker/clickhouse/users-dev.xml:/etc/clickhouse-server/users.xml + - ./docker/clickhouse/user_defined_function.xml:/etc/clickhouse-server/user_defined_function.xml + - ./posthog/user_scripts:/var/lib/clickhouse/user_scripts depends_on: - kafka - zookeeper diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index d21b1af2ee75d..e9d698c2d3584 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -61,10 +61,15 @@ services: - '9440:9440' - '9009:9009' volumes: + # this new entrypoint file is to fix a bug detailed here https://github.com/ClickHouse/ClickHouse/pull/59991 + # revert this when we upgrade clickhouse + - ./docker/clickhouse/entrypoint.sh:/entrypoint.sh - ./posthog/idl:/idl - ./docker/clickhouse/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d - ./docker/clickhouse/config.xml:/etc/clickhouse-server/config.xml - ./docker/clickhouse/users-dev.xml:/etc/clickhouse-server/users.xml + - ./docker/clickhouse/user_defined_function.xml:/etc/clickhouse-server/user_defined_function.xml + - ./posthog/user_scripts:/var/lib/clickhouse/user_scripts extra_hosts: - 'host.docker.internal:host-gateway' depends_on: diff --git a/docker/clickhouse/docker-entrypoint-initdb.d/init-db.sh b/docker/clickhouse/docker-entrypoint-initdb.d/init-db.sh index 0d4f4332c98ad..4141e3345d05b 100755 --- a/docker/clickhouse/docker-entrypoint-initdb.d/init-db.sh +++ b/docker/clickhouse/docker-entrypoint-initdb.d/init-db.sh @@ -1,4 +1,5 @@ #!/bin/bash set -e +apk add python3 cp -r /idl/* /var/lib/clickhouse/format_schemas/ diff --git a/docker/clickhouse/entrypoint.sh b/docker/clickhouse/entrypoint.sh new file mode 100755 index 0000000000000..7d247ab14ea2a --- /dev/null +++ b/docker/clickhouse/entrypoint.sh @@ -0,0 +1,207 @@ +#!/bin/bash + +set -eo pipefail +shopt -s nullglob + +DO_CHOWN=1 +if [ "${CLICKHOUSE_DO_NOT_CHOWN:-0}" = "1" ]; then + DO_CHOWN=0 +fi + +CLICKHOUSE_UID="${CLICKHOUSE_UID:-"$(id -u clickhouse)"}" +CLICKHOUSE_GID="${CLICKHOUSE_GID:-"$(id -g clickhouse)"}" + +# support --user +if [ "$(id -u)" = "0" ]; then + USER=$CLICKHOUSE_UID + GROUP=$CLICKHOUSE_GID +else + USER="$(id -u)" + GROUP="$(id -g)" + DO_CHOWN=0 +fi + +# set some vars +CLICKHOUSE_CONFIG="${CLICKHOUSE_CONFIG:-/etc/clickhouse-server/config.xml}" + +# get CH directories locations +DATA_DIR="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key=path || true)" +TMP_DIR="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key=tmp_path || true)" +USER_PATH="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key=user_files_path || true)" +LOG_PATH="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key=logger.log || true)" +LOG_DIR="" +if [ -n "$LOG_PATH" ]; then LOG_DIR="$(dirname "$LOG_PATH")"; fi +ERROR_LOG_PATH="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key=logger.errorlog || true)" +ERROR_LOG_DIR="" +if [ -n "$ERROR_LOG_PATH" ]; then ERROR_LOG_DIR="$(dirname "$ERROR_LOG_PATH")"; fi +FORMAT_SCHEMA_PATH="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key=format_schema_path || true)" + +# There could be many disks declared in config +readarray -t DISKS_PATHS < <(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key='storage_configuration.disks.*.path' || true) +readarray -t DISKS_METADATA_PATHS < <(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key='storage_configuration.disks.*.metadata_path' || true) + +CLICKHOUSE_USER="${CLICKHOUSE_USER:-default}" +CLICKHOUSE_PASSWORD="${CLICKHOUSE_PASSWORD:-}" +CLICKHOUSE_DB="${CLICKHOUSE_DB:-}" +CLICKHOUSE_ACCESS_MANAGEMENT="${CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT:-0}" + +for dir in "$DATA_DIR" \ + "$ERROR_LOG_DIR" \ + "$LOG_DIR" \ + "$TMP_DIR" \ + "$USER_PATH" \ + "$FORMAT_SCHEMA_PATH" \ + "${DISKS_PATHS[@]}" \ + "${DISKS_METADATA_PATHS[@]}" +do + # check if variable not empty + [ -z "$dir" ] && continue + # ensure directories exist + if [ "$DO_CHOWN" = "1" ]; then + mkdir="mkdir" + else + # if DO_CHOWN=0 it means that the system does not map root user to "admin" permissions + # it mainly happens on NFS mounts where root==nobody for security reasons + # thus mkdir MUST run with user id/gid and not from nobody that has zero permissions + mkdir="/usr/bin/clickhouse su "${USER}:${GROUP}" mkdir" + fi + if ! $mkdir -p "$dir"; then + echo "Couldn't create necessary directory: $dir" + exit 1 + fi + + if [ "$DO_CHOWN" = "1" ]; then + # ensure proper directories permissions + # but skip it for if directory already has proper premissions, cause recursive chown may be slow + if [ "$(stat -c %u "$dir")" != "$USER" ] || [ "$(stat -c %g "$dir")" != "$GROUP" ]; then + chown -R "$USER:$GROUP" "$dir" + fi + fi +done + +# if clickhouse user is defined - create it (user "default" already exists out of box) +if [ -n "$CLICKHOUSE_USER" ] && [ "$CLICKHOUSE_USER" != "default" ] || [ -n "$CLICKHOUSE_PASSWORD" ] || [ "$CLICKHOUSE_ACCESS_MANAGEMENT" != "0" ]; then + echo "$0: create new user '$CLICKHOUSE_USER' instead 'default'" + cat < /etc/clickhouse-server/users.d/default-user.xml + + + + + + + + <${CLICKHOUSE_USER}> + default + + ::/0 + + ${CLICKHOUSE_PASSWORD} + default + ${CLICKHOUSE_ACCESS_MANAGEMENT} + + + +EOT +fi + +CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS="${CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS:-}" + +# checking $DATA_DIR for initialization +if [ -d "${DATA_DIR%/}/data" ]; then + DATABASE_ALREADY_EXISTS='true' +fi + +# run initialization if flag CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS is not empty or data directory is empty +if [[ -n "${CLICKHOUSE_ALWAYS_RUN_INITDB_SCRIPTS}" || -z "${DATABASE_ALREADY_EXISTS}" ]]; then + RUN_INITDB_SCRIPTS='true' +fi + +if [ -n "${RUN_INITDB_SCRIPTS}" ]; then + if [ -n "$(ls /docker-entrypoint-initdb.d/)" ] || [ -n "$CLICKHOUSE_DB" ]; then + # port is needed to check if clickhouse-server is ready for connections + HTTP_PORT="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key=http_port --try)" + HTTPS_PORT="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_CONFIG" --key=https_port --try)" + + if [ -n "$HTTP_PORT" ]; then + URL="http://127.0.0.1:$HTTP_PORT/ping" + else + URL="https://127.0.0.1:$HTTPS_PORT/ping" + fi + + # Listen only on localhost until the initialization is done + /usr/bin/clickhouse su "${USER}:${GROUP}" /usr/bin/clickhouse-server --config-file="$CLICKHOUSE_CONFIG" -- --listen_host=127.0.0.1 & + pid="$!" + + # check if clickhouse is ready to accept connections + # will try to send ping clickhouse via http_port (max 1000 retries by default, with 1 sec timeout and 1 sec delay between retries) + tries=${CLICKHOUSE_INIT_TIMEOUT:-1000} + while ! wget --spider --no-check-certificate -T 1 -q "$URL" 2>/dev/null; do + if [ "$tries" -le "0" ]; then + echo >&2 'ClickHouse init process failed.' + exit 1 + fi + tries=$(( tries-1 )) + sleep 1 + done + + clickhouseclient=( clickhouse-client --multiquery --host "127.0.0.1" -u "$CLICKHOUSE_USER" --password "$CLICKHOUSE_PASSWORD" ) + + echo + + # create default database, if defined + if [ -n "$CLICKHOUSE_DB" ]; then + echo "$0: create database '$CLICKHOUSE_DB'" + "${clickhouseclient[@]}" -q "CREATE DATABASE IF NOT EXISTS $CLICKHOUSE_DB"; + fi + + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + echo "$0: running $f" + "$f" + else + echo "$0: sourcing $f" + # shellcheck source=/dev/null + . "$f" + fi + ;; + *.sql) echo "$0: running $f"; "${clickhouseclient[@]}" < "$f" ; echo ;; + *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${clickhouseclient[@]}"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + if ! kill -s TERM "$pid" || ! wait "$pid"; then + echo >&2 'Finishing of ClickHouse init process failed.' + exit 1 + fi + fi +else + echo "ClickHouse Database directory appears to contain a database; Skipping initialization" +fi + +# if no args passed to `docker run` or first argument start with `--`, then the user is passing clickhouse-server arguments +if [[ $# -lt 1 ]] || [[ "$1" == "--"* ]]; then + # Watchdog is launched by default, but does not send SIGINT to the main process, + # so the container can't be finished by ctrl+c + CLICKHOUSE_WATCHDOG_ENABLE=${CLICKHOUSE_WATCHDOG_ENABLE:-0} + export CLICKHOUSE_WATCHDOG_ENABLE + + # An option for easy restarting and replacing clickhouse-server in a container, especially in Kubernetes. + # For example, you can replace the clickhouse-server binary to another and restart it while keeping the container running. + if [[ "${CLICKHOUSE_DOCKER_RESTART_ON_EXIT:-0}" -eq "1" ]]; then + while true; do + # This runs the server as a child process of the shell script: + /usr/bin/clickhouse su "${USER}:${GROUP}" /usr/bin/clickhouse-server --config-file="$CLICKHOUSE_CONFIG" "$@" ||: + echo >&2 'ClickHouse Server exited, and the environment variable CLICKHOUSE_DOCKER_RESTART_ON_EXIT is set to 1. Restarting the server.' + done + else + # This replaces the shell script with the server: + exec /usr/bin/clickhouse su "${USER}:${GROUP}" /usr/bin/clickhouse-server --config-file="$CLICKHOUSE_CONFIG" "$@" + fi +fi + +# Otherwise, we assume the user want to run his own process, for example a `bash` shell to explore this image +exec "$@" diff --git a/docker/clickhouse/user_defined_function.xml b/docker/clickhouse/user_defined_function.xml new file mode 100644 index 0000000000000..9617d2495ced1 --- /dev/null +++ b/docker/clickhouse/user_defined_function.xml @@ -0,0 +1,287 @@ + + + executable + aggregate_funnel + Array(Tuple(Int8, Nullable(String), Array(Float64))) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), Nullable(String), Array(Int8))) + value + + JSONEachRow + aggregate_funnel.py + + + + executable + aggregate_funnel_cohort + Array(Tuple(Int8, UInt64, Array(Float64))) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, Array(Int8))) + value + + JSONEachRow + aggregate_funnel_cohort.py + + + + executable + aggregate_funnel_array + Array(Tuple(Int8, Array(String), Array(Float64))) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), Array(String), Array(Int8))) + value + + JSONEachRow + aggregate_funnel_array.py + + + + executable + aggregate_funnel_test + String + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), Nullable(String), Array(Int8))) + value + + JSONEachRow + aggregate_funnel_test.py + + + + executable + aggregate_funnel_trends + Array(Tuple(DateTime, Int8, Nullable(String))) + result + + UInt8 + from_step + + + UInt8 + num_steps + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), Nullable(DateTime), Nullable(String), Array(Int8))) + value + + JSONEachRow + aggregate_funnel_trends.py + + + + executable + aggregate_funnel_array_trends + + Array(Tuple(DateTime, Int8, Array(String))) + result + + UInt8 + from_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), Nullable(DateTime), Array(String), Array(Int8))) + value + + JSONEachRow + aggregate_funnel_array_trends.py + + + + executable + aggregate_funnel_cohort_trends + + Array(Tuple(DateTime, Int8, UInt64)) + result + + UInt8 + from_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Tuple(Nullable(Float64), Nullable(DateTime), UInt64, Array(Int8))) + value + + JSONEachRow + aggregate_funnel_cohort_trends.py + + + + executable + aggregate_funnel_array_trends_test + String + result + + UInt8 + from_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), Nullable(DateTime), Array(String), Array(Int8))) + value + + JSONEachRow + aggregate_funnel_array_trends_test.py + + \ No newline at end of file diff --git a/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown--dark.png b/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown--dark.png index 8b41666303c28e0ea47af8656e6bbe39724d70ef..79db1daa2edf6ee2e720177631055a63edd38fe3 100644 GIT binary patch literal 96992 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 z%0A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%0A} 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 z62$an�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 diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index 2a8b466400bdb..02761a7532378 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -205,6 +205,7 @@ export const FEATURE_FLAGS = { MULTIPLE_BREAKDOWNS: 'multiple-breakdowns', // owner: @skoob13 #team-product-analytics WEB_ANALYTICS_LIVE_USER_COUNT: 'web-analytics-live-user-count', // owner: @robbie-c SETTINGS_SESSION_TABLE_VERSION: 'settings-session-table-version', // owner: @robbie-c + INSIGHT_FUNNELS_USE_UDF: 'insight-funnels-use-udf', // owner: @aspicer #team-product-analytics FIRST_TIME_FOR_USER_MATH: 'first-time-for-user-math', // owner: @skoob13 #team-product-analytics MULTITAB_EDITOR: 'multitab-editor', // owner: @EDsCODE #team-data-warehouse WEB_ANALYTICS_REPLAY: 'web-analytics-replay', // owner: @robbie-c diff --git a/frontend/src/queries/schema.json b/frontend/src/queries/schema.json index 09bcdf2f44af1..90be24bd22c33 100644 --- a/frontend/src/queries/schema.json +++ b/frontend/src/queries/schema.json @@ -1235,6 +1235,9 @@ "description": "Generated HogQL query.", "type": "string" }, + "isUdf": { + "type": "boolean" + }, "is_cached": { "type": "boolean" }, @@ -4938,6 +4941,9 @@ "layout": { "$ref": "#/definitions/FunnelLayout", "default": "vertical" + }, + "useUdf": { + "type": "boolean" } }, "type": "object" @@ -5084,6 +5090,9 @@ "description": "Generated HogQL query.", "type": "string" }, + "isUdf": { + "type": "boolean" + }, "modifiers": { "$ref": "#/definitions/HogQLQueryModifiers", "description": "Modifiers used when performing the query" @@ -8307,6 +8316,9 @@ "description": "Generated HogQL query.", "type": "string" }, + "isUdf": { + "type": "boolean" + }, "modifiers": { "$ref": "#/definitions/HogQLQueryModifiers", "description": "Modifiers used when performing the query" diff --git a/frontend/src/queries/schema.ts b/frontend/src/queries/schema.ts index 66439691f7a80..7cb850d06cb7f 100644 --- a/frontend/src/queries/schema.ts +++ b/frontend/src/queries/schema.ts @@ -947,6 +947,7 @@ export type FunnelsFilter = { hiddenLegendBreakdowns?: string[] /** @default total */ funnelStepReference?: FunnelsFilterLegacy['funnel_step_reference'] + useUdf?: boolean } export interface FunnelsQuery extends InsightsQueryBase { @@ -973,7 +974,9 @@ export type FunnelTrendsResults = Record[] export interface FunnelsQueryResponse extends AnalyticsQueryResponseBase< FunnelStepsResults | FunnelStepsBreakdownResults | FunnelTimeToConvertResults | FunnelTrendsResults - > {} + > { + isUdf?: boolean +} export type CachedFunnelsQueryResponse = CachedQueryResponse diff --git a/posthog/hogql/constants.py b/posthog/hogql/constants.py index 557cbfd05c01e..5e64111632997 100644 --- a/posthog/hogql/constants.py +++ b/posthog/hogql/constants.py @@ -92,6 +92,8 @@ def get_breakdown_limit_for_context(limit_context: LimitContext) -> int: class HogQLQuerySettings(BaseModel): model_config = ConfigDict(extra="forbid") optimize_aggregation_in_order: Optional[bool] = None + date_time_output_format: Optional[str] = None + date_time_input_format: Optional[str] = None # Settings applied on top of all HogQL queries. diff --git a/posthog/hogql/functions/mapping.py b/posthog/hogql/functions/mapping.py index 232e99e7a064e..586eed0c4a274 100644 --- a/posthog/hogql/functions/mapping.py +++ b/posthog/hogql/functions/mapping.py @@ -470,6 +470,7 @@ def compare_types(arg_types: list[ConstantType], sig_arg_types: tuple[ConstantTy "timeStampSub": HogQLFunctionMeta("timeStampSub", 2, 2), "now": HogQLFunctionMeta("now64", 0, 1, tz_aware=True, case_sensitive=False), "nowInBlock": HogQLFunctionMeta("nowInBlock", 1, 1), + "rowNumberInBlock": HogQLFunctionMeta("rowNumberInBlock", 0, 0), "rowNumberInAllBlocks": HogQLFunctionMeta("rowNumberInAllBlocks", 0, 0), "today": HogQLFunctionMeta("today"), "yesterday": HogQLFunctionMeta("yesterday"), @@ -833,6 +834,14 @@ def compare_types(arg_types: list[ConstantType], sig_arg_types: tuple[ConstantTy "leadInFrame": HogQLFunctionMeta("leadInFrame", 1, 1), # table functions "generateSeries": HogQLFunctionMeta("generate_series", 3, 3), + ## UDFS + "aggregate_funnel": HogQLFunctionMeta("aggregate_funnel", 6, 6, aggregate=False), + "aggregate_funnel_array": HogQLFunctionMeta("aggregate_funnel_array", 6, 6, aggregate=False), + "aggregate_funnel_cohort": HogQLFunctionMeta("aggregate_funnel_cohort", 6, 6, aggregate=False), + "aggregate_funnel_trends": HogQLFunctionMeta("aggregate_funnel_trends", 7, 7, aggregate=False), + "aggregate_funnel_array_trends": HogQLFunctionMeta("aggregate_funnel_array_trends", 7, 7, aggregate=False), + "aggregate_funnel_cohort_trends": HogQLFunctionMeta("aggregate_funnel_cohort_trends", 7, 7, aggregate=False), + "aggregate_funnel_test": HogQLFunctionMeta("aggregate_funnel_test", 6, 6, aggregate=False), } # Permitted HogQL aggregations HOGQL_AGGREGATIONS: dict[str, HogQLFunctionMeta] = { @@ -884,7 +893,7 @@ def compare_types(arg_types: list[ConstantType], sig_arg_types: tuple[ConstantTy # "topKWeighted": HogQLFunctionMeta("topKWeighted", 1, 1, aggregate=True), # "topKWeightedIf": HogQLFunctionMeta("topKWeightedIf", 2, 2, aggregate=True), "groupArray": HogQLFunctionMeta("groupArray", 1, 1, aggregate=True), - # "groupArrayIf": HogQLFunctionMeta("groupArrayIf", 2, 2, aggregate=True), + "groupArrayIf": HogQLFunctionMeta("groupArrayIf", 2, 2, aggregate=True), # "groupArrayLast": HogQLFunctionMeta("groupArrayLast", 1, 1, aggregate=True), # "groupArrayLastIf": HogQLFunctionMeta("groupArrayLastIf", 2, 2, aggregate=True), "groupUniqArray": HogQLFunctionMeta("groupUniqArray", 1, 1, aggregate=True), diff --git a/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr b/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr index 369f18ab9d118..66203f817267f 100644 --- a/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr +++ b/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr @@ -31,7 +31,7 @@ FROM events LEFT JOIN ( SELECT person_static_cohort.person_id AS cohort_person_id, 1 AS matched, person_static_cohort.cohort_id AS cohort_id FROM person_static_cohort - WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [2]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) + WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [13]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) WHERE and(equals(events.team_id, 420), 1, ifNull(equals(__in_cohort.matched, 1), 0)) LIMIT 100 SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1, format_csv_allow_double_quotes=0, max_ast_elements=4000000, max_expanded_ast_elements=4000000, max_bytes_before_external_group_by=0 @@ -42,7 +42,7 @@ FROM events LEFT JOIN ( SELECT person_id AS cohort_person_id, 1 AS matched, cohort_id FROM static_cohort_people - WHERE in(cohort_id, [2])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) + WHERE in(cohort_id, [13])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) WHERE and(1, equals(__in_cohort.matched, 1)) LIMIT 100 ''' @@ -55,7 +55,7 @@ FROM events LEFT JOIN ( SELECT person_static_cohort.person_id AS cohort_person_id, 1 AS matched, person_static_cohort.cohort_id AS cohort_id FROM person_static_cohort - WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [3]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) + WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [14]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) WHERE and(equals(events.team_id, 420), 1, ifNull(equals(__in_cohort.matched, 1), 0)) LIMIT 100 SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1, format_csv_allow_double_quotes=0, max_ast_elements=4000000, max_expanded_ast_elements=4000000, max_bytes_before_external_group_by=0 @@ -66,7 +66,7 @@ FROM events LEFT JOIN ( SELECT person_id AS cohort_person_id, 1 AS matched, cohort_id FROM static_cohort_people - WHERE in(cohort_id, [3])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) + WHERE in(cohort_id, [14])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) WHERE and(1, equals(__in_cohort.matched, 1)) LIMIT 100 ''' diff --git a/posthog/hogql_queries/insights/funnels/__init__.py b/posthog/hogql_queries/insights/funnels/__init__.py index 8a20d9784df8b..787cd01ec887d 100644 --- a/posthog/hogql_queries/insights/funnels/__init__.py +++ b/posthog/hogql_queries/insights/funnels/__init__.py @@ -1,5 +1,6 @@ from .base import FunnelBase from .funnel import Funnel +from .funnel_udf import FunnelUDF from .funnel_strict import FunnelStrict from .funnel_unordered import FunnelUnordered from .funnel_time_to_convert import FunnelTimeToConvert diff --git a/posthog/hogql_queries/insights/funnels/base.py b/posthog/hogql_queries/insights/funnels/base.py index 84ddf66eafccd..d5757225246f4 100644 --- a/posthog/hogql_queries/insights/funnels/base.py +++ b/posthog/hogql_queries/insights/funnels/base.py @@ -33,6 +33,7 @@ FunnelExclusionActionsNode, FunnelTimeToConvertResults, FunnelVizType, + FunnelExclusionEventsNode, ) from posthog.types import EntityNode, ExclusionEntityNode @@ -410,6 +411,92 @@ def _get_inner_event_query( return funnel_events_query + # This version of the inner event query modifies how exclusions are returned to + # make them behave more like steps. It returns a boolean "exclusion_{0..n}" for each event + def _get_inner_event_query_for_udf( + self, + entities: list[EntityNode] | None = None, + entity_name="events", + skip_entity_filter=False, + skip_step_filter=False, + ) -> ast.SelectQuery: + query, funnelsFilter, breakdown, breakdownType, breakdownAttributionType = ( + self.context.query, + self.context.funnelsFilter, + self.context.breakdown, + self.context.breakdownType, + self.context.breakdownAttributionType, + ) + entities_to_use = entities or query.series + + extra_fields: list[str] = [] + + for prop in self.context.includeProperties: + extra_fields.append(prop) + + funnel_events_query = FunnelEventQuery( + context=self.context, + extra_fields=[*self._extra_event_fields, *extra_fields], + extra_event_properties=self._extra_event_properties, + ).to_query( + skip_entity_filter=skip_entity_filter, + ) + # funnel_events_query, params = FunnelEventQuery( + # extra_fields=[*self._extra_event_fields, *extra_fields], + # extra_event_properties=self._extra_event_properties, + # ).get_query(entities_to_use, entity_name, skip_entity_filter=skip_entity_filter) + + all_step_cols: list[ast.Expr] = [] + all_exclusions: list[list[FunnelExclusionEventsNode | FunnelExclusionActionsNode]] = [] + for index, entity in enumerate(entities_to_use): + step_cols = self._get_step_col(entity, index, entity_name) + all_step_cols.extend(step_cols) + all_exclusions.append([]) + + for excluded_entity in funnelsFilter.exclusions or []: + for i in range(excluded_entity.funnelFromStep + 1, excluded_entity.funnelToStep + 1): + all_exclusions[i].append(excluded_entity) + + for index, exclusions in enumerate(all_exclusions): + exclusion_col_expr = self._get_exclusions_col(exclusions, index, entity_name) + all_step_cols.append(exclusion_col_expr) + + breakdown_select_prop = self._get_breakdown_select_prop() + + if breakdown_select_prop: + all_step_cols.extend(breakdown_select_prop) + + funnel_events_query.select = [*funnel_events_query.select, *all_step_cols] + + if breakdown and breakdownType == BreakdownType.COHORT: + assert funnel_events_query.select_from is not None + funnel_events_query.select_from.next_join = self._get_cohort_breakdown_join() + + if not skip_step_filter: + assert isinstance(funnel_events_query.where, ast.Expr) + steps_conditions = self._get_steps_conditions_for_udf(all_exclusions, length=len(entities_to_use)) + funnel_events_query.where = ast.And(exprs=[funnel_events_query.where, steps_conditions]) + + if breakdown and breakdownAttributionType != BreakdownAttributionType.ALL_EVENTS: + # ALL_EVENTS attribution is the old default, which doesn't need the subquery + return self._add_breakdown_attribution_subquery(funnel_events_query) + + return funnel_events_query + + def _get_exclusions_col( + self, + exclusions: list[ExclusionEntityNode], + index: int, + entity_name: str, + ) -> ast.Expr: + if not exclusions: + return parse_expr(f"0 as exclusion_{index}") + + conditions = [self._build_step_query(exclusion, index, entity_name, "") for exclusion in exclusions] + return parse_expr( + f"if({{condition}}, 1, 0) as exclusion_{index}", placeholders={"condition": ast.Or(exprs=conditions)} + ) + def _get_cohort_breakdown_join(self) -> ast.JoinExpr: breakdown = self.context.breakdown @@ -547,12 +634,23 @@ def _get_steps_conditions(self, length: int) -> ast.Expr: return ast.Or(exprs=step_conditions) + def _get_steps_conditions_for_udf(self, exclusions, length: int) -> ast.Expr: + step_conditions: list[ast.Expr] = [] + + for index in range(length): + step_conditions.append(parse_expr(f"step_{index} = 1")) + if exclusions[index]: + step_conditions.append(parse_expr(f"exclusion_{index} = 1")) + + return ast.Or(exprs=step_conditions) + def _get_step_col( self, entity: EntityNode | ExclusionEntityNode, index: int, entity_name: str, step_prefix: str = "", + for_udf: bool = False, ) -> list[ast.Expr]: # step prefix is used to distinguish actual steps, and exclusion steps # without the prefix, we get the same parameter binding for both, which borks things up @@ -561,9 +659,10 @@ def _get_step_col( step_cols.append( parse_expr(f"if({{condition}}, 1, 0) as {step_prefix}step_{index}", placeholders={"condition": condition}) ) - step_cols.append( - parse_expr(f"if({step_prefix}step_{index} = 1, timestamp, null) as {step_prefix}latest_{index}") - ) + if not for_udf: + step_cols.append( + parse_expr(f"if({step_prefix}step_{index} = 1, timestamp, null) as {step_prefix}latest_{index}") + ) for field in self.extra_event_fields_and_properties: step_cols.append( diff --git a/posthog/hogql_queries/insights/funnels/funnel_query_context.py b/posthog/hogql_queries/insights/funnels/funnel_query_context.py index 8c280e272dbe3..ef6cf57af9563 100644 --- a/posthog/hogql_queries/insights/funnels/funnel_query_context.py +++ b/posthog/hogql_queries/insights/funnels/funnel_query_context.py @@ -2,7 +2,6 @@ from posthog.hogql.constants import LimitContext from posthog.hogql.timings import HogQLTimings from posthog.hogql_queries.insights.query_context import QueryContext -from posthog.models.filters.mixins.utils import cached_property from posthog.models.property.util import box_value from posthog.models.team.team import Team from posthog.schema import ( @@ -39,6 +38,8 @@ class FunnelQueryContext(QueryContext): includeProperties: list[str] includeFinalMatchingEvents: Optional[bool] + max_steps_override: int | None = None + def __init__( self, query: FunnelsQuery, @@ -105,6 +106,8 @@ def __init__( self.actorsQuery = None - @cached_property + @property def max_steps(self) -> int: + if self.max_steps_override is not None: + return self.max_steps_override return len(self.query.series) diff --git a/posthog/hogql_queries/insights/funnels/funnel_time_to_convert.py b/posthog/hogql_queries/insights/funnels/funnel_time_to_convert.py index 38600dcc1fec6..5c28697b6edab 100644 --- a/posthog/hogql_queries/insights/funnels/funnel_time_to_convert.py +++ b/posthog/hogql_queries/insights/funnels/funnel_time_to_convert.py @@ -16,7 +16,8 @@ def __init__( ): super().__init__(context) - self.funnel_order = get_funnel_order_class(self.context.funnelsFilter)(context=self.context) + # Haven't implemented calls for time_to_convert in UDF yet + self.funnel_order = get_funnel_order_class(self.context.funnelsFilter, use_udf=False)(context=self.context) def _format_results(self, results: list) -> FunnelTimeToConvertResults: return FunnelTimeToConvertResults( diff --git a/posthog/hogql_queries/insights/funnels/funnel_trends.py b/posthog/hogql_queries/insights/funnels/funnel_trends.py index ad7a67d1207d6..8bdab281147a9 100644 --- a/posthog/hogql_queries/insights/funnels/funnel_trends.py +++ b/posthog/hogql_queries/insights/funnels/funnel_trends.py @@ -120,16 +120,15 @@ def _format_single_summary(self, summary): labels.append(timestamp.strftime(HUMAN_READABLE_TIMESTAMP_FORMAT)) return {"count": count, "data": data, "days": days, "labels": labels} - def get_query(self) -> ast.SelectQuery: - team, interval, query, now = self.context.team, self.context.interval, self.context.query, self.context.now - - date_range = QueryDateRange( - date_range=query.dateRange, - team=team, - interval=query.interval, - now=now, + def _date_range(self): + return QueryDateRange( + date_range=self.context.query.dateRange, + team=self.context.team, + interval=self.context.query.interval, + now=self.context.now, ) + def get_query(self) -> ast.SelectQuery: step_counts = self.get_step_counts_without_aggregation_query() # Expects multiple rows for same person, first event time, steps taken. @@ -138,12 +137,6 @@ def get_query(self) -> ast.SelectQuery: reached_to_step_count_condition, _, ) = self.get_steps_reached_conditions() - interval_func = get_interval_func_ch(interval.value) - - if date_range.date_from() is None: - _date_from = get_earliest_timestamp(team.pk) - else: - _date_from = date_range.date_from() breakdown_clause = self._get_breakdown_prop_expr() @@ -154,52 +147,12 @@ def get_query(self) -> ast.SelectQuery: *breakdown_clause, ] - formatted_date_from = (_date_from.strftime("%Y-%m-%d %H:%M:%S"),) - formatted_date_to = (date_range.date_to().strftime("%Y-%m-%d %H:%M:%S"),) - date_from_as_hogql = ast.Call( - name="assumeNotNull", - args=[ast.Call(name="toDateTime", args=[(ast.Constant(value=formatted_date_from))])], - ) - date_to_as_hogql = ast.Call( - name="assumeNotNull", - args=[ast.Call(name="toDateTime", args=[(ast.Constant(value=formatted_date_to))])], - ) data_select_from = ast.JoinExpr(table=step_counts) data_group_by: list[ast.Expr] = [ast.Field(chain=["entrance_period_start"]), *breakdown_clause] data_query = ast.SelectQuery(select=data_select, select_from=data_select_from, group_by=data_group_by) - fill_select: list[ast.Expr] = [ - ast.Alias( - alias="entrance_period_start", - expr=ast.ArithmeticOperation( - left=get_start_of_interval_hogql(interval.value, team=team, source=date_from_as_hogql), - right=ast.Call(name=interval_func, args=[ast.Field(chain=["number"])]), - op=ast.ArithmeticOperationOp.Add, - ), - ), - ] - fill_select_from = ast.JoinExpr( - table=ast.Field(chain=["numbers"]), - table_args=[ - ast.ArithmeticOperation( - left=ast.Call( - name="dateDiff", - args=[ - ast.Constant(value=interval.value), - get_start_of_interval_hogql(interval.value, team=team, source=date_from_as_hogql), - get_start_of_interval_hogql(interval.value, team=team, source=date_to_as_hogql), - ], - ), - right=ast.Constant(value=1), - op=ast.ArithmeticOperationOp.Add, - ) - ], - alias="period_offsets", - ) - fill_query = ast.SelectQuery( - select=fill_select, - select_from=fill_select_from, - ) + fill_query = self._get_fill_query() + fill_join = ast.JoinExpr( table=data_query, alias="data", @@ -254,7 +207,7 @@ def get_query(self) -> ast.SelectQuery: ) breakdown_limit = self.get_breakdown_limit() if breakdown_limit: - limit = min(breakdown_limit * len(date_range.all_values()), limit) + limit = min(breakdown_limit * len(self._date_range().all_values()), limit) else: select = [ ast.Field(chain=["fill", "entrance_period_start"]), @@ -276,6 +229,63 @@ def get_query(self) -> ast.SelectQuery: limit=ast.Constant(value=limit), # increased limit (default 100) for hourly breakdown ) + # The fill query returns all the start_interval dates in the response + def _get_fill_query(self) -> ast.SelectQuery: + team, interval = self.context.team, self.context.interval + + date_range = self._date_range() + + if date_range.date_from() is None: + _date_from = get_earliest_timestamp(team.pk) + else: + _date_from = date_range.date_from() + + formatted_date_from = (_date_from.strftime("%Y-%m-%d %H:%M:%S"),) + formatted_date_to = (date_range.date_to().strftime("%Y-%m-%d %H:%M:%S"),) + date_from_as_hogql = ast.Call( + name="assumeNotNull", + args=[ast.Call(name="toDateTime", args=[(ast.Constant(value=formatted_date_from))])], + ) + date_to_as_hogql = ast.Call( + name="assumeNotNull", + args=[ast.Call(name="toDateTime", args=[(ast.Constant(value=formatted_date_to))])], + ) + interval_func = get_interval_func_ch(interval.value) + + fill_select: list[ast.Expr] = [ + ast.Alias( + alias="entrance_period_start", + expr=ast.ArithmeticOperation( + left=get_start_of_interval_hogql(interval.value, team=team, source=date_from_as_hogql), + right=ast.Call(name=interval_func, args=[ast.Field(chain=["number"])]), + op=ast.ArithmeticOperationOp.Add, + ), + ), + ] + fill_select_from = ast.JoinExpr( + table=ast.Field(chain=["numbers"]), + table_args=[ + ast.ArithmeticOperation( + left=ast.Call( + name="dateDiff", + args=[ + ast.Constant(value=interval.value), + get_start_of_interval_hogql(interval.value, team=team, source=date_from_as_hogql), + get_start_of_interval_hogql(interval.value, team=team, source=date_to_as_hogql), + ], + ), + right=ast.Constant(value=1), + op=ast.ArithmeticOperationOp.Add, + ) + ], + alias="period_offsets", + ) + fill_query = ast.SelectQuery( + select=fill_select, + select_from=fill_select_from, + ) + return fill_query + def get_step_counts_without_aggregation_query( self, *, specific_entrance_period_start: Optional[datetime] = None ) -> ast.SelectQuery: diff --git a/posthog/hogql_queries/insights/funnels/funnel_trends_udf.py b/posthog/hogql_queries/insights/funnels/funnel_trends_udf.py new file mode 100644 index 0000000000000..2f928e014daf4 --- /dev/null +++ b/posthog/hogql_queries/insights/funnels/funnel_trends_udf.py @@ -0,0 +1,163 @@ +from typing import cast + +from posthog.hogql import ast +from posthog.hogql.constants import HogQLQuerySettings +from posthog.hogql.parser import parse_select +from posthog.hogql_queries.insights.funnels import FunnelTrends +from posthog.hogql_queries.insights.utils.utils import get_start_of_interval_hogql_str +from posthog.schema import BreakdownType, BreakdownAttributionType +from posthog.utils import DATERANGE_MAP + +TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S" +HUMAN_READABLE_TIMESTAMP_FORMAT = "%-d-%b-%Y" + + +class FunnelTrendsUDF(FunnelTrends): + def get_step_counts_query(self): + max_steps = self.context.max_steps + return self._get_step_counts_query( + outer_select=[ + *self._get_matching_event_arrays(max_steps), + ], + inner_select=[ + *self._get_matching_events(max_steps), + ], + ) + + def conversion_window_limit(self) -> int: + return int( + self.context.funnelWindowInterval * DATERANGE_MAP[self.context.funnelWindowIntervalUnit].total_seconds() + ) + + def get_query(self) -> ast.SelectQuery: + # If they're asking for a "to_step" just truncate the funnel + funnelsFilter = self.context.funnelsFilter + max_steps = self.context.max_steps if funnelsFilter.funnelToStep is None else funnelsFilter.funnelToStep + 1 + self.context.max_steps_override = max_steps + + if self.context.funnelsFilter.funnelOrderType == "strict": + inner_event_query = self._get_inner_event_query_for_udf( + entity_name="events", skip_step_filter=True, skip_entity_filter=True + ) + else: + inner_event_query = self._get_inner_event_query_for_udf(entity_name="events") + + default_breakdown_selector = "[]" if self._query_has_array_breakdown() else "''" + + # stores the steps as an array of integers from 1 to max_steps + # so if the event could be step_0, step_1 or step_4, it looks like [1,2,0,0,5] + + # Each event is going to be a set of steps or it's going to be a set of exclusions. It can't be both. + steps = ",".join([f"{i + 1} * step_{i}" for i in range(self.context.max_steps)]) + + # this will error if they put in a bad exclusion + exclusions = "" + if getattr(self.context.funnelsFilter, "exclusions", None): + exclusions = "".join([f",-{i + 1} * exclusion_{i}" for i in range(1, self.context.max_steps)]) + + # Todo: Make this work for breakdowns + if self.context.breakdownType == BreakdownType.COHORT: + fn = "aggregate_funnel_cohort_trends" + breakdown_prop = ", prop" + elif self._query_has_array_breakdown(): + fn = "aggregate_funnel_array_trends" + breakdown_prop = "" + else: + fn = "aggregate_funnel_trends" + breakdown_prop = "" + + prop_selector = "prop" if self.context.breakdown else default_breakdown_selector + prop_vals = "groupUniqArray(prop)" if self.context.breakdown else f"[{default_breakdown_selector}]" + + breakdown_attribution_string = f"{self.context.breakdownAttributionType}{f'_{self.context.funnelsFilter.breakdownAttributionValue}' if self.context.breakdownAttributionType == BreakdownAttributionType.STEP else ''}" + + from_step = funnelsFilter.funnelFromStep or 0 + + inner_select = cast( + ast.SelectQuery, + parse_select( + f""" + SELECT + arrayJoin({fn}( + {from_step}, + {max_steps}, + {self.conversion_window_limit()}, + '{breakdown_attribution_string}', + '{self.context.funnelsFilter.funnelOrderType}', + {prop_vals}, + arraySort(t -> t.1, groupArray(tuple(toFloat(timestamp), {get_start_of_interval_hogql_str(self.context.interval.value, team=self.context.team, source='timestamp')}, {prop_selector}, arrayFilter((x) -> x != 0, [{steps}{exclusions}])))) + )) as af_tuple, + toTimeZone(af_tuple.1, '{self.context.team.timezone}') as entrance_period_start, + af_tuple.2 as success_bool, + af_tuple.3 as breakdown + FROM {{inner_event_query}} + GROUP BY aggregation_target{breakdown_prop} + """, + {"inner_event_query": inner_event_query}, + ), + ) + # This is necessary so clickhouse doesn't truncate timezone information when passing datetimes to and from python + inner_select.settings = HogQLQuerySettings(date_time_output_format="iso", date_time_input_format="best_effort") + + conversion_rate_expr = ( + "if(reached_from_step_count > 0, round(reached_to_step_count / reached_from_step_count * 100, 2), 0)" + ) + + fill_query = self._get_fill_query() + + limit = 1_000 + if self.context.breakdown: + breakdown_limit = self.get_breakdown_limit() + if breakdown_limit: + limit = min(breakdown_limit * len(self._date_range().all_values()), limit) + + s = parse_select( + f""" + SELECT + fill.entrance_period_start AS entrance_period_start, + sumIf(data.reached_from_step_count, ifNull(equals(fill.entrance_period_start, data.entrance_period_start), isNull(fill.entrance_period_start) and isNull(data.entrance_period_start))) AS reached_from_step_count, + sumIf(data.reached_to_step_count, ifNull(equals(fill.entrance_period_start, data.entrance_period_start), isNull(fill.entrance_period_start) and isNull(data.entrance_period_start))) AS reached_to_step_count, + if(ifNull(greater(reached_from_step_count, 0), 0), round(multiply(divide(reached_to_step_count, reached_from_step_count), 100), 2), 0) AS conversion_rate, + data.prop AS prop + FROM + ({{fill_query}}) as fill + CROSS JOIN (SELECT + entrance_period_start as entrance_period_start, + countIf(success_bool != 0) as reached_from_step_count, + countIf(success_bool = 1) as reached_to_step_count, + breakdown as prop + FROM + ({{inner_select}}) + GROUP BY entrance_period_start, breakdown) as data + GROUP BY + fill.entrance_period_start, + data.prop + ORDER BY + sum(reached_from_step_count) OVER (PARTITION BY data.prop) DESC, + data.prop DESC, + fill.entrance_period_start ASC + LIMIT {limit} + """, + {"fill_query": fill_query, "inner_select": inner_select}, + ) + else: + s = parse_select( + f""" + SELECT + fill.entrance_period_start as entrance_period_start, + countIf(success_bool != 0) as reached_from_step_count, + countIf(success_bool = 1) as reached_to_step_count, + {conversion_rate_expr} as conversion_rate, + breakdown as prop + FROM + ({{inner_select}}) as data + RIGHT OUTER JOIN + ({{fill_query}}) as fill + ON data.entrance_period_start = fill.entrance_period_start + GROUP BY entrance_period_start, data.breakdown + ORDER BY entrance_period_start + LIMIT {limit} + """, + {"fill_query": fill_query, "inner_select": inner_select}, + ) + return cast(ast.SelectQuery, s) diff --git a/posthog/hogql_queries/insights/funnels/funnel_udf.py b/posthog/hogql_queries/insights/funnels/funnel_udf.py new file mode 100644 index 0000000000000..7ec91374dcdee --- /dev/null +++ b/posthog/hogql_queries/insights/funnels/funnel_udf.py @@ -0,0 +1,184 @@ +from typing import cast + +from posthog.hogql import ast +from posthog.hogql.parser import parse_select +from posthog.hogql_queries.insights.funnels.base import FunnelBase +from posthog.schema import BreakdownType, BreakdownAttributionType +from posthog.utils import DATERANGE_MAP + +TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S" +HUMAN_READABLE_TIMESTAMP_FORMAT = "%-d-%b-%Y" + + +class FunnelUDF(FunnelBase): + def get_step_counts_query(self): + max_steps = self.context.max_steps + return self._get_step_counts_query( + outer_select=[ + *self._get_matching_event_arrays(max_steps), + ], + inner_select=[ + *self._get_matching_events(max_steps), + ], + ) + + def conversion_window_limit(self) -> int: + return int( + self.context.funnelWindowInterval * DATERANGE_MAP[self.context.funnelWindowIntervalUnit].total_seconds() + ) + + def get_query(self) -> ast.SelectQuery: + if self.context.funnelsFilter.funnelOrderType == "strict": + inner_event_query = self._get_inner_event_query_for_udf( + entity_name="events", skip_step_filter=True, skip_entity_filter=True + ) + else: + inner_event_query = self._get_inner_event_query_for_udf(entity_name="events") + + default_breakdown_selector = "[]" if self._query_has_array_breakdown() else "''" + + # stores the steps as an array of integers from 1 to max_steps + # so if the event could be step_0, step_1 or step_4, it looks like [1,2,0,0,5] + + # Each event is going to be a set of steps or it's going to be a set of exclusions. It can't be both. + steps = ",".join([f"{i + 1} * step_{i}" for i in range(self.context.max_steps)]) + + # this will error if they put in a bad exclusion + exclusions = "" + if getattr(self.context.funnelsFilter, "exclusions", None): + exclusions = "".join([f",-{i + 1} * exclusion_{i}" for i in range(1, self.context.max_steps)]) + + if self.context.breakdownType == BreakdownType.COHORT: + fn = "aggregate_funnel_cohort" + breakdown_prop = ", prop" + elif self._query_has_array_breakdown(): + fn = "aggregate_funnel_array" + breakdown_prop = "" + else: + fn = "aggregate_funnel" + breakdown_prop = "" + + prop_selector = "prop" if self.context.breakdown else default_breakdown_selector + prop_vals = "groupUniqArray(prop)" if self.context.breakdown else f"[{default_breakdown_selector}]" + + breakdown_attribution_string = f"{self.context.breakdownAttributionType}{f'_{self.context.funnelsFilter.breakdownAttributionValue}' if self.context.breakdownAttributionType == BreakdownAttributionType.STEP else ''}" + + # test + ''' + inner_select = parse_select( + f""" + SELECT + arrayJoin({fn}( + {self.context.max_steps}, + {self.conversion_window_limit()}, + '{breakdown_attribution_string}', + '{self.context.funnelsFilter.funnelOrderType}', + {prop_vals}, + arraySort(t -> t.1, groupArray(tuple(toFloat(timestamp), {prop_selector}, arrayFilter((x) -> x != 0, [{steps}{exclusions}])))) + )) as af_tuple, + af_tuple.1 as af, + af_tuple.2 as breakdown, + af_tuple.3 as timings + FROM {{inner_event_query}} + GROUP BY aggregation_target{breakdown_prop} + HAVING af >= 0 + """, + {"inner_event_query": inner_event_query}, + ) + return inner_select + ''' + + inner_select = parse_select( + f""" + SELECT + arrayJoin({fn}( + {self.context.max_steps}, + {self.conversion_window_limit()}, + '{breakdown_attribution_string}', + '{self.context.funnelsFilter.funnelOrderType}', + {prop_vals}, + arraySort(t -> t.1, groupArray(tuple(toFloat(timestamp), {prop_selector}, arrayFilter((x) -> x != 0, [{steps}{exclusions}])))) + )) as af_tuple, + af_tuple.1 as af, + af_tuple.2 as breakdown, + af_tuple.3 as timings + FROM {{inner_event_query}} + GROUP BY aggregation_target{breakdown_prop} + HAVING af >= 0 + """, + {"inner_event_query": inner_event_query}, + ) + + step_results = ",".join( + [f"countIf(ifNull(equals(af, {i}), 0)) AS step_{i+1}" for i in range(self.context.max_steps)] + ) + step_results2 = ",".join([f"sum(step_{i+1}) AS step_{i+1}" for i in range(self.context.max_steps)]) + + conversion_time_arrays = ",".join( + [ + f"groupArrayIf(timings[{i}], timings[{i}] > 0) AS step_{i}_conversion_times" + for i in range(1, self.context.max_steps) + ] + ) + + order_by = ",".join([f"step_{i+1} DESC" for i in reversed(range(self.context.max_steps))]) + + other_aggregation = "['Other']" if self._query_has_array_breakdown() else "'Other'" + + use_breakdown_limit = self.context.breakdown and self.context.breakdownType in [ + BreakdownType.PERSON, + BreakdownType.EVENT, + BreakdownType.GROUP, + ] + + final_prop = ( + f"if(row_number < {self.get_breakdown_limit()}, breakdown, {other_aggregation})" + if use_breakdown_limit + else "breakdown" + ) + + s = parse_select( + f""" + SELECT + {step_results}, + {conversion_time_arrays}, + rowNumberInBlock() as row_number, + {final_prop} as final_prop + FROM + {{inner_select}} + GROUP BY breakdown + ORDER BY {order_by} + """, + {"inner_select": inner_select}, + ) + + mean_conversion_times = ",".join( + [ + f"arrayMap(x -> if(isNaN(x), NULL, x), [avgArray(step_{i}_conversion_times)])[1] AS step_{i}_average_conversion_time" + for i in range(1, self.context.max_steps) + ] + ) + median_conversion_times = ",".join( + [ + f"arrayMap(x -> if(isNaN(x), NULL, x), [medianArray(step_{i}_conversion_times)])[1] AS step_{i}_median_conversion_time" + for i in range(1, self.context.max_steps) + ] + ) + + # Weird: unless you reference row_number in this outer block, it doesn't work correctly + s = parse_select( + f""" + SELECT + {step_results2}, + {mean_conversion_times}, + {median_conversion_times}, + groupArray(row_number) as row_number, + final_prop + FROM + {{s}} + GROUP BY final_prop + """, + {"s": s}, + ) + + return cast(ast.SelectQuery, s) diff --git a/posthog/hogql_queries/insights/funnels/funnels_query_runner.py b/posthog/hogql_queries/insights/funnels/funnels_query_runner.py index 08c64720a4f9d..ca10680f9f6a1 100644 --- a/posthog/hogql_queries/insights/funnels/funnels_query_runner.py +++ b/posthog/hogql_queries/insights/funnels/funnels_query_runner.py @@ -17,7 +17,9 @@ from posthog.hogql_queries.insights.funnels.funnel_query_context import FunnelQueryContext from posthog.hogql_queries.insights.funnels.funnel_time_to_convert import FunnelTimeToConvert from posthog.hogql_queries.insights.funnels.funnel_trends import FunnelTrends +from posthog.hogql_queries.insights.funnels.funnel_trends_udf import FunnelTrendsUDF from posthog.hogql_queries.insights.funnels.utils import get_funnel_actor_class, get_funnel_order_class +from posthog.hogql_queries.legacy_compatibility.feature_flag import insight_funnels_use_udf from posthog.hogql_queries.query_runner import QueryRunner from posthog.hogql_queries.utils.query_date_range import QueryDateRange from posthog.models import Team @@ -28,6 +30,7 @@ FunnelsQuery, FunnelsQueryResponse, HogQLQueryModifiers, + StepOrderValue, ) @@ -102,18 +105,28 @@ def calculate(self): if response.timings is not None: timings.extend(response.timings) - return FunnelsQueryResponse(results=results, timings=timings, hogql=hogql, modifiers=self.modifiers) + return FunnelsQueryResponse( + isUdf=self._use_udf, results=results, timings=timings, hogql=hogql, modifiers=self.modifiers + ) + + @cached_property + def _use_udf(self): + return self.context.funnelsFilter.useUdf or insight_funnels_use_udf(self.team) @cached_property def funnel_order_class(self): - return get_funnel_order_class(self.context.funnelsFilter)(context=self.context) + return get_funnel_order_class(self.context.funnelsFilter, use_udf=self._use_udf)(context=self.context) @cached_property def funnel_class(self): funnelVizType = self.context.funnelsFilter.funnelVizType if funnelVizType == FunnelVizType.TRENDS: - return FunnelTrends(context=self.context, **self.kwargs) + return ( + FunnelTrendsUDF(context=self.context, **self.kwargs) + if self._use_udf and self.context.funnelsFilter.funnelOrderType != StepOrderValue.UNORDERED + else FunnelTrends(context=self.context, **self.kwargs) + ) elif funnelVizType == FunnelVizType.TIME_TO_CONVERT: return FunnelTimeToConvert(context=self.context) else: diff --git a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_breakdowns_by_current_url.ambr b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_breakdowns_by_current_url.ambr deleted file mode 100644 index 142118fb7056f..0000000000000 --- a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_breakdowns_by_current_url.ambr +++ /dev/null @@ -1,213 +0,0 @@ -# serializer version: 1 -# name: TestBreakdownsByCurrentURL.test_breakdown_by_current_url - ''' - SELECT [if(empty(replaceRegexpOne(ifNull(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), ''), '[\\/?#]*$', '')), '/', replaceRegexpOne(ifNull(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), ''), '[\\/?#]*$', ''))] AS value, - count(*) AS count - FROM events AS e - INNER JOIN - (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, - person_distinct_id2.distinct_id AS distinct_id - FROM person_distinct_id2 - WHERE equals(person_distinct_id2.team_id, 2) - GROUP BY person_distinct_id2.distinct_id - HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) - WHERE and(equals(e.team_id, 2), in(e.event, tuple('terminate funnel', 'watched movie')), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-02 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-12 23:59:59.999999', 6, 'UTC'))), notEmpty(e__pdi.person_id)) - GROUP BY value - ORDER BY count DESC, value DESC - LIMIT 101 - OFFSET 0 SETTINGS readonly=2, - max_execution_time=60, - allow_experimental_object_type=1 - ''' -# --- -# name: TestBreakdownsByCurrentURL.test_breakdown_by_current_url.1 - ''' - SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, - countIf(ifNull(equals(steps, 2), 0)) AS step_2, - avg(step_1_average_conversion_time_inner) AS step_1_average_conversion_time, - median(step_1_median_conversion_time_inner) AS step_1_median_conversion_time, - prop AS prop - FROM - (SELECT aggregation_target AS aggregation_target, - steps AS steps, - prop AS prop, - avg(step_1_conversion_time) AS step_1_average_conversion_time_inner, - median(step_1_conversion_time) AS step_1_median_conversion_time_inner, - prop AS prop - FROM - (SELECT aggregation_target AS aggregation_target, - steps AS steps, - prop AS prop, - max(steps) OVER (PARTITION BY aggregation_target, - prop) AS max_steps, - step_1_conversion_time AS step_1_conversion_time, - prop AS prop - FROM - (SELECT aggregation_target AS aggregation_target, - timestamp AS timestamp, - step_0 AS step_0, - latest_0 AS latest_0, - step_1 AS step_1, - latest_1 AS latest_1, - prop AS prop, - if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(latest_0, toIntervalDay(14))), 0)), 2, 1) AS steps, - if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(latest_0, toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, - prop AS prop - FROM - (SELECT aggregation_target AS aggregation_target, - timestamp AS timestamp, - step_0 AS step_0, - latest_0 AS latest_0, - step_1 AS step_1, - min(latest_1) OVER (PARTITION BY aggregation_target, - prop - ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, - if(has([['https://example.com/home'], ['https://example.com'], ['/']], prop), prop, ['Other']) AS prop - FROM - (SELECT timestamp AS timestamp, - aggregation_target AS aggregation_target, - step_0 AS step_0, - latest_0 AS latest_0, - step_1 AS step_1, - latest_1 AS latest_1, - prop_basic AS prop_basic, - prop, - prop_vals AS prop_vals, - if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['']) AS prop - FROM - (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, - e__pdi.person_id AS aggregation_target, - if(equals(e.event, 'watched movie'), 1, 0) AS step_0, - if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, - if(equals(e.event, 'terminate funnel'), 1, 0) AS step_1, - if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, - [if(empty(replaceRegexpOne(ifNull(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), ''), '[\\/?#]*$', '')), '/', replaceRegexpOne(ifNull(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), ''), '[\\/?#]*$', ''))] AS prop_basic, - prop_basic AS prop, - argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals - FROM events AS e - INNER JOIN - (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, - person_distinct_id2.distinct_id AS distinct_id - FROM person_distinct_id2 - WHERE equals(person_distinct_id2.team_id, 2) - GROUP BY person_distinct_id2.distinct_id - HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) - WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-02 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-12 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('terminate funnel', 'watched movie'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0)))))) - WHERE ifNull(equals(step_0, 1), 0))) - GROUP BY aggregation_target, - steps, - prop - HAVING ifNull(equals(steps, max_steps), isNull(steps) - and isNull(max_steps))) - GROUP BY prop - LIMIT 100 SETTINGS readonly=2, - max_execution_time=60, - allow_experimental_object_type=1 - ''' -# --- -# name: TestBreakdownsByCurrentURL.test_breakdown_by_pathname - ''' - SELECT [if(empty(replaceRegexpOne(ifNull(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$pathname'), ''), 'null'), '^"|"$', ''), ''), '[\\/?#]*$', '')), '/', replaceRegexpOne(ifNull(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$pathname'), ''), 'null'), '^"|"$', ''), ''), '[\\/?#]*$', ''))] AS value, - count(*) AS count - FROM events AS e - INNER JOIN - (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, - person_distinct_id2.distinct_id AS distinct_id - FROM person_distinct_id2 - WHERE equals(person_distinct_id2.team_id, 2) - GROUP BY person_distinct_id2.distinct_id - HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) - WHERE and(equals(e.team_id, 2), in(e.event, tuple('terminate funnel', 'watched movie')), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-02 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-12 23:59:59.999999', 6, 'UTC'))), notEmpty(e__pdi.person_id)) - GROUP BY value - ORDER BY count DESC, value DESC - LIMIT 101 - OFFSET 0 SETTINGS readonly=2, - max_execution_time=60, - allow_experimental_object_type=1 - ''' -# --- -# name: TestBreakdownsByCurrentURL.test_breakdown_by_pathname.1 - ''' - SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, - countIf(ifNull(equals(steps, 2), 0)) AS step_2, - avg(step_1_average_conversion_time_inner) AS step_1_average_conversion_time, - median(step_1_median_conversion_time_inner) AS step_1_median_conversion_time, - prop AS prop - FROM - (SELECT aggregation_target AS aggregation_target, - steps AS steps, - prop AS prop, - avg(step_1_conversion_time) AS step_1_average_conversion_time_inner, - median(step_1_conversion_time) AS step_1_median_conversion_time_inner, - prop AS prop - FROM - (SELECT aggregation_target AS aggregation_target, - steps AS steps, - prop AS prop, - max(steps) OVER (PARTITION BY aggregation_target, - prop) AS max_steps, - step_1_conversion_time AS step_1_conversion_time, - prop AS prop - FROM - (SELECT aggregation_target AS aggregation_target, - timestamp AS timestamp, - step_0 AS step_0, - latest_0 AS latest_0, - step_1 AS step_1, - latest_1 AS latest_1, - prop AS prop, - if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(latest_0, toIntervalDay(14))), 0)), 2, 1) AS steps, - if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(latest_0, toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, - prop AS prop - FROM - (SELECT aggregation_target AS aggregation_target, - timestamp AS timestamp, - step_0 AS step_0, - latest_0 AS latest_0, - step_1 AS step_1, - min(latest_1) OVER (PARTITION BY aggregation_target, - prop - ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, - if(has([['/'], ['/home']], prop), prop, ['Other']) AS prop - FROM - (SELECT timestamp AS timestamp, - aggregation_target AS aggregation_target, - step_0 AS step_0, - latest_0 AS latest_0, - step_1 AS step_1, - latest_1 AS latest_1, - prop_basic AS prop_basic, - prop, - prop_vals AS prop_vals, - if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['']) AS prop - FROM - (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, - e__pdi.person_id AS aggregation_target, - if(equals(e.event, 'watched movie'), 1, 0) AS step_0, - if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, - if(equals(e.event, 'terminate funnel'), 1, 0) AS step_1, - if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, - [if(empty(replaceRegexpOne(ifNull(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$pathname'), ''), 'null'), '^"|"$', ''), ''), '[\\/?#]*$', '')), '/', replaceRegexpOne(ifNull(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$pathname'), ''), 'null'), '^"|"$', ''), ''), '[\\/?#]*$', ''))] AS prop_basic, - prop_basic AS prop, - argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals - FROM events AS e - INNER JOIN - (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, - person_distinct_id2.distinct_id AS distinct_id - FROM person_distinct_id2 - WHERE equals(person_distinct_id2.team_id, 2) - GROUP BY person_distinct_id2.distinct_id - HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) - WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-02 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-12 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('terminate funnel', 'watched movie'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0)))))) - WHERE ifNull(equals(step_0, 1), 0))) - GROUP BY aggregation_target, - steps, - prop - HAVING ifNull(equals(steps, max_steps), isNull(steps) - and isNull(max_steps))) - GROUP BY prop - LIMIT 100 SETTINGS readonly=2, - max_execution_time=60, - allow_experimental_object_type=1 - ''' -# --- diff --git a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_strict.ambr b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_strict.ambr index 7e7d0e0586b32..8e77766f6667d 100644 --- a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_strict.ambr +++ b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_strict.ambr @@ -1,4 +1,1131 @@ # serializer version: 1 +# name: BaseTestFunnelStrictStepsBreakdown.test_funnel_breakdown_correct_breakdown_props_are_chosen + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, ['Other']) AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_2 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['']) AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, 'buy'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', ''), 'xyz'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelStrictStepsBreakdown.test_funnel_breakdown_correct_breakdown_props_are_chosen_for_step + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, ['Other']) AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_2 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop_basic AS prop_basic, + prop_0 AS prop_0, + prop_1 AS prop_1, + prop, + prop_vals AS prop_vals, + prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, 'buy'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', ''), 'xyz'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + if(ifNull(equals(step_0, 1), 0), prop_basic, []) AS prop_0, + if(ifNull(equals(step_1, 1), 0), prop_basic, []) AS prop_1, + prop_1 AS prop, + groupUniqArray(prop) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))) ARRAY + JOIN prop_vals AS prop + WHERE ifNull(notEquals(prop, []), isNotNull(prop) + or isNotNull([])))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelStrictStepsBreakdown.test_funnel_step_multiple_breakdown_snapshot + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, ['Other']) AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_2 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['', '']) AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'buy'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), ''), ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_aggregate_by_groups_breakdown_group_person_on_events + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(avgArrayOrNull(step_2_conversion_time_array) AS inter_2_conversion), NULL, inter_2_conversion) AS step_2_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(isNaN(medianArrayOrNull(step_2_conversion_time_array) AS inter_2_median), NULL, inter_2_median) AS step_2_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, 'Other') AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + countIf(ifNull(equals(steps, 3), 0)) AS step_3, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + groupArray(step_2_conversion_time) AS step_2_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_3 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time, + min(step_2_conversion_time) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) AS latest_2, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e.`$group_0` AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_aggregate_by_groups_breakdown_group_person_on_events_poe_v2 + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(avgArrayOrNull(step_2_conversion_time_array) AS inter_2_conversion), NULL, inter_2_conversion) AS step_2_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(isNaN(medianArrayOrNull(step_2_conversion_time_array) AS inter_2_median), NULL, inter_2_median) AS step_2_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, 'Other') AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + countIf(ifNull(equals(steps, 3), 0)) AS step_3, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + groupArray(step_2_conversion_time) AS step_2_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_3 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time, + min(step_2_conversion_time) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) AS latest_2, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e.`$group_0` AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(avgArrayOrNull(step_2_conversion_time_array) AS inter_2_conversion), NULL, inter_2_conversion) AS step_2_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(isNaN(medianArrayOrNull(step_2_conversion_time_array) AS inter_2_median), NULL, inter_2_median) AS step_2_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, 'Other') AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + countIf(ifNull(equals(steps, 3), 0)) AS step_3, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + groupArray(step_2_conversion_time) AS step_2_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_3 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time, + min(step_2_conversion_time) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) AS latest_2, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.1 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.2 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [1, 2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('finance')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.3 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.4 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('finance')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.5 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.6 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [1, 2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('technology')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.7 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.8 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('technology')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- # name: TestFunnelStrictStepsBreakdown.test_funnel_breakdown_correct_breakdown_props_are_chosen ''' SELECT sum(step_1) AS step_1, diff --git a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_strict_udf.ambr b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_strict_udf.ambr new file mode 100644 index 0000000000000..837c953bc93f5 --- /dev/null +++ b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_strict_udf.ambr @@ -0,0 +1,2066 @@ +# serializer version: 1 +# name: BaseTestFunnelStrictStepsBreakdown.test_funnel_breakdown_correct_breakdown_props_are_chosen + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, ['Other']) AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_2 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['']) AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, 'buy'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', ''), 'xyz'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelStrictStepsBreakdown.test_funnel_breakdown_correct_breakdown_props_are_chosen_for_step + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, ['Other']) AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_2 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop_basic AS prop_basic, + prop_0 AS prop_0, + prop_1 AS prop_1, + prop, + prop_vals AS prop_vals, + prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, 'buy'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', ''), 'xyz'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + if(ifNull(equals(step_0, 1), 0), prop_basic, []) AS prop_0, + if(ifNull(equals(step_1, 1), 0), prop_basic, []) AS prop_1, + prop_1 AS prop, + groupUniqArray(prop) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))) ARRAY + JOIN prop_vals AS prop + WHERE ifNull(notEquals(prop, []), isNotNull(prop) + or isNotNull([])))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelStrictStepsBreakdown.test_funnel_step_multiple_breakdown_snapshot + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, ['Other']) AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_2 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['', '']) AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'buy'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), ''), ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_aggregate_by_groups_breakdown_group_person_on_events + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(avgArrayOrNull(step_2_conversion_time_array) AS inter_2_conversion), NULL, inter_2_conversion) AS step_2_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(isNaN(medianArrayOrNull(step_2_conversion_time_array) AS inter_2_median), NULL, inter_2_median) AS step_2_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, 'Other') AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + countIf(ifNull(equals(steps, 3), 0)) AS step_3, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + groupArray(step_2_conversion_time) AS step_2_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_3 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time, + min(step_2_conversion_time) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) AS latest_2, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e.`$group_0` AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_aggregate_by_groups_breakdown_group_person_on_events_poe_v2 + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(avgArrayOrNull(step_2_conversion_time_array) AS inter_2_conversion), NULL, inter_2_conversion) AS step_2_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(isNaN(medianArrayOrNull(step_2_conversion_time_array) AS inter_2_median), NULL, inter_2_median) AS step_2_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, 'Other') AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + countIf(ifNull(equals(steps, 3), 0)) AS step_3, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + groupArray(step_2_conversion_time) AS step_2_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_3 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time, + min(step_2_conversion_time) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) AS latest_2, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e.`$group_0` AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + if(isNaN(avgArrayOrNull(step_1_conversion_time_array) AS inter_1_conversion), NULL, inter_1_conversion) AS step_1_average_conversion_time, + if(isNaN(avgArrayOrNull(step_2_conversion_time_array) AS inter_2_conversion), NULL, inter_2_conversion) AS step_2_average_conversion_time, + if(isNaN(medianArrayOrNull(step_1_conversion_time_array) AS inter_1_median), NULL, inter_1_median) AS step_1_median_conversion_time, + if(isNaN(medianArrayOrNull(step_2_conversion_time_array) AS inter_2_median), NULL, inter_2_median) AS step_2_median_conversion_time, + if(ifNull(less(row_number, 26), 0), prop, 'Other') AS final_prop + FROM + (SELECT countIf(ifNull(equals(steps, 1), 0)) AS step_1, + countIf(ifNull(equals(steps, 2), 0)) AS step_2, + countIf(ifNull(equals(steps, 3), 0)) AS step_3, + groupArray(step_1_conversion_time) AS step_1_conversion_time_array, + groupArray(step_2_conversion_time) AS step_2_conversion_time_array, + prop AS prop, + row_number() OVER ( + ORDER BY step_3 DESC) AS row_number + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + prop AS prop, + min(step_1_conversion_time) AS step_1_conversion_time, + min(step_2_conversion_time) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + prop AS prop, + max(steps) OVER (PARTITION BY aggregation_target, + prop) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time, + prop AS prop + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop AS prop, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) AS latest_2, + prop AS prop + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps, + prop + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + GROUP BY prop) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.1 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.2 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [1, 2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('finance')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.3 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.4 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('finance')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.5 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.6 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [1, 2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('technology')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.7 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: BaseTestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.8 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('technology')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: TestFunnelStrictStepsBreakdown.test_funnel_breakdown_correct_breakdown_props_are_chosen + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, ['Other']) AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'first_touch', 'strict', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['']) AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, 'buy'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', ''), 'xyz'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC')))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelStrictStepsBreakdown.test_funnel_breakdown_correct_breakdown_props_are_chosen_for_step + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, ['Other']) AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'step_1', 'strict', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + prop_basic AS prop_basic, + prop_0 AS prop_0, + prop_1 AS prop_1, + prop, + prop_vals AS prop_vals, + prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, 'buy'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', ''), 'xyz'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + if(ifNull(equals(step_0, 1), 0), prop_basic, []) AS prop_0, + if(ifNull(equals(step_1, 1), 0), prop_basic, []) AS prop_1, + prop_1 AS prop, + groupUniqArray(prop) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))))) ARRAY + JOIN prop_vals AS prop + WHERE ifNull(notEquals(prop, []), isNotNull(prop) + or isNotNull([]))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelStrictStepsBreakdown.test_funnel_step_multiple_breakdown_snapshot + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, ['Other']) AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'first_touch', 'strict', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['', '']) AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'buy'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), ''), ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC')))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_aggregate_by_groups_breakdown_group_person_on_events + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, 'Other') AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel(3, 1209600, 'first_touch', 'strict', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + exclusion_2 AS exclusion_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e.`$group_0` AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC')))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_aggregate_by_groups_breakdown_group_person_on_events_poe_v2 + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, 'Other') AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel(3, 1209600, 'first_touch', 'strict', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + exclusion_2 AS exclusion_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e.`$group_0` AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC')))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, 'Other') AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel(3, 1209600, 'first_touch', 'strict', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + exclusion_2 AS exclusion_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC')))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.1 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.2 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [1, 2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('finance')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.3 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.4 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('finance')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.5 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.6 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [1, 2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('technology')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.7 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: TestStrictFunnelGroupBreakdown.test_funnel_breakdown_group.8 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner, + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time, + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps, + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (1=1) ))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('technology')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- diff --git a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_trends.ambr b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_trends.ambr index 7267c85d00c1b..cfbc8d8a68362 100644 --- a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_trends.ambr +++ b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_trends.ambr @@ -1,4 +1,366 @@ # serializer version: 1 +# name: BaseTestFunnelTrends.test_timezones_trends + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + data.reached_from_step_count AS reached_from_step_count, + data.reached_to_step_count AS reached_to_step_count, + if(ifNull(greater(data.reached_from_step_count, 0), 0), round(multiply(divide(data.reached_to_step_count, data.reached_from_step_count), 100), 2), 0) AS conversion_rate + FROM + (SELECT plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'UTC'))), toIntervalDay(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'UTC')))), 1)) AS period_offsets) AS fill + LEFT OUTER JOIN + (SELECT entrance_period_start AS entrance_period_start, + countIf(ifNull(greaterOrEquals(steps_completed, 1), 0)) AS reached_from_step_count, + countIf(ifNull(greaterOrEquals(steps_completed, 3), 0)) AS reached_to_step_count + FROM + (SELECT aggregation_target AS aggregation_target, + toStartOfDay(timestamp) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-04-30 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0)) + GROUP BY aggregation_target, + entrance_period_start) + GROUP BY entrance_period_start) AS data ON equals(data.entrance_period_start, fill.entrance_period_start) + ORDER BY fill.entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelTrends.test_timezones_trends.1 + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + data.reached_from_step_count AS reached_from_step_count, + data.reached_to_step_count AS reached_to_step_count, + if(ifNull(greater(data.reached_from_step_count, 0), 0), round(multiply(divide(data.reached_to_step_count, data.reached_from_step_count), 100), 2), 0) AS conversion_rate + FROM + (SELECT plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'US/Pacific'))), toIntervalDay(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'US/Pacific'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'US/Pacific')))), 1)) AS period_offsets) AS fill + LEFT OUTER JOIN + (SELECT entrance_period_start AS entrance_period_start, + countIf(ifNull(greaterOrEquals(steps_completed, 1), 0)) AS reached_from_step_count, + countIf(ifNull(greaterOrEquals(steps_completed, 3), 0)) AS reached_to_step_count + FROM + (SELECT aggregation_target AS aggregation_target, + toStartOfDay(timestamp) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'US/Pacific') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'US/Pacific'), toDateTime64('2021-04-30 00:00:00.000000', 6, 'US/Pacific')), lessOrEquals(toTimeZone(e.timestamp, 'US/Pacific'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'US/Pacific'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0)) + GROUP BY aggregation_target, + entrance_period_start) + GROUP BY entrance_period_start) AS data ON equals(data.entrance_period_start, fill.entrance_period_start) + ORDER BY fill.entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelTrends.test_week_interval + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + data.reached_from_step_count AS reached_from_step_count, + data.reached_to_step_count AS reached_to_step_count, + if(ifNull(greater(data.reached_from_step_count, 0), 0), round(multiply(divide(data.reached_to_step_count, data.reached_from_step_count), 100), 2), 0) AS conversion_rate + FROM + (SELECT plus(toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-01 00:00:00'), 6, 'UTC')), 0), toIntervalWeek(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('week', toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-01 00:00:00'), 6, 'UTC')), 0), toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'UTC')), 0)), 1)) AS period_offsets) AS fill + LEFT OUTER JOIN + (SELECT entrance_period_start AS entrance_period_start, + countIf(ifNull(greaterOrEquals(steps_completed, 1), 0)) AS reached_from_step_count, + countIf(ifNull(greaterOrEquals(steps_completed, 3), 0)) AS reached_to_step_count + FROM + (SELECT aggregation_target AS aggregation_target, + toStartOfWeek(timestamp, 0) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0)) + GROUP BY aggregation_target, + entrance_period_start) + GROUP BY entrance_period_start) AS data ON equals(data.entrance_period_start, fill.entrance_period_start) + ORDER BY fill.entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelTrends.test_week_interval.1 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + toStartOfWeek(toTimeZone(toDateTime(timestamp, 'UTC'), 'UTC'), 0) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps , + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + if(latest_2 < latest_1, NULL, latest_2) as latest_2 + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'step one', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'step two', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'step three', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2 + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND event IN ['step one', 'step three', 'step two'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2021-05-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2021-05-07 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + WHERE team_id = 2 + AND event IN ['step one', 'step three', 'step two'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2021-05-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2021-05-07 23:59:59', 'UTC') + AND (step_0 = 1 + OR step_1 = 1 + OR step_2 = 1) )))) + WHERE step_0 = 1 ) + WHERE toDateTime(entrance_period_start) = '2021-04-25 00:00:00' + GROUP BY aggregation_target, + entrance_period_start) + WHERE steps_completed >= 3 + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- # name: TestFunnelTrends.test_timezones_trends ''' SELECT fill.entrance_period_start AS entrance_period_start, diff --git a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_trends_udf.ambr b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_trends_udf.ambr new file mode 100644 index 0000000000000..0c52cf349a36b --- /dev/null +++ b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_trends_udf.ambr @@ -0,0 +1,602 @@ +# serializer version: 1 +# name: BaseTestFunnelTrends.test_timezones_trends + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + data.reached_from_step_count AS reached_from_step_count, + data.reached_to_step_count AS reached_to_step_count, + if(ifNull(greater(data.reached_from_step_count, 0), 0), round(multiply(divide(data.reached_to_step_count, data.reached_from_step_count), 100), 2), 0) AS conversion_rate + FROM + (SELECT plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'UTC'))), toIntervalDay(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'UTC')))), 1)) AS period_offsets) AS fill + LEFT OUTER JOIN + (SELECT entrance_period_start AS entrance_period_start, + countIf(ifNull(greaterOrEquals(steps_completed, 1), 0)) AS reached_from_step_count, + countIf(ifNull(greaterOrEquals(steps_completed, 3), 0)) AS reached_to_step_count + FROM + (SELECT aggregation_target AS aggregation_target, + toStartOfDay(timestamp) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-04-30 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0)) + GROUP BY aggregation_target, + entrance_period_start) + GROUP BY entrance_period_start) AS data ON equals(data.entrance_period_start, fill.entrance_period_start) + ORDER BY fill.entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelTrends.test_timezones_trends.1 + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + data.reached_from_step_count AS reached_from_step_count, + data.reached_to_step_count AS reached_to_step_count, + if(ifNull(greater(data.reached_from_step_count, 0), 0), round(multiply(divide(data.reached_to_step_count, data.reached_from_step_count), 100), 2), 0) AS conversion_rate + FROM + (SELECT plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'US/Pacific'))), toIntervalDay(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'US/Pacific'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'US/Pacific')))), 1)) AS period_offsets) AS fill + LEFT OUTER JOIN + (SELECT entrance_period_start AS entrance_period_start, + countIf(ifNull(greaterOrEquals(steps_completed, 1), 0)) AS reached_from_step_count, + countIf(ifNull(greaterOrEquals(steps_completed, 3), 0)) AS reached_to_step_count + FROM + (SELECT aggregation_target AS aggregation_target, + toStartOfDay(timestamp) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'US/Pacific') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'US/Pacific'), toDateTime64('2021-04-30 00:00:00.000000', 6, 'US/Pacific')), lessOrEquals(toTimeZone(e.timestamp, 'US/Pacific'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'US/Pacific'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0)) + GROUP BY aggregation_target, + entrance_period_start) + GROUP BY entrance_period_start) AS data ON equals(data.entrance_period_start, fill.entrance_period_start) + ORDER BY fill.entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelTrends.test_week_interval + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + data.reached_from_step_count AS reached_from_step_count, + data.reached_to_step_count AS reached_to_step_count, + if(ifNull(greater(data.reached_from_step_count, 0), 0), round(multiply(divide(data.reached_to_step_count, data.reached_from_step_count), 100), 2), 0) AS conversion_rate + FROM + (SELECT plus(toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-01 00:00:00'), 6, 'UTC')), 0), toIntervalWeek(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('week', toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-01 00:00:00'), 6, 'UTC')), 0), toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'UTC')), 0)), 1)) AS period_offsets) AS fill + LEFT OUTER JOIN + (SELECT entrance_period_start AS entrance_period_start, + countIf(ifNull(greaterOrEquals(steps_completed, 1), 0)) AS reached_from_step_count, + countIf(ifNull(greaterOrEquals(steps_completed, 3), 0)) AS reached_to_step_count + FROM + (SELECT aggregation_target AS aggregation_target, + toStartOfWeek(timestamp, 0) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0)) + GROUP BY aggregation_target, + entrance_period_start) + GROUP BY entrance_period_start) AS data ON equals(data.entrance_period_start, fill.entrance_period_start) + ORDER BY fill.entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: BaseTestFunnelTrends.test_week_interval.1 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + toStartOfWeek(toTimeZone(toDateTime(timestamp, 'UTC'), 'UTC'), 0) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps , + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + if(latest_2 < latest_1, NULL, latest_2) as latest_2 + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'step one', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'step two', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'step three', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2 + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND event IN ['step one', 'step three', 'step two'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2021-05-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2021-05-07 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + WHERE team_id = 2 + AND event IN ['step one', 'step three', 'step two'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2021-05-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2021-05-07 23:59:59', 'UTC') + AND (step_0 = 1 + OR step_1 = 1 + OR step_2 = 1) )))) + WHERE step_0 = 1 ) + WHERE toDateTime(entrance_period_start) = '2021-04-25 00:00:00' + GROUP BY aggregation_target, + entrance_period_start) + WHERE steps_completed >= 3 + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: TestFunnelTrendsUDF.test_timezones_trends + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + countIf(ifNull(notEquals(data.success_bool, 0), 1)) AS reached_from_step_count, + countIf(ifNull(equals(data.success_bool, 1), 0)) AS reached_to_step_count, + if(ifNull(greater(reached_from_step_count, 0), 0), round(multiply(divide(reached_to_step_count, reached_from_step_count), 100), 2), 0) AS conversion_rate, + data.breakdown AS prop + FROM + (SELECT arrayJoin(aggregate_funnel_array_trends(0, 3, 1209600, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), toStartOfDay(timestamp), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + toTimeZone(af_tuple.1, 'UTC') AS entrance_period_start, + af_tuple.2 AS success_bool, + af_tuple.3 AS breakdown + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-04-30 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0)))) + GROUP BY aggregation_target SETTINGS date_time_output_format='iso', + date_time_input_format='best_effort') AS data + RIGHT OUTER JOIN + (SELECT plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'UTC'))), toIntervalDay(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'UTC')))), 1)) AS period_offsets) AS fill ON equals(data.entrance_period_start, fill.entrance_period_start) + GROUP BY entrance_period_start, + data.breakdown + ORDER BY entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelTrendsUDF.test_timezones_trends.1 + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + countIf(ifNull(notEquals(data.success_bool, 0), 1)) AS reached_from_step_count, + countIf(ifNull(equals(data.success_bool, 1), 0)) AS reached_to_step_count, + if(ifNull(greater(reached_from_step_count, 0), 0), round(multiply(divide(reached_to_step_count, reached_from_step_count), 100), 2), 0) AS conversion_rate, + data.breakdown AS prop + FROM + (SELECT arrayJoin(aggregate_funnel_array_trends(0, 3, 1209600, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), toStartOfDay(timestamp), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + toTimeZone(af_tuple.1, 'US/Pacific') AS entrance_period_start, + af_tuple.2 AS success_bool, + af_tuple.3 AS breakdown + FROM + (SELECT toTimeZone(e.timestamp, 'US/Pacific') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'US/Pacific'), toDateTime64('2021-04-30 00:00:00.000000', 6, 'US/Pacific')), lessOrEquals(toTimeZone(e.timestamp, 'US/Pacific'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'US/Pacific'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0)))) + GROUP BY aggregation_target SETTINGS date_time_output_format='iso', + date_time_input_format='best_effort') AS data + RIGHT OUTER JOIN + (SELECT plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'US/Pacific'))), toIntervalDay(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-04-30 00:00:00'), 6, 'US/Pacific'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'US/Pacific')))), 1)) AS period_offsets) AS fill ON equals(data.entrance_period_start, fill.entrance_period_start) + GROUP BY entrance_period_start, + data.breakdown + ORDER BY entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelTrendsUDF.test_week_interval + ''' + SELECT fill.entrance_period_start AS entrance_period_start, + countIf(ifNull(notEquals(data.success_bool, 0), 1)) AS reached_from_step_count, + countIf(ifNull(equals(data.success_bool, 1), 0)) AS reached_to_step_count, + if(ifNull(greater(reached_from_step_count, 0), 0), round(multiply(divide(reached_to_step_count, reached_from_step_count), 100), 2), 0) AS conversion_rate, + data.breakdown AS prop + FROM + (SELECT arrayJoin(aggregate_funnel_array_trends(0, 3, 1209600, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), toStartOfWeek(timestamp, 0), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + toTimeZone(af_tuple.1, 'UTC') AS entrance_period_start, + af_tuple.2 AS success_bool, + af_tuple.3 AS breakdown + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-07 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0)))) + GROUP BY aggregation_target SETTINGS date_time_output_format='iso', + date_time_input_format='best_effort') AS data + RIGHT OUTER JOIN + (SELECT plus(toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-01 00:00:00'), 6, 'UTC')), 0), toIntervalWeek(period_offsets.number)) AS entrance_period_start + FROM numbers(plus(dateDiff('week', toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-01 00:00:00'), 6, 'UTC')), 0), toStartOfWeek(assumeNotNull(parseDateTime64BestEffortOrNull(('2021-05-07 23:59:59'), 6, 'UTC')), 0)), 1)) AS period_offsets) AS fill ON equals(data.entrance_period_start, fill.entrance_period_start) + GROUP BY entrance_period_start, + data.breakdown + ORDER BY entrance_period_start ASC + LIMIT 1000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelTrendsUDF.test_week_interval.1 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + toStartOfWeek(toTimeZone(toDateTime(timestamp, 'UTC'), 'UTC'), 0) AS entrance_period_start, + max(steps) AS steps_completed + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps , + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + if(latest_2 < latest_1, NULL, latest_2) as latest_2 + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'step one', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'step two', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'step three', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2 + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND event IN ['step one', 'step three', 'step two'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2021-05-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2021-05-07 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + WHERE team_id = 2 + AND event IN ['step one', 'step three', 'step two'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2021-05-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2021-05-07 23:59:59', 'UTC') + AND (step_0 = 1 + OR step_1 = 1 + OR step_2 = 1) )))) + WHERE step_0 = 1 ) + WHERE toDateTime(entrance_period_start) = '2021-04-25 00:00:00' + GROUP BY aggregation_target, + entrance_period_start) + WHERE steps_completed >= 3 + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- diff --git a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_udf.ambr b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_udf.ambr new file mode 100644 index 0000000000000..e8487d4a42a9e --- /dev/null +++ b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel_udf.ambr @@ -0,0 +1,1887 @@ +# serializer version: 1 +# name: TestFOSSFunnelUDF.test_funnel_conversion_window_seconds + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + breakdown AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(3, 15, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-14 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0)))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_conversion_window_seconds.1 + ''' + SELECT persons.id, + persons.id AS id, + persons.created_at AS created_at, + 1 + FROM + (SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + avg(step_1_conversion_time) AS step_1_average_conversion_time_inner, + avg(step_2_conversion_time) AS step_2_average_conversion_time_inner, + median(step_1_conversion_time) AS step_1_median_conversion_time_inner, + median(step_2_conversion_time) AS step_2_median_conversion_time_inner + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + max(steps) OVER (PARTITION BY aggregation_target) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalSecond(15))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalSecond(15))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalSecond(15))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalSecond(15))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalSecond(15))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'step one'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'step two'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'step three'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2021-05-14 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('step one', 'step three', 'step two'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + WHERE ifNull(in(steps, [2, 3]), 0) + ORDER BY aggregation_target ASC) AS source + INNER JOIN + (SELECT argMax(toTimeZone(person.created_at, 'UTC'), person.version) AS created_at, + person.id AS id + FROM person + WHERE equals(person.team_id, 2) + GROUP BY person.id + HAVING and(ifNull(equals(argMax(person.is_deleted, person.version), 0), 0), ifNull(less(argMax(toTimeZone(person.created_at, 'UTC'), person.version), plus(now64(6, 'UTC'), toIntervalDay(1))), 0)) SETTINGS optimize_aggregation_in_order=1) AS persons ON equals(persons.id, source.actor_id) + ORDER BY persons.created_at DESC + LIMIT 101 + OFFSET 0 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=0, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_events_with_person_on_events_v2 + ''' + + SELECT DISTINCT person_id + FROM events + WHERE team_id = 2 + AND distinct_id = 'stopped_after_pay' + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_events_with_person_on_events_v2.1 + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + breakdown AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(3, 1209600, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + if(not(empty(e__override.distinct_id)), e__override.person_id, e.person_id) AS aggregation_target, + if(equals(e.event, 'user signed up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, '$autocapture'), match(e.elements_chain, '(^|;)button(\\.|$|;|:)'), arrayExists(x -> ifNull(equals(x, 'Pay $10'), 0), e.elements_chain_texts)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(and(equals(e.event, '$autocapture'), match(e.elements_chain, '(^|;)a(\\.|$|;|:)'), equals(e.elements_chain_href, '/movie')), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2 + FROM events AS e + LEFT OUTER JOIN + (SELECT argMax(person_distinct_id_overrides.person_id, person_distinct_id_overrides.version) AS person_id, + person_distinct_id_overrides.distinct_id AS distinct_id + FROM person_distinct_id_overrides + WHERE equals(person_distinct_id_overrides.team_id, 2) + GROUP BY person_distinct_id_overrides.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id_overrides.is_deleted, person_distinct_id_overrides.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__override ON equals(e.distinct_id, e__override.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2011-12-25 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2012-01-01 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('$autocapture', 'user signed up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0)))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_precalculated_cohort_step_filter + ''' + + SELECT count(DISTINCT person_id) + FROM cohortpeople + WHERE team_id = 2 + AND cohort_id = 2 + AND version = NULL + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_precalculated_cohort_step_filter.1 + ''' + /* cohort_calculation: */ + SELECT count(DISTINCT person_id) + FROM cohortpeople + WHERE team_id = 2 + AND cohort_id = 2 + AND version = 0 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_precalculated_cohort_step_filter.2 + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + breakdown AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(and(equals(e.event, 'user signed up'), ifNull(in(e__pdi.person_id, + (SELECT cohortpeople.person_id AS person_id + FROM cohortpeople + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0)), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'paid'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-14 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('paid', 'user signed up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0)))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_property_groups + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + breakdown AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(3, 1209600, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'user signed up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, '$pageview'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), 'aloha.com'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(and(equals(e.event, '$pageview'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), 'aloha2.com'), 0)), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS e__pdi___person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + INNER JOIN + (SELECT person.id AS id, + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, 'email'), ''), 'null'), '^"|"$', '') AS properties___email, + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, 'age'), ''), 'null'), '^"|"$', '') AS properties___age + FROM person + WHERE and(equals(person.team_id, 2), ifNull(in(tuple(person.id, person.version), + (SELECT person.id AS id, max(person.version) AS version + FROM person + WHERE equals(person.team_id, 2) + GROUP BY person.id + HAVING and(ifNull(equals(argMax(person.is_deleted, person.version), 0), 0), ifNull(less(argMax(toTimeZone(person.created_at, 'UTC'), person.version), plus(now64(6, 'UTC'), toIntervalDay(1))), 0)))), 0)) SETTINGS optimize_aggregation_in_order=1) AS e__pdi__person ON equals(e__pdi.e__pdi___person_id, e__pdi__person.id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-07-01 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('$pageview', 'user signed up')), or(and(ifNull(ilike(e__pdi__person.properties___email, '%.com%'), 0), ifNull(equals(e__pdi__person.properties___age, '20'), 0)), or(ifNull(ilike(e__pdi__person.properties___email, '%.org%'), 0), ifNull(equals(e__pdi__person.properties___age, '28'), 0)))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0)))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_property_groups.1 + ''' + SELECT persons.id, + persons.id AS id, + persons.created_at AS created_at, + 1 + FROM + (SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + avg(step_1_conversion_time) AS step_1_average_conversion_time_inner, + avg(step_2_conversion_time) AS step_2_average_conversion_time_inner, + median(step_1_conversion_time) AS step_1_median_conversion_time_inner, + median(step_2_conversion_time) AS step_2_median_conversion_time_inner + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + max(steps) OVER (PARTITION BY aggregation_target) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'user signed up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, '$pageview'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), 'aloha.com'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(and(equals(e.event, '$pageview'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), 'aloha2.com'), 0)), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS e__pdi___person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + INNER JOIN + (SELECT person.id AS id, + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, 'email'), ''), 'null'), '^"|"$', '') AS properties___email, + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, 'age'), ''), 'null'), '^"|"$', '') AS properties___age + FROM person + WHERE and(equals(person.team_id, 2), ifNull(in(tuple(person.id, person.version), + (SELECT person.id AS id, max(person.version) AS version + FROM person + WHERE equals(person.team_id, 2) + GROUP BY person.id + HAVING and(ifNull(equals(argMax(person.is_deleted, person.version), 0), 0), ifNull(less(argMax(toTimeZone(person.created_at, 'UTC'), person.version), plus(now64(6, 'UTC'), toIntervalDay(1))), 0)))), 0)) SETTINGS optimize_aggregation_in_order=1) AS e__pdi__person ON equals(e__pdi.e__pdi___person_id, e__pdi__person.id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-07-01 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('$pageview', 'user signed up')), or(and(ifNull(ilike(e__pdi__person.properties___email, '%.com%'), 0), ifNull(equals(e__pdi__person.properties___age, '20'), 0)), or(ifNull(ilike(e__pdi__person.properties___email, '%.org%'), 0), ifNull(equals(e__pdi__person.properties___age, '28'), 0)))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + WHERE ifNull(in(steps, [1, 2, 3]), 0) + ORDER BY aggregation_target ASC) AS source + INNER JOIN + (SELECT argMax(toTimeZone(person.created_at, 'UTC'), person.version) AS created_at, + person.id AS id + FROM person + WHERE equals(person.team_id, 2) + GROUP BY person.id + HAVING and(ifNull(equals(argMax(person.is_deleted, person.version), 0), 0), ifNull(less(argMax(toTimeZone(person.created_at, 'UTC'), person.version), plus(now64(6, 'UTC'), toIntervalDay(1))), 0)) SETTINGS optimize_aggregation_in_order=1) AS persons ON equals(persons.id, source.actor_id) + ORDER BY persons.created_at DESC + LIMIT 101 + OFFSET 0 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=0, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_property_groups.2 + ''' + SELECT persons.id, + persons.id AS id, + persons.created_at AS created_at, + 1 + FROM + (SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + avg(step_1_conversion_time) AS step_1_average_conversion_time_inner, + avg(step_2_conversion_time) AS step_2_average_conversion_time_inner, + median(step_1_conversion_time) AS step_1_median_conversion_time_inner, + median(step_2_conversion_time) AS step_2_median_conversion_time_inner + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + max(steps) OVER (PARTITION BY aggregation_target) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'user signed up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, '$pageview'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), 'aloha.com'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(and(equals(e.event, '$pageview'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), 'aloha2.com'), 0)), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS e__pdi___person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + INNER JOIN + (SELECT person.id AS id, + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, 'email'), ''), 'null'), '^"|"$', '') AS properties___email, + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, 'age'), ''), 'null'), '^"|"$', '') AS properties___age + FROM person + WHERE and(equals(person.team_id, 2), ifNull(in(tuple(person.id, person.version), + (SELECT person.id AS id, max(person.version) AS version + FROM person + WHERE equals(person.team_id, 2) + GROUP BY person.id + HAVING and(ifNull(equals(argMax(person.is_deleted, person.version), 0), 0), ifNull(less(argMax(toTimeZone(person.created_at, 'UTC'), person.version), plus(now64(6, 'UTC'), toIntervalDay(1))), 0)))), 0)) SETTINGS optimize_aggregation_in_order=1) AS e__pdi__person ON equals(e__pdi.e__pdi___person_id, e__pdi__person.id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-07-01 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('$pageview', 'user signed up')), or(and(ifNull(ilike(e__pdi__person.properties___email, '%.com%'), 0), ifNull(equals(e__pdi__person.properties___age, '20'), 0)), or(ifNull(ilike(e__pdi__person.properties___email, '%.org%'), 0), ifNull(equals(e__pdi__person.properties___age, '28'), 0)))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + WHERE ifNull(in(steps, [2, 3]), 0) + ORDER BY aggregation_target ASC) AS source + INNER JOIN + (SELECT argMax(toTimeZone(person.created_at, 'UTC'), person.version) AS created_at, + person.id AS id + FROM person + WHERE equals(person.team_id, 2) + GROUP BY person.id + HAVING and(ifNull(equals(argMax(person.is_deleted, person.version), 0), 0), ifNull(less(argMax(toTimeZone(person.created_at, 'UTC'), person.version), plus(now64(6, 'UTC'), toIntervalDay(1))), 0)) SETTINGS optimize_aggregation_in_order=1) AS persons ON equals(persons.id, source.actor_id) + ORDER BY persons.created_at DESC + LIMIT 101 + OFFSET 0 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=0, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_property_groups.3 + ''' + SELECT persons.id, + persons.id AS id, + persons.created_at AS created_at, + 1 + FROM + (SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + avg(step_1_conversion_time) AS step_1_average_conversion_time_inner, + avg(step_2_conversion_time) AS step_2_average_conversion_time_inner, + median(step_1_conversion_time) AS step_1_median_conversion_time_inner, + median(step_2_conversion_time) AS step_2_median_conversion_time_inner + FROM + (SELECT aggregation_target AS aggregation_target, + steps AS steps, + max(steps) OVER (PARTITION BY aggregation_target) AS max_steps, + step_1_conversion_time AS step_1_conversion_time, + step_2_conversion_time AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0), ifNull(lessOrEquals(latest_1, latest_2), 0), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 3, if(and(ifNull(lessOrEquals(latest_0, latest_1), 0), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), 2, 1)) AS steps, + if(and(isNotNull(latest_1), ifNull(lessOrEquals(latest_1, plus(toTimeZone(latest_0, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_0, latest_1), NULL) AS step_1_conversion_time, + if(and(isNotNull(latest_2), ifNull(lessOrEquals(latest_2, plus(toTimeZone(latest_1, 'UTC'), toIntervalDay(14))), 0)), dateDiff('second', latest_1, latest_2), NULL) AS step_2_conversion_time + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + if(ifNull(less(latest_2, latest_1), 0), NULL, latest_2) AS latest_2 + FROM + (SELECT aggregation_target AS aggregation_target, + timestamp AS timestamp, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + min(latest_1) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_1, + step_2 AS step_2, + min(latest_2) OVER (PARTITION BY aggregation_target + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2 + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'user signed up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, '$pageview'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), 'aloha.com'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(and(equals(e.event, '$pageview'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$current_url'), ''), 'null'), '^"|"$', ''), 'aloha2.com'), 0)), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS e__pdi___person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + INNER JOIN + (SELECT person.id AS id, + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, 'email'), ''), 'null'), '^"|"$', '') AS properties___email, + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, 'age'), ''), 'null'), '^"|"$', '') AS properties___age + FROM person + WHERE and(equals(person.team_id, 2), ifNull(in(tuple(person.id, person.version), + (SELECT person.id AS id, max(person.version) AS version + FROM person + WHERE equals(person.team_id, 2) + GROUP BY person.id + HAVING and(ifNull(equals(argMax(person.is_deleted, person.version), 0), 0), ifNull(less(argMax(toTimeZone(person.created_at, 'UTC'), person.version), plus(now64(6, 'UTC'), toIntervalDay(1))), 0)))), 0)) SETTINGS optimize_aggregation_in_order=1) AS e__pdi__person ON equals(e__pdi.e__pdi___person_id, e__pdi__person.id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-07-01 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('$pageview', 'user signed up')), or(and(ifNull(ilike(e__pdi__person.properties___email, '%.com%'), 0), ifNull(equals(e__pdi__person.properties___age, '20'), 0)), or(ifNull(ilike(e__pdi__person.properties___email, '%.org%'), 0), ifNull(equals(e__pdi__person.properties___age, '28'), 0)))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))))) + WHERE ifNull(equals(step_0, 1), 0))) + GROUP BY aggregation_target, + steps + HAVING ifNull(equals(steps, max(max_steps)), isNull(steps) + and isNull(max(max_steps)))) + WHERE ifNull(in(steps, [3]), 0) + ORDER BY aggregation_target ASC) AS source + INNER JOIN + (SELECT argMax(toTimeZone(person.created_at, 'UTC'), person.version) AS created_at, + person.id AS id + FROM person + WHERE equals(person.team_id, 2) + GROUP BY person.id + HAVING and(ifNull(equals(argMax(person.is_deleted, person.version), 0), 0), ifNull(less(argMax(toTimeZone(person.created_at, 'UTC'), person.version), plus(now64(6, 'UTC'), toIntervalDay(1))), 0)) SETTINGS optimize_aggregation_in_order=1) AS persons ON equals(persons.id, source.actor_id) + ORDER BY persons.created_at DESC + LIMIT 101 + OFFSET 0 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=0, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_static_cohort_step_filter + ''' + + SELECT count(DISTINCT person_id) + FROM person_static_cohort + WHERE team_id = 2 + AND cohort_id = 2 + ''' +# --- +# name: TestFOSSFunnelUDF.test_funnel_with_static_cohort_step_filter.1 + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + breakdown AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(and(equals(e.event, 'user signed up'), ifNull(in(e__pdi.person_id, + (SELECT person_static_cohort.person_id AS person_id + FROM person_static_cohort + WHERE and(equals(person_static_cohort.team_id, 2), equals(person_static_cohort.cohort_id, 2)))), 0)), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'paid'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-14 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('paid', 'user signed up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0)))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFOSSFunnelUDF.test_timezones + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + breakdown AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'first_touch', 'ordered', [[]], arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), [], arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT toTimeZone(e.timestamp, 'US/Pacific') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'user signed up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'paid'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1 + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'US/Pacific'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'US/Pacific')), lessOrEquals(toTimeZone(e.timestamp, 'US/Pacific'), toDateTime64('2020-01-14 23:59:59.999999', 6, 'US/Pacific'))), in(e.event, tuple('paid', 'user signed up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0)))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelBreakdownUDF.test_funnel_breakdown_correct_breakdown_props_are_chosen + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, ['Other']) AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'first_touch', 'ordered', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['']) AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, 'buy'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', ''), 'xyz'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('buy', 'sign up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelBreakdownUDF.test_funnel_breakdown_correct_breakdown_props_are_chosen_for_step + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, ['Other']) AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'step_1', 'ordered', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + prop_basic AS prop_basic, + prop_0 AS prop_0, + prop_1 AS prop_1, + prop, + prop_vals AS prop_vals, + prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(and(equals(e.event, 'buy'), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', ''), 'xyz'), 0)), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + if(ifNull(equals(step_0, 1), 0), prop_basic, []) AS prop_0, + if(ifNull(equals(step_1, 1), 0), prop_basic, []) AS prop_1, + prop_1 AS prop, + groupUniqArray(prop) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('buy', 'sign up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0)))) ARRAY + JOIN prop_vals AS prop + WHERE ifNull(notEquals(prop, []), isNotNull(prop) + or isNotNull([]))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelBreakdownUDF.test_funnel_step_multiple_breakdown_snapshot + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, ['Other']) AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel_array(2, 1209600, 'first_touch', 'ordered', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['', '']) AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'buy'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + 0 AS exclusion_0, + 0 AS exclusion_1, + [ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$browser'), ''), 'null'), '^"|"$', '')), ''), ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$version'), ''), 'null'), '^"|"$', '')), '')] AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('buy', 'sign up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_aggregate_by_groups_breakdown_group_person_on_events + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, 'Other') AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel(3, 1209600, 'first_touch', 'ordered', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + exclusion_2 AS exclusion_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e.`$group_0` AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('buy', 'play movie', 'sign up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_aggregate_by_groups_breakdown_group_person_on_events_poe_v2 + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, 'Other') AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel(3, 1209600, 'first_touch', 'ordered', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + exclusion_2 AS exclusion_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e.`$group_0` AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('buy', 'play movie', 'sign up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group + ''' + SELECT sum(step_1) AS step_1, + sum(step_2) AS step_2, + sum(step_3) AS step_3, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_1_conversion_times)])[1] AS step_1_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [avgArrayOrNull(step_2_conversion_times)])[1] AS step_2_average_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_1_conversion_times)])[1] AS step_1_median_conversion_time, + arrayMap(x -> if(isNaN(x), NULL, x), [medianArrayOrNull(step_2_conversion_times)])[1] AS step_2_median_conversion_time, + groupArray(row_number) AS row_number, + final_prop AS final_prop + FROM + (SELECT countIf(ifNull(ifNull(equals(af, 0), 0), 0)) AS step_1, + countIf(ifNull(ifNull(equals(af, 1), 0), 0)) AS step_2, + countIf(ifNull(ifNull(equals(af, 2), 0), 0)) AS step_3, + groupArrayIf(timings[1], ifNull(greater(timings[1], 0), 0)) AS step_1_conversion_times, + groupArrayIf(timings[2], ifNull(greater(timings[2], 0), 0)) AS step_2_conversion_times, + rowNumberInBlock() AS row_number, + if(ifNull(less(row_number, 25), 0), breakdown, 'Other') AS final_prop + FROM + (SELECT arrayJoin(aggregate_funnel(3, 1209600, 'first_touch', 'ordered', groupUniqArray(prop), arraySort(t -> t.1, groupArray(tuple(accurateCastOrNull(timestamp, 'Float64'), prop, arrayFilter(x -> ifNull(notEquals(x, 0), 1), [multiply(1, step_0), multiply(2, step_1), multiply(3, step_2)])))))) AS af_tuple, + af_tuple.1 AS af, + af_tuple.2 AS breakdown, + af_tuple.3 AS timings + FROM + (SELECT timestamp AS timestamp, + aggregation_target AS aggregation_target, + step_0 AS step_0, + latest_0 AS latest_0, + step_1 AS step_1, + latest_1 AS latest_1, + step_2 AS step_2, + latest_2 AS latest_2, + exclusion_0 AS exclusion_0, + exclusion_1 AS exclusion_1, + exclusion_2 AS exclusion_2, + prop_basic AS prop_basic, + prop, + prop_vals AS prop_vals, + prop_vals AS prop + FROM + (SELECT toTimeZone(e.timestamp, 'UTC') AS timestamp, + e__pdi.person_id AS aggregation_target, + if(equals(e.event, 'sign up'), 1, 0) AS step_0, + if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, + if(equals(e.event, 'play movie'), 1, 0) AS step_1, + if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1, + if(equals(e.event, 'buy'), 1, 0) AS step_2, + if(ifNull(equals(step_2, 1), 0), timestamp, NULL) AS latest_2, + 0 AS exclusion_0, + 0 AS exclusion_1, + 0 AS exclusion_2, + ifNull(toString(e__group_0.properties___industry), '') AS prop_basic, + prop_basic AS prop, + argMinIf(prop, timestamp, isNotNull(prop)) OVER (PARTITION BY aggregation_target) AS prop_vals + FROM events AS e + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + LEFT JOIN + (SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(groups.group_properties, 'industry'), ''), 'null'), '^"|"$', ''), toTimeZone(groups._timestamp, 'UTC')) AS properties___industry, + groups.group_type_index AS index, + groups.group_key AS key + FROM groups + WHERE and(equals(groups.team_id, 2), ifNull(equals(index, 0), 0)) + GROUP BY groups.group_type_index, + groups.group_key) AS e__group_0 ON equals(e.`$group_0`, e__group_0.key) + WHERE and(equals(e.team_id, 2), and(and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-01 00:00:00.000000', 6, 'UTC')), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('2020-01-08 23:59:59.999999', 6, 'UTC'))), in(e.event, tuple('buy', 'play movie', 'sign up'))), or(ifNull(equals(step_0, 1), 0), ifNull(equals(step_1, 1), 0), ifNull(equals(step_2, 1), 0))))) + GROUP BY aggregation_target + HAVING ifNull(greaterOrEquals(af, 0), 0)) + GROUP BY breakdown + ORDER BY step_3 DESC, step_2 DESC, step_1 DESC) + GROUP BY final_prop + LIMIT 100 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=23622320128, + allow_experimental_analyzer=1 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group.1 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group.2 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner , + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time , + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps , + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time, + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 , + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + if(latest_2 < latest_1, NULL, latest_2) as latest_2 , + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (step_0 = 1 + OR step_1 = 1 + OR step_2 = 1) ))))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [1, 2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('finance')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group.3 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group.4 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner , + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time , + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps , + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time, + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 , + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + if(latest_2 < latest_1, NULL, latest_2) as latest_2 , + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (step_0 = 1 + OR step_1 = 1 + OR step_2 = 1) ))))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('finance')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group.5 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group.6 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner , + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time , + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps , + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time, + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 , + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + if(latest_2 < latest_1, NULL, latest_2) as latest_2 , + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (step_0 = 1 + OR step_1 = 1 + OR step_2 = 1) ))))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [1, 2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('technology')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group.7 + ''' + + SELECT replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS value, + count(*) as count + FROM events e + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + GROUP BY value + ORDER BY count DESC, value DESC + LIMIT 26 + OFFSET 0 + ''' +# --- +# name: TestFunnelGroupBreakdownUDF.test_funnel_breakdown_group.8 + ''' + + SELECT aggregation_target AS actor_id + FROM + (SELECT aggregation_target, + steps, + avg(step_1_conversion_time) step_1_average_conversion_time_inner, + avg(step_2_conversion_time) step_2_average_conversion_time_inner, + median(step_1_conversion_time) step_1_median_conversion_time_inner, + median(step_2_conversion_time) step_2_median_conversion_time_inner , + prop + FROM + (SELECT aggregation_target, + steps, + max(steps) over (PARTITION BY aggregation_target, + prop) as max_steps, + step_1_conversion_time, + step_2_conversion_time , + prop + FROM + (SELECT *, + if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY + AND latest_1 <= latest_2 + AND latest_2 <= latest_0 + INTERVAL 7 DAY, 3, if(latest_0 <= latest_1 + AND latest_1 <= latest_0 + INTERVAL 7 DAY, 2, 1)) AS steps , + if(isNotNull(latest_1) + AND latest_1 <= latest_0 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time, + if(isNotNull(latest_2) + AND latest_2 <= latest_1 + INTERVAL 7 DAY, dateDiff('second', toDateTime(latest_1), toDateTime(latest_2)), NULL) step_2_conversion_time, + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 , + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + latest_1, + step_2, + if(latest_2 < latest_1, NULL, latest_2) as latest_2 , + prop + FROM + (SELECT aggregation_target, timestamp, step_0, + latest_0, + step_1, + min(latest_1) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_1, + step_2, + min(latest_2) over (PARTITION by aggregation_target, + prop + ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_2 , + if(has(['technology', 'finance'], prop), prop, 'Other') as prop + FROM + (SELECT *, + prop_vals as prop + FROM + (SELECT e.timestamp as timestamp, + pdi.person_id as aggregation_target, + pdi.person_id as person_id, + if(event = 'sign up', 1, 0) as step_0, + if(step_0 = 1, timestamp, null) as latest_0, + if(event = 'play movie', 1, 0) as step_1, + if(step_1 = 1, timestamp, null) as latest_1, + if(event = 'buy', 1, 0) as step_2, + if(step_2 = 1, timestamp, null) as latest_2, + replaceRegexpAll(JSONExtractRaw(group_properties_0, 'industry'), '^"|"$', '') AS prop_basic, + prop_basic as prop, + argMinIf(prop, timestamp, isNotNull(prop)) over (PARTITION by aggregation_target) as prop_vals + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + AND distinct_id IN + (SELECT distinct_id + FROM events + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') ) + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + LEFT JOIN + (SELECT group_key, + argMax(group_properties, _timestamp) AS group_properties_0 + FROM groups + WHERE team_id = 2 + AND group_type_index = 0 + GROUP BY group_key) groups_0 ON "$group_0" == groups_0.group_key + WHERE team_id = 2 + AND event IN ['buy', 'play movie', 'sign up'] + AND toTimeZone(timestamp, 'UTC') >= toDateTime('2020-01-01 00:00:00', 'UTC') + AND toTimeZone(timestamp, 'UTC') <= toDateTime('2020-01-08 23:59:59', 'UTC') + AND (step_0 = 1 + OR step_1 = 1 + OR step_2 = 1) ))))) + WHERE step_0 = 1 )) + GROUP BY aggregation_target, + steps, + prop + HAVING steps = max_steps) + WHERE steps IN [2, 3] + AND arrayFlatten(array(prop)) = arrayFlatten(array('technology')) + ORDER BY aggregation_target + LIMIT 100 + OFFSET 0 SETTINGS max_ast_elements=1000000, + max_expanded_ast_elements=1000000 + ''' +# --- diff --git a/posthog/hogql_queries/insights/funnels/test/test_funnel.py b/posthog/hogql_queries/insights/funnels/test/test_funnel.py index 77033100a5009..575f76992ebf3 100644 --- a/posthog/hogql_queries/insights/funnels/test/test_funnel.py +++ b/posthog/hogql_queries/insights/funnels/test/test_funnel.py @@ -1,6 +1,7 @@ import uuid from datetime import datetime from typing import cast +from unittest.mock import patch, Mock from django.test import override_settings from freezegun import freeze_time @@ -68,6 +69,7 @@ def _create_action(**kwargs): return action +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) class TestFunnelBreakdown( ClickhouseTestMixin, funnel_breakdown_test_factory( # type: ignore @@ -81,6 +83,7 @@ class TestFunnelBreakdown( pass +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) class TestFunnelGroupBreakdown( ClickhouseTestMixin, funnel_breakdown_group_test_factory( # type: ignore @@ -91,6 +94,7 @@ class TestFunnelGroupBreakdown( pass +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) class TestFunnelConversionTime( ClickhouseTestMixin, funnel_conversion_time_test_factory(FunnelOrderType.ORDERED, ClickhouseFunnelActors), # type: ignore @@ -2460,10 +2464,14 @@ def test_advanced_funnel_exclusions_between_steps(self): query = cast(FunnelsQuery, filter_to_query(filters)) results = FunnelsQueryRunner(query=query, team=self.team).calculate().results - self.assertEqual(results[0]["name"], "user signed up") - self.assertEqual(results[0]["count"], 0) - - self.assertEqual(results[4]["count"], 0) + # There should be no events. UDF funnels returns an empty array and says "no events" + # Old style funnels returns a count of 0 + try: + self.assertEqual([], results) + except AssertionError: + self.assertEqual(results[0]["name"], "user signed up") + self.assertEqual(results[0]["count"], 0) + self.assertEqual(results[4]["count"], 0) self.assertCountEqual(self._get_actor_ids_at_step(filters, 1), []) @@ -3290,7 +3298,7 @@ def test_timezones(self): # event _create_person(distinct_ids=["user_1"], team_id=self.team.pk) - #  this event shouldn't appear as in US/Pacific this would be the previous day + # this event shouldn't appear as in US/Pacific this would be the previous day _create_event( team=self.team, event="user signed up", @@ -3300,9 +3308,13 @@ def test_timezones(self): query = cast(FunnelsQuery, filter_to_query(filters)) results = FunnelsQueryRunner(query=query, team=self.team).calculate().results - - self.assertEqual(results[0]["name"], "user signed up") - self.assertEqual(results[0]["count"], 0) + # There should be no events. UDF funnels returns an empty array and says "no events" + # Old style funnels returns a count of 0 + try: + self.assertEqual([], results) + except AssertionError: + self.assertEqual(results[0]["name"], "user signed up") + self.assertEqual(results[0]["count"], 0) def test_funnel_with_sampling(self): action_play_movie = Action.objects.create( @@ -4095,6 +4107,7 @@ def test_first_time_for_user_funnel_multiple_ids(self): return TestGetFunnel +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) class TestFOSSFunnel(funnel_test_factory(Funnel, _create_event, _create_person)): # type: ignore maxDiff = None diff --git a/posthog/hogql_queries/insights/funnels/test/test_funnel_strict.py b/posthog/hogql_queries/insights/funnels/test/test_funnel_strict.py index e146547285fae..7be35d81324d1 100644 --- a/posthog/hogql_queries/insights/funnels/test/test_funnel_strict.py +++ b/posthog/hogql_queries/insights/funnels/test/test_funnel_strict.py @@ -1,5 +1,6 @@ from datetime import datetime from typing import cast +from unittest.mock import Mock, patch from posthog.constants import INSIGHT_FUNNELS, FunnelOrderType from posthog.hogql_queries.insights.funnels.funnels_query_runner import FunnelsQueryRunner @@ -38,7 +39,7 @@ def _create_action(**kwargs): return action -class TestFunnelStrictStepsBreakdown( +class BaseTestFunnelStrictStepsBreakdown( ClickhouseTestMixin, funnel_breakdown_test_factory( # type: ignore FunnelOrderType.STRICT, @@ -178,7 +179,7 @@ def test_strict_breakdown_events_with_multiple_properties(self): self.assertCountEqual(self._get_actor_ids_at_step(filters, 2, ["Safari"]), [people["person2"].uuid]) -class TestStrictFunnelGroupBreakdown( +class BaseTestStrictFunnelGroupBreakdown( ClickhouseTestMixin, funnel_breakdown_group_test_factory( # type: ignore FunnelOrderType.STRICT, @@ -188,7 +189,7 @@ class TestStrictFunnelGroupBreakdown( pass -class TestFunnelStrictStepsConversionTime( +class BaseTestFunnelStrictStepsConversionTime( ClickhouseTestMixin, funnel_conversion_time_test_factory(FunnelOrderType.ORDERED, ClickhouseFunnelStrictActors), # type: ignore ): @@ -196,7 +197,7 @@ class TestFunnelStrictStepsConversionTime( pass -class TestFunnelStrictSteps(ClickhouseTestMixin, APIBaseTest): +class BaseTestFunnelStrictSteps(ClickhouseTestMixin, APIBaseTest): maxDiff = None def _get_actor_ids_at_step(self, filter, funnel_step, breakdown_value=None): @@ -624,3 +625,23 @@ def test_basic_strict_funnel_conversion_times(self): self._get_actor_ids_at_step(filters, 3), [person3_stopped_after_insight_view.uuid], ) + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) +class TestFunnelStrictStepsBreakdown(BaseTestFunnelStrictStepsBreakdown): + pass + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) +class TestFunnelStrictSteps(BaseTestFunnelStrictSteps): + pass + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) +class TestStrictFunnelGroupBreakdown(BaseTestStrictFunnelGroupBreakdown): + pass + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) +class TestFunnelStrictStepsConversionTime(BaseTestFunnelStrictStepsConversionTime): + pass diff --git a/posthog/hogql_queries/insights/funnels/test/test_funnel_strict_udf.py b/posthog/hogql_queries/insights/funnels/test/test_funnel_strict_udf.py new file mode 100644 index 0000000000000..178e329d3748e --- /dev/null +++ b/posthog/hogql_queries/insights/funnels/test/test_funnel_strict_udf.py @@ -0,0 +1,28 @@ +from unittest.mock import Mock, patch + +from posthog.hogql_queries.insights.funnels.test.test_funnel_strict import ( + BaseTestFunnelStrictStepsBreakdown, + BaseTestFunnelStrictSteps, + BaseTestStrictFunnelGroupBreakdown, + BaseTestFunnelStrictStepsConversionTime, +) + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestFunnelStrictStepsBreakdown(BaseTestFunnelStrictStepsBreakdown): + pass + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestFunnelStrictSteps(BaseTestFunnelStrictSteps): + pass + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestStrictFunnelGroupBreakdown(BaseTestStrictFunnelGroupBreakdown): + pass + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestFunnelStrictStepsConversionTime(BaseTestFunnelStrictStepsConversionTime): + pass diff --git a/posthog/hogql_queries/insights/funnels/test/test_funnel_trends.py b/posthog/hogql_queries/insights/funnels/test/test_funnel_trends.py index 7b86e305ca89e..55a1f8660d0ca 100644 --- a/posthog/hogql_queries/insights/funnels/test/test_funnel_trends.py +++ b/posthog/hogql_queries/insights/funnels/test/test_funnel_trends.py @@ -1,5 +1,6 @@ from datetime import date, datetime, timedelta from typing import cast +from unittest.mock import patch, Mock from zoneinfo import ZoneInfo from freezegun.api import freeze_time @@ -23,7 +24,7 @@ FORMAT_TIME_DAY_END = "%Y-%m-%d 23:59:59" -class TestFunnelTrends(ClickhouseTestMixin, APIBaseTest): +class BaseTestFunnelTrends(ClickhouseTestMixin, APIBaseTest): maxDiff = None def _get_actors_at_step(self, filter, entrance_period_start, drop_off): @@ -130,43 +131,43 @@ def test_only_one_user_reached_one_step(self): [ { "reached_to_step_count": 0, - "conversion_rate": 0, + "conversion_rate": 0.0, "reached_from_step_count": 1, "timestamp": datetime(2021, 6, 7, 0, 0).replace(tzinfo=ZoneInfo("UTC")), }, { "reached_to_step_count": 0, - "conversion_rate": 0, + "conversion_rate": 0.0, "reached_from_step_count": 0, "timestamp": datetime(2021, 6, 8, 0, 0).replace(tzinfo=ZoneInfo("UTC")), }, { "reached_to_step_count": 0, - "conversion_rate": 0, + "conversion_rate": 0.0, "reached_from_step_count": 0, "timestamp": datetime(2021, 6, 9, 0, 0).replace(tzinfo=ZoneInfo("UTC")), }, { "reached_to_step_count": 0, - "conversion_rate": 0, + "conversion_rate": 0.0, "reached_from_step_count": 0, "timestamp": datetime(2021, 6, 10, 0, 0).replace(tzinfo=ZoneInfo("UTC")), }, { "reached_to_step_count": 0, - "conversion_rate": 0, + "conversion_rate": 0.0, "reached_from_step_count": 0, "timestamp": datetime(2021, 6, 11, 0, 0).replace(tzinfo=ZoneInfo("UTC")), }, { "reached_to_step_count": 0, - "conversion_rate": 0, + "conversion_rate": 0.0, "reached_from_step_count": 0, "timestamp": datetime(2021, 6, 12, 0, 0).replace(tzinfo=ZoneInfo("UTC")), }, { "reached_to_step_count": 0, - "conversion_rate": 0, + "conversion_rate": 0.0, "reached_from_step_count": 0, "timestamp": datetime(2021, 6, 13, 0, 0).replace(tzinfo=ZoneInfo("UTC")), }, @@ -1611,3 +1612,8 @@ def test_parses_breakdown_correctly(self): results = FunnelsQueryRunner(query=query, team=self.team).calculate().results self.assertEqual(len(results), 1) + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=False)) +class TestFunnelTrends(BaseTestFunnelTrends): + pass diff --git a/posthog/hogql_queries/insights/funnels/test/test_funnel_trends_udf.py b/posthog/hogql_queries/insights/funnels/test/test_funnel_trends_udf.py new file mode 100644 index 0000000000000..6965222b749f5 --- /dev/null +++ b/posthog/hogql_queries/insights/funnels/test/test_funnel_trends_udf.py @@ -0,0 +1,8 @@ +from unittest.mock import patch, Mock + +from posthog.hogql_queries.insights.funnels.test.test_funnel_trends import BaseTestFunnelTrends + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestFunnelTrendsUDF(BaseTestFunnelTrends): + pass diff --git a/posthog/hogql_queries/insights/funnels/test/test_funnel_udf.py b/posthog/hogql_queries/insights/funnels/test/test_funnel_udf.py new file mode 100644 index 0000000000000..2844d4b7792d4 --- /dev/null +++ b/posthog/hogql_queries/insights/funnels/test/test_funnel_udf.py @@ -0,0 +1,66 @@ +from unittest.mock import patch, Mock + +from posthog.constants import FunnelOrderType +from posthog.hogql_queries.insights.funnels import Funnel +from posthog.hogql_queries.insights.funnels.test.breakdown_cases import ( + funnel_breakdown_test_factory, + funnel_breakdown_group_test_factory, +) +from posthog.models import Action +from posthog.queries.funnels import ClickhouseFunnelActors +from posthog.test.base import ( + ClickhouseTestMixin, + _create_event, + _create_person, +) +from test_funnel import funnel_test_factory +from posthog.hogql_queries.insights.funnels.test.conversion_time_cases import ( + funnel_conversion_time_test_factory, +) + + +def _create_action(**kwargs): + team = kwargs.pop("team") + name = kwargs.pop("name") + properties = kwargs.pop("properties", {}) + action = Action.objects.create(team=team, name=name, steps_json=[{"event": name, "properties": properties}]) + return action + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestFunnelBreakdownUDF( + ClickhouseTestMixin, + funnel_breakdown_test_factory( # type: ignore + FunnelOrderType.ORDERED, + ClickhouseFunnelActors, + _create_action, + _create_person, + ), +): + maxDiff = None + pass + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestFunnelGroupBreakdownUDF( + ClickhouseTestMixin, + funnel_breakdown_group_test_factory( # type: ignore + FunnelOrderType.ORDERED, + ClickhouseFunnelActors, + ), +): + pass + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestFOSSFunnelUDF(funnel_test_factory(Funnel, _create_event, _create_person)): # type: ignore + maxDiff = None + + +@patch("posthoganalytics.feature_enabled", new=Mock(return_value=True)) +class TestFunnelConversionTimeUDF( + ClickhouseTestMixin, + funnel_conversion_time_test_factory(FunnelOrderType.ORDERED, ClickhouseFunnelActors), # type: ignore +): + maxDiff = None + pass diff --git a/posthog/hogql_queries/insights/funnels/utils.py b/posthog/hogql_queries/insights/funnels/utils.py index d5c968a913494..31c31fa9b361d 100644 --- a/posthog/hogql_queries/insights/funnels/utils.py +++ b/posthog/hogql_queries/insights/funnels/utils.py @@ -5,15 +5,18 @@ from rest_framework.exceptions import ValidationError -def get_funnel_order_class(funnelsFilter: FunnelsFilter): +def get_funnel_order_class(funnelsFilter: FunnelsFilter, use_udf=False): from posthog.hogql_queries.insights.funnels import ( Funnel, + FunnelUDF, FunnelStrict, FunnelUnordered, ) if funnelsFilter.funnelOrderType == StepOrderValue.UNORDERED: return FunnelUnordered + elif use_udf: + return FunnelUDF elif funnelsFilter.funnelOrderType == StepOrderValue.STRICT: return FunnelStrict return Funnel diff --git a/posthog/hogql_queries/insights/utils/utils.py b/posthog/hogql_queries/insights/utils/utils.py index 747d7e2b6ca5a..15689aba7927e 100644 --- a/posthog/hogql_queries/insights/utils/utils.py +++ b/posthog/hogql_queries/insights/utils/utils.py @@ -10,3 +10,8 @@ def get_start_of_interval_hogql(interval: str, *, team: Team, source: Optional[a if trunc_func == "toStartOfWeek": trunc_func_args.append(ast.Constant(value=int((WeekStartDay(team.week_start_day or 0)).clickhouse_mode))) return ast.Call(name=trunc_func, args=trunc_func_args) + + +def get_start_of_interval_hogql_str(interval: str, *, team: Team, source: str) -> str: + trunc_func = get_trunc_func_ch(interval) + return f"{trunc_func}({source}{f', {int((WeekStartDay(team.week_start_day or 0)).clickhouse_mode)}' if trunc_func == 'toStartOfWeek' else ''})" diff --git a/posthog/hogql_queries/legacy_compatibility/feature_flag.py b/posthog/hogql_queries/legacy_compatibility/feature_flag.py index 6b4a6e0e22a0b..697e479f6031f 100644 --- a/posthog/hogql_queries/legacy_compatibility/feature_flag.py +++ b/posthog/hogql_queries/legacy_compatibility/feature_flag.py @@ -21,3 +21,24 @@ def hogql_insights_replace_filters(team: Team) -> bool: only_evaluate_locally=True, send_feature_flag_events=False, ) + + +def insight_funnels_use_udf(team: Team) -> bool: + return posthoganalytics.feature_enabled( + "insight-funnels-use-udf", + str(team.uuid), + groups={ + "organization": str(team.organization_id), + "project": str(team.id), + }, + group_properties={ + "organization": { + "id": str(team.organization_id), + }, + "project": { + "id": str(team.id), + }, + }, + only_evaluate_locally=False, + send_feature_flag_events=False, + ) diff --git a/posthog/schema.py b/posthog/schema.py index bf7662b7a9e5b..aaf418fae271b 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -1768,6 +1768,7 @@ class CachedFunnelsQueryResponse(BaseModel): description="Query error. Returned only if 'explain' or `modifiers.debug` is true. Throws an error otherwise.", ) hogql: Optional[str] = Field(default=None, description="Generated HogQL query.") + isUdf: Optional[bool] = None is_cached: bool last_refresh: AwareDatetime modifiers: Optional[HogQLQueryModifiers] = Field( @@ -2550,6 +2551,7 @@ class FunnelsQueryResponse(BaseModel): description="Query error. Returned only if 'explain' or `modifiers.debug` is true. Throws an error otherwise.", ) hogql: Optional[str] = Field(default=None, description="Generated HogQL query.") + isUdf: Optional[bool] = None modifiers: Optional[HogQLQueryModifiers] = Field( default=None, description="Modifiers used when performing the query" ) @@ -3329,6 +3331,7 @@ class QueryResponseAlternative25(BaseModel): description="Query error. Returned only if 'explain' or `modifiers.debug` is true. Throws an error otherwise.", ) hogql: Optional[str] = Field(default=None, description="Generated HogQL query.") + isUdf: Optional[bool] = None modifiers: Optional[HogQLQueryModifiers] = Field( default=None, description="Modifiers used when performing the query" ) @@ -4642,6 +4645,7 @@ class FunnelsFilter(BaseModel): funnelWindowIntervalUnit: Optional[FunnelConversionWindowTimeUnit] = FunnelConversionWindowTimeUnit.DAY hiddenLegendBreakdowns: Optional[list[str]] = None layout: Optional[FunnelLayout] = FunnelLayout.VERTICAL + useUdf: Optional[bool] = None class HasPropertiesNode(RootModel[Union[EventsNode, EventsQuery, PersonsNode]]): diff --git a/posthog/test/user_scripts/__init__.py b/posthog/test/user_scripts/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/posthog/test/user_scripts/test_aggregate_funnel.py b/posthog/test/user_scripts/test_aggregate_funnel.py new file mode 100644 index 0000000000000..2b20929002f83 --- /dev/null +++ b/posthog/test/user_scripts/test_aggregate_funnel.py @@ -0,0 +1,4206 @@ +from typing import Any + +from posthog.user_scripts.aggregate_funnel import calculate_funnel_from_user_events + + +def test(): + y = [ + [(1577973600.0, "", [1]), (1577980800.0, "", [2]), (1577984400.0, "", [3])], + [(1577880000.0, "", [1]), (1577883600.0, "", [2]), (1577890800.0, "", [3])], + [(1577973600.0, "", [1]), (1577980800.0, "", [2])], + ] + + for x in y: + calculate_funnel_from_user_events(3, 1209600, "first_touch", "strict", [""], x) + + +def test2(): + a: list[Any] = [ + [(1720051532.484019, [], [1, 2, 3, 4, 5, 6])], + [(1720105713.331995, [], [1, 2, 3, 4, 5, 6])], + [(1720329565.847159, [], [1, 2, 3, 4, 5, 6])], + [ + (1720186008.567886, [], [1, 2, 3, 4, 5, 6]), + (1720326697.522923, [], [1, 2, 3, 4, 5, 6]), + (1720482974.426314, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720327526.250804, [], [1, 2, 3, 4, 5, 6]), (1720497558.23414, [], [1, 2, 3, 4, 5, 6])], + [ + (1719979738.339271, [], [1, 2, 3, 4, 5, 6]), + (1720025384.961105, [], [1, 2, 3, 4, 5, 6]), + (1720504618.55439, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720136408.619257, [], [1, 2, 3, 4, 5, 6]), + (1720136458.666712, [], [1, 2, 3, 4, 5, 6]), + (1720136460.776795, [], [1, 2, 3, 4, 5, 6]), + (1720136463.761667, [], [1, 2, 3, 4, 5, 6]), + (1720136465.813823, [], [1, 2, 3, 4, 5, 6]), + (1720153490.167176, [], [1, 2, 3, 4, 5, 6]), + (1720153611.687424, [], [1, 2, 3, 4, 5, 6]), + (1720153613.813758, [], [1, 2, 3, 4, 5, 6]), + (1720221238.819741, [], [1, 2, 3, 4, 5, 6]), + (1720221389.412602, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720234125.717526, [], [1, 2, 3, 4, 5, 6])], + [ + (1720245095.229565, [], [1, 2, 3, 4, 5, 6]), + (1720396821.910578, [], [1, 2, 3, 4, 5, 6]), + (1720502554.801179, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720237286.585886, [], [1, 2, 3, 4, 5, 6]), (1720492842.0014, [], [1, 2, 3, 4, 5, 6])], + [(1720145259.463577, [], [1, 2, 3, 4, 5, 6])], + [(1720173037.951133, [], [1, 2, 3, 4, 5, 6]), (1720398629.834351, [], [1, 2, 3, 4, 5, 6])], + [(1720576515.470242, [], [1, 2, 3, 4, 5, 6])], + [(1720488634.248776, [], [1, 2, 3, 4, 5, 6])], + [ + (1719966672.507604, [], [1, 2, 3, 4, 5, 6]), + (1720379305.230415, [], [1, 2, 3, 4, 5, 6]), + (1720485725.30467, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720056848.984567, [], [1, 2, 3, 4, 5, 6]), + (1720234634.97164, [], [1, 2, 3, 4, 5, 6]), + (1720326372.083307, [], [1, 2, 3, 4, 5, 6]), + (1720487169.130815, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719979630.05111, [], [1, 2, 3, 4, 5, 6])], + [(1720067082.599895, [], [1, 2, 3, 4, 5, 6])], + [(1720065455.678956, [], [1, 2, 3, 4, 5, 6])], + [(1720141594.235645, [], [1, 2, 3, 4, 5, 6]), (1720479638.868071, [], [1, 2, 3, 4, 5, 6])], + [(1720172558.775714, [], [1, 2, 3, 4, 5, 6]), (1720589944.987293, [], [1, 2, 3, 4, 5, 6])], + [(1720240665.403432, [], [1, 2, 3, 4, 5, 6]), (1720403456.771406, [], [1, 2, 3, 4, 5, 6])], + [ + (1720151433.593775, [], [1, 2, 3, 4, 5, 6]), + (1720397705.729741, [], [1, 2, 3, 4, 5, 6]), + (1720407937.654196, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720063019.413544, [], [1, 2, 3, 4, 5, 6]), + (1720230670.007217, [], [1, 2, 3, 4, 5, 6]), + (1720572529.432945, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720062676.566511, [], [1, 2, 3, 4, 5, 6]), + (1720062768.411832, [], [1, 2, 3, 4, 5, 6]), + (1720062770.476807, [], [1, 2, 3, 4, 5, 6]), + (1720062771.394614, [], [1, 2, 3, 4, 5, 6]), + (1720156065.434007, [], [1, 2, 3, 4, 5, 6]), + (1720156180.339675, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720053274.311851, [], [1, 2, 3, 4, 5, 6]), (1720574916.370766, [], [1, 2, 3, 4, 5, 6])], + [(1720403600.103166, [], [1, 2, 3, 4, 5, 6])], + [(1720070524.509752, [], [1, 2, 3, 4, 5, 6]), (1720330735.128105, [], [1, 2, 3, 4, 5, 6])], + [ + (1719980823.099161, [], [1, 2, 3, 4, 5, 6]), + (1720109783.667678, [], [1, 2, 3, 4, 5, 6]), + (1720488536.75761, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720120539.020908, [], [1, 2, 3, 4, 5, 6]), + (1720235556.263511, [], [1, 2, 3, 4, 5, 6]), + (1720404531.8727, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720461710.602542, [], [1, 2, 3, 4, 5, 6])], + [(1720142147.27027, [], [1, 2, 3, 4, 5, 6]), (1720463509.177443, [], [1, 2, 3, 4, 5, 6])], + [(1720609249.094945, [], [1, 2, 3, 4, 5, 6])], + [ + (1720061653.09558, [], [1, 2, 3, 4, 5, 6]), + (1720331923.364924, [], [1, 2, 3, 4, 5, 6]), + (1720493879.336969, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719981455.944035, [], [1, 2, 3, 4, 5, 6]), + (1719981517.705732, [], [1, 2, 3, 4, 5, 6]), + (1719994503.81365, [], [1, 2, 3, 4, 5, 6]), + (1719994621.6397, [], [1, 2, 3, 4, 5, 6]), + (1719994623.698368, [], [1, 2, 3, 4, 5, 6]), + (1719994627.578717, [], [1, 2, 3, 4, 5, 6]), + (1719994629.663136, [], [1, 2, 3, 4, 5, 6]), + (1719994631.068061, [], [1, 2, 3, 4, 5, 6]), + (1719994633.142381, [], [1, 2, 3, 4, 5, 6]), + (1720027463.767433, [], [1, 2, 3, 4, 5, 6]), + (1720027502.563106, [], [1, 2, 3, 4, 5, 6]), + (1720027504.670674, [], [1, 2, 3, 4, 5, 6]), + (1720057341.723675, [], [1, 2, 3, 4, 5, 6]), + (1720057343.781939, [], [1, 2, 3, 4, 5, 6]), + (1720145087.601179, [], [1, 2, 3, 4, 5, 6]), + (1720145089.680587, [], [1, 2, 3, 4, 5, 6]), + (1720243008.749524, [], [1, 2, 3, 4, 5, 6]), + (1720243068.439551, [], [1, 2, 3, 4, 5, 6]), + (1720318425.097956, [], [1, 2, 3, 4, 5, 6]), + (1720318427.16319, [], [1, 2, 3, 4, 5, 6]), + (1720318432.221956, [], [1, 2, 3, 4, 5, 6]), + (1720318434.329525, [], [1, 2, 3, 4, 5, 6]), + (1720418148.778433, [], [1, 2, 3, 4, 5, 6]), + (1720418150.861104, [], [1, 2, 3, 4, 5, 6]), + (1720488202.399436, [], [1, 2, 3, 4, 5, 6]), + (1720488212.260625, [], [1, 2, 3, 4, 5, 6]), + (1720488214.365566, [], [1, 2, 3, 4, 5, 6]), + (1720572393.815712, [], [1, 2, 3, 4, 5, 6]), + (1720613041.916708, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720057097.342555, [], [1, 2, 3, 4, 5, 6]), + (1720317039.904735, [], [1, 2, 3, 4, 5, 6]), + (1720483178.967836, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720181661.187285, [], [1, 2, 3, 4, 5, 6])], + [(1720199552.174104, [], [1, 2, 3, 4, 5, 6]), (1720568803.062761, [], [1, 2, 3, 4, 5, 6])], + [ + (1720247391.136136, [], [1, 2, 3, 4, 5, 6]), + (1720410696.088339, [], [1, 2, 3, 4, 5, 6]), + (1720599399.171422, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720312357.61565, [], [1, 2, 3, 4, 5, 6])], + [(1720052008.103911, [], [1, 2, 3, 4, 5, 6]), (1720400141.042944, [], [1, 2, 3, 4, 5, 6])], + [(1720210751.331903, [], [1, 2, 3, 4, 5, 6]), (1720503558.839248, [], [1, 2, 3, 4, 5, 6])], + [ + (1720241352.747626, [], [1, 2, 3, 4, 5, 6]), + (1720321677.766712, [], [1, 2, 3, 4, 5, 6]), + (1720409706.122052, [], [1, 2, 3, 4, 5, 6]), + (1720519728.980875, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719977467.931514, [], [1, 2, 3, 4, 5, 6]), (1720568695.132969, [], [1, 2, 3, 4, 5, 6])], + [(1720071302.148667, [], [1, 2, 3, 4, 5, 6]), (1720238096.092618, [], [1, 2, 3, 4, 5, 6])], + [(1720057437.769059, [], [1, 2, 3, 4, 5, 6])], + [ + (1720221473.506037, [], [1, 2, 3, 4, 5, 6]), + (1720348129.55283, [], [1, 2, 3, 4, 5, 6]), + (1720482938.000889, [], [1, 2, 3, 4, 5, 6]), + (1720576755.035308, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720235902.362301, [], [1, 2, 3, 4, 5, 6])], + [(1720024782.723245, [], [1, 2, 3, 4, 5, 6])], + [(1720070158.75827, [], [1, 2, 3, 4, 5, 6])], + [ + (1720000651.858702, [], [1, 2, 3, 4, 5, 6]), + (1720244645.395695, [], [1, 2, 3, 4, 5, 6]), + (1720411107.259775, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720191076.938109, [], [1, 2, 3, 4, 5, 6]), + (1720322967.081356, [], [1, 2, 3, 4, 5, 6]), + (1720323158.146239, [], [1, 2, 3, 4, 5, 6]), + (1720323172.234517, [], [1, 2, 3, 4, 5, 6]), + (1720323206.302768, [], [1, 2, 3, 4, 5, 6]), + (1720323313.146535, [], [1, 2, 3, 4, 5, 6]), + (1720323364.511129, [], [1, 2, 3, 4, 5, 6]), + (1720323458.282407, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720065260.493236, [], [1, 2, 3, 4, 5, 6]), + (1720065334.608797, [], [1, 2, 3, 4, 5, 6]), + (1720141650.234015, [], [1, 2, 3, 4, 5, 6]), + (1720141749.547675, [], [1, 2, 3, 4, 5, 6]), + (1720141751.641012, [], [1, 2, 3, 4, 5, 6]), + (1720154278.705276, [], [1, 2, 3, 4, 5, 6]), + (1720154280.760532, [], [1, 2, 3, 4, 5, 6]), + (1720229499.077048, [], [1, 2, 3, 4, 5, 6]), + (1720229572.436301, [], [1, 2, 3, 4, 5, 6]), + (1720259010.216367, [], [1, 2, 3, 4, 5, 6]), + (1720259234.335094, [], [1, 2, 3, 4, 5, 6]), + (1720259236.42606, [], [1, 2, 3, 4, 5, 6]), + (1720318686.64822, [], [1, 2, 3, 4, 5, 6]), + (1720318843.45613, [], [1, 2, 3, 4, 5, 6]), + (1720318845.509738, [], [1, 2, 3, 4, 5, 6]), + (1720363113.918907, [], [1, 2, 3, 4, 5, 6]), + (1720363184.856665, [], [1, 2, 3, 4, 5, 6]), + (1720400947.604003, [], [1, 2, 3, 4, 5, 6]), + (1720400949.633637, [], [1, 2, 3, 4, 5, 6]), + (1720498232.720406, [], [1, 2, 3, 4, 5, 6]), + (1720498253.802808, [], [1, 2, 3, 4, 5, 6]), + (1720498255.908508, [], [1, 2, 3, 4, 5, 6]), + (1720586991.26782, [], [1, 2, 3, 4, 5, 6]), + (1720587059.251675, [], [1, 2, 3, 4, 5, 6]), + (1720587061.383312, [], [1, 2, 3, 4, 5, 6]), + (1720638042.876812, [], [1, 2, 3, 4, 5, 6]), + (1720638133.182092, [], [1, 2, 3, 4, 5, 6]), + (1720638135.286491, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719978486.488845, [], [1, 2, 3, 4, 5, 6]), (1720406010.994165, [], [1, 2, 3, 4, 5, 6])], + [(1720062931.526777, [], [1, 2, 3, 4, 5, 6])], + [ + (1720142330.725196, [], [1, 2, 3, 4, 5, 6]), + (1720238332.287607, [], [1, 2, 3, 4, 5, 6]), + (1720404745.279674, [], [1, 2, 3, 4, 5, 6]), + (1720577388.350881, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719973721.653682, [], [1, 2, 3, 4, 5, 6]), + (1720045556.714061, [], [1, 2, 3, 4, 5, 6]), + (1720286335.062706, [], [1, 2, 3, 4, 5, 6]), + (1720408637.593505, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719980831.540691, [], [1, 2, 3, 4, 5, 6]), + (1719980890.3872, [], [1, 2, 3, 4, 5, 6]), + (1719980892.464391, [], [1, 2, 3, 4, 5, 6]), + (1720027957.165729, [], [1, 2, 3, 4, 5, 6]), + (1720027959.212697, [], [1, 2, 3, 4, 5, 6]), + (1720055928.682589, [], [1, 2, 3, 4, 5, 6]), + (1720055930.747743, [], [1, 2, 3, 4, 5, 6]), + (1720138782.333308, [], [1, 2, 3, 4, 5, 6]), + (1720138842.547168, [], [1, 2, 3, 4, 5, 6]), + (1720138844.667335, [], [1, 2, 3, 4, 5, 6]), + (1720138846.225705, [], [1, 2, 3, 4, 5, 6]), + (1720153595.409537, [], [1, 2, 3, 4, 5, 6]), + (1720153694.792152, [], [1, 2, 3, 4, 5, 6]), + (1720222583.234486, [], [1, 2, 3, 4, 5, 6]), + (1720222651.732326, [], [1, 2, 3, 4, 5, 6]), + (1720222653.840022, [], [1, 2, 3, 4, 5, 6]), + (1720231129.338916, [], [1, 2, 3, 4, 5, 6]), + (1720231262.508465, [], [1, 2, 3, 4, 5, 6]), + (1720315761.130281, [], [1, 2, 3, 4, 5, 6]), + (1720315844.746953, [], [1, 2, 3, 4, 5, 6]), + (1720315846.831435, [], [1, 2, 3, 4, 5, 6]), + (1720406873.849957, [], [1, 2, 3, 4, 5, 6]), + (1720406879.412626, [], [1, 2, 3, 4, 5, 6]), + (1720485467.197531, [], [1, 2, 3, 4, 5, 6]), + (1720485486.733099, [], [1, 2, 3, 4, 5, 6]), + (1720485488.847143, [], [1, 2, 3, 4, 5, 6]), + (1720485492.354688, [], [1, 2, 3, 4, 5, 6]), + (1720485494.434006, [], [1, 2, 3, 4, 5, 6]), + (1720581292.87898, [], [1, 2, 3, 4, 5, 6]), + (1720581372.990683, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719965396.997192, [], [1, 2, 3, 4, 5, 6]), + (1720109840.37035, [], [1, 2, 3, 4, 5, 6]), + (1720224849.338664, [], [1, 2, 3, 4, 5, 6]), + (1720311680.960628, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720593841.069028, [], [1, 2, 3, 4, 5, 6])], + [(1720193711.631887, [], [1, 2, 3, 4, 5, 6]), (1720355386.424798, [], [1, 2, 3, 4, 5, 6])], + [(1720137394.637585, [], [1, 2, 3, 4, 5, 6]), (1720227526.549035, [], [1, 2, 3, 4, 5, 6])], + [(1720601724.604091, [], [1, 2, 3, 4, 5, 6])], + [(1720242114.286726, [], [1, 2, 3, 4, 5, 6]), (1720495287.866943, [], [1, 2, 3, 4, 5, 6])], + [ + (1719984060.976083, [], [1, 2, 3, 4, 5, 6]), + (1720233353.478142, [], [1, 2, 3, 4, 5, 6]), + (1720331822.027661, [], [1, 2, 3, 4, 5, 6]), + (1720499420.953642, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720327908.649598, [], [1, 2, 3, 4, 5, 6]), + (1720327957.004146, [], [1, 2, 3, 4, 5, 6]), + (1720328002.921775, [], [1, 2, 3, 4, 5, 6]), + (1720328054.34555, [], [1, 2, 3, 4, 5, 6]), + (1720394578.210396, [], [1, 2, 3, 4, 5, 6]), + (1720394668.213374, [], [1, 2, 3, 4, 5, 6]), + (1720394670.323029, [], [1, 2, 3, 4, 5, 6]), + (1720410358.68385, [], [1, 2, 3, 4, 5, 6]), + (1720410430.047079, [], [1, 2, 3, 4, 5, 6]), + (1720410432.093006, [], [1, 2, 3, 4, 5, 6]), + (1720485479.982584, [], [1, 2, 3, 4, 5, 6]), + (1720485552.035405, [], [1, 2, 3, 4, 5, 6]), + (1720485554.099771, [], [1, 2, 3, 4, 5, 6]), + (1720576265.461408, [], [1, 2, 3, 4, 5, 6]), + (1720576267.553332, [], [1, 2, 3, 4, 5, 6]), + (1720580196.882833, [], [1, 2, 3, 4, 5, 6]), + (1720580198.938581, [], [1, 2, 3, 4, 5, 6]), + (1720580201.66793, [], [1, 2, 3, 4, 5, 6]), + (1720580203.765767, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720512918.56325, [], [1, 2, 3, 4, 5, 6])], + [(1720587573.354151, [], [1, 2, 3, 4, 5, 6])], + [ + (1720059581.380866, [], [1, 2, 3, 4, 5, 6]), + (1720226059.821101, [], [1, 2, 3, 4, 5, 6]), + (1720569936.860231, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720483812.243251, [], [1, 2, 3, 4, 5, 6])], + [ + (1720047890.599986, [], [1, 2, 3, 4, 5, 6]), + (1720151933.610926, [], [1, 2, 3, 4, 5, 6]), + (1720426395.237753, [], [1, 2, 3, 4, 5, 6]), + (1720589584.479646, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720050613.849179, [], [1, 2, 3, 4, 5, 6]), + (1720183728.480776, [], [1, 2, 3, 4, 5, 6]), + (1720245305.222942, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719974717.393306, [], [1, 2, 3, 4, 5, 6]), + (1720238913.058213, [], [1, 2, 3, 4, 5, 6]), + (1720403863.202175, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720066616.245506, [], [1, 2, 3, 4, 5, 6]), (1720329802.077257, [], [1, 2, 3, 4, 5, 6])], + [(1720058023.220462, [], [1, 2, 3, 4, 5, 6]), (1720273250.296181, [], [1, 2, 3, 4, 5, 6])], + [(1720400521.741834, [], [1, 2, 3, 4, 5, 6])], + [(1720590006.799829, [], [1, 2, 3, 4, 5, 6])], + [ + (1719977522.311193, [], [1, 2, 3, 4, 5, 6]), + (1720394307.490994, [], [1, 2, 3, 4, 5, 6]), + (1720541599.758133, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720059720.64277, [], [1, 2, 3, 4, 5, 6]), + (1720225557.277258, [], [1, 2, 3, 4, 5, 6]), + (1720318879.528985, [], [1, 2, 3, 4, 5, 6]), + (1720448939.738279, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720159019.782951, [], [1, 2, 3, 4, 5, 6]), + (1720232688.231366, [], [1, 2, 3, 4, 5, 6]), + (1720312031.934367, [], [1, 2, 3, 4, 5, 6]), + (1720420263.292336, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720051467.327131, [], [1, 2, 3, 4, 5, 6]), + (1720226107.259649, [], [1, 2, 3, 4, 5, 6]), + (1720410027.350582, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719966308.30787, [], [1, 2, 3, 4, 5, 6]), + (1720136775.382126, [], [1, 2, 3, 4, 5, 6]), + (1720453167.302523, [], [1, 2, 3, 4, 5, 6]), + (1720578911.142536, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719965705.478301, [], [1, 2, 3, 4, 5, 6]), + (1720089492.274268, [], [1, 2, 3, 4, 5, 6]), + (1720458943.365803, [], [1, 2, 3, 4, 5, 6]), + (1720588170.374851, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720137202.259506, [], [1, 2, 3, 4, 5, 6]), (1720309242.730837, [], [1, 2, 3, 4, 5, 6])], + [(1720397209.557207, [], [1, 2, 3, 4, 5, 6]), (1720628958.303298, [], [1, 2, 3, 4, 5, 6])], + [(1719967303.936898, [], [1, 2, 3, 4, 5, 6]), (1720069496.922345, [], [1, 2, 3, 4, 5, 6])], + [ + (1719970996.586184, [], [1, 2, 3, 4, 5, 6]), + (1720168525.715398, [], [1, 2, 3, 4, 5, 6]), + (1720504098.515479, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720601826.09111, [], [1, 2, 3, 4, 5, 6])], + [ + (1719971199.057468, [], [1, 2, 3, 4, 5, 6]), + (1720068258.0151, [], [1, 2, 3, 4, 5, 6]), + (1720137337.044491, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719971421.175757, [], [1, 2, 3, 4, 5, 6]), (1720134959.956933, [], [1, 2, 3, 4, 5, 6])], + [ + (1719976305.13246, [], [1, 2, 3, 4, 5, 6]), + (1720059646.658845, [], [1, 2, 3, 4, 5, 6]), + (1720145964.773181, [], [1, 2, 3, 4, 5, 6]), + (1720233116.664838, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720436748.603567, [], [1, 2, 3, 4, 5, 6])], + [(1719969550.144929, [], [1, 2, 3, 4, 5, 6]), (1720315269.690666, [], [1, 2, 3, 4, 5, 6])], + [ + (1720274096.315691, [], [1, 2, 3, 4, 5, 6]), + (1720274154.981534, [], [1, 2, 3, 4, 5, 6]), + (1720274184.028094, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720268306.026574, [], [1, 2, 3, 4, 5, 6]), (1720323182.163554, [], [1, 2, 3, 4, 5, 6])], + [ + (1720032173.053995, [], [1, 2, 3, 4, 5, 6]), + (1720157155.365383, [], [1, 2, 3, 4, 5, 6]), + (1720314424.94755, [], [1, 2, 3, 4, 5, 6]), + (1720481047.114281, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720010572.095008, [], [1, 2, 3, 4, 5, 6])], + [ + (1719968638.302149, [], [1, 2, 3, 4, 5, 6]), + (1719968762.98274, [], [1, 2, 3, 4, 5, 6]), + (1719968765.072701, [], [1, 2, 3, 4, 5, 6]), + (1720005012.137582, [], [1, 2, 3, 4, 5, 6]), + (1720005160.858454, [], [1, 2, 3, 4, 5, 6]), + (1720005162.913788, [], [1, 2, 3, 4, 5, 6]), + (1720175681.69546, [], [1, 2, 3, 4, 5, 6]), + (1720175774.033356, [], [1, 2, 3, 4, 5, 6]), + (1720175776.151125, [], [1, 2, 3, 4, 5, 6]), + (1720220252.732147, [], [1, 2, 3, 4, 5, 6]), + (1720220252.777516, [], [1, 2, 3, 4, 5, 6]), + (1720220256.747294, [], [1, 2, 3, 4, 5, 6]), + (1720492139.162569, [], [1, 2, 3, 4, 5, 6]), + (1720492141.256483, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719970987.569565, [], [1, 2, 3, 4, 5, 6])], + [(1720054508.915859, [], [1, 2, 3, 4, 5, 6]), (1720315224.08896, [], [1, 2, 3, 4, 5, 6])], + [(1720325854.156535, [], [1, 2, 3, 4, 5, 6]), (1720483854.080251, [], [1, 2, 3, 4, 5, 6])], + [(1720406510.418443, [], [1, 2, 3, 4, 5, 6])], + [ + (1720030600.544521, [], [1, 2, 3, 4, 5, 6]), + (1720069524.719771, [], [1, 2, 3, 4, 5, 6]), + (1720484112.369653, [], [1, 2, 3, 4, 5, 6]), + (1720568851.121099, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720304785.385271, [], [1, 2, 3, 4, 5, 6])], + [ + (1720313035.494802, [], [1, 2, 3, 4, 5, 6]), + (1720313090.718424, [], [1, 2, 3, 4, 5, 6]), + (1720313239.783577, [], [1, 2, 3, 4, 5, 6]), + (1720313343.042083, [], [1, 2, 3, 4, 5, 6]), + (1720404935.491204, [], [1, 2, 3, 4, 5, 6]), + (1720404979.552845, [], [1, 2, 3, 4, 5, 6]), + (1720404981.647182, [], [1, 2, 3, 4, 5, 6]), + (1720501716.284759, [], [1, 2, 3, 4, 5, 6]), + (1720501761.154088, [], [1, 2, 3, 4, 5, 6]), + (1720501763.234903, [], [1, 2, 3, 4, 5, 6]), + (1720584650.853158, [], [1, 2, 3, 4, 5, 6]), + (1720584688.899508, [], [1, 2, 3, 4, 5, 6]), + (1720584691.020015, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720229088.205557, [], [1, 2, 3, 4, 5, 6]), (1720487228.612214, [], [1, 2, 3, 4, 5, 6])], + [(1720241088.456982, [], [1, 2, 3, 4, 5, 6])], + [(1720042764.160666, [], [1, 2, 3, 4, 5, 6])], + [ + (1719984325.782697, [], [1, 2, 3, 4, 5, 6]), + (1720047953.098659, [], [1, 2, 3, 4, 5, 6]), + (1720268267.887048, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720054622.362154, [], [1, 2, 3, 4, 5, 6]), + (1720134575.953204, [], [1, 2, 3, 4, 5, 6]), + (1720416355.096939, [], [1, 2, 3, 4, 5, 6]), + (1720500581.691615, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719972690.486054, [], [1, 2, 3, 4, 5, 6]), + (1719972877.103609, [], [1, 2, 3, 4, 5, 6]), + (1719972879.22778, [], [1, 2, 3, 4, 5, 6]), + (1719972881.797102, [], [1, 2, 3, 4, 5, 6]), + (1719972883.859612, [], [1, 2, 3, 4, 5, 6]), + (1720052338.317127, [], [1, 2, 3, 4, 5, 6]), + (1720052340.409592, [], [1, 2, 3, 4, 5, 6]), + (1720069426.554888, [], [1, 2, 3, 4, 5, 6]), + (1720069428.615973, [], [1, 2, 3, 4, 5, 6]), + (1720149027.365317, [], [1, 2, 3, 4, 5, 6]), + (1720149089.951754, [], [1, 2, 3, 4, 5, 6]), + (1720149092.012724, [], [1, 2, 3, 4, 5, 6]), + (1720234565.610403, [], [1, 2, 3, 4, 5, 6]), + (1720239125.82035, [], [1, 2, 3, 4, 5, 6]), + (1720239147.87241, [], [1, 2, 3, 4, 5, 6]), + (1720318243.573983, [], [1, 2, 3, 4, 5, 6]), + (1720318245.63705, [], [1, 2, 3, 4, 5, 6]), + (1720418009.877203, [], [1, 2, 3, 4, 5, 6]), + (1720418011.983148, [], [1, 2, 3, 4, 5, 6]), + (1720418014.464823, [], [1, 2, 3, 4, 5, 6]), + (1720485277.913378, [], [1, 2, 3, 4, 5, 6]), + (1720485280.026695, [], [1, 2, 3, 4, 5, 6]), + (1720574328.529507, [], [1, 2, 3, 4, 5, 6]), + (1720574330.633898, [], [1, 2, 3, 4, 5, 6]), + (1720581736.051228, [], [1, 2, 3, 4, 5, 6]), + (1720581766.135021, [], [1, 2, 3, 4, 5, 6]), + (1720581768.228326, [], [1, 2, 3, 4, 5, 6]), + (1720652888.715284, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720328167.133332, [], [1, 2, 3, 4, 5, 6]), (1720394291.998224, [], [1, 2, 3, 4, 5, 6])], + [(1720138278.025347, [], [1, 2, 3, 4, 5, 6])], + [(1720411684.615562, [], [1, 2, 3, 4, 5, 6])], + [ + (1719979551.790599, [], [1, 2, 3, 4, 5, 6]), + (1720062548.79153, [], [1, 2, 3, 4, 5, 6]), + (1720152645.092565, [], [1, 2, 3, 4, 5, 6]), + (1720273648.542968, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720150050.836492, [], [1, 2, 3, 4, 5, 6])], + [(1720235665.517364, [], [1, 2, 3, 4, 5, 6]), (1720504709.666893, [], [1, 2, 3, 4, 5, 6])], + [(1720502409.011067, [], [1, 2, 3, 4, 5, 6]), (1720652305.691241, [], [1, 2, 3, 4, 5, 6])], + [ + (1719983664.396995, [], [1, 2, 3, 4, 5, 6]), + (1720057964.860551, [], [1, 2, 3, 4, 5, 6]), + (1720058069.016671, [], [1, 2, 3, 4, 5, 6]), + (1720119055.986377, [], [1, 2, 3, 4, 5, 6]), + (1720119177.882926, [], [1, 2, 3, 4, 5, 6]), + (1720146988.862958, [], [1, 2, 3, 4, 5, 6]), + (1720146990.940118, [], [1, 2, 3, 4, 5, 6]), + (1720207091.824328, [], [1, 2, 3, 4, 5, 6]), + (1720207147.984162, [], [1, 2, 3, 4, 5, 6]), + (1720207150.045311, [], [1, 2, 3, 4, 5, 6]), + (1720221686.916464, [], [1, 2, 3, 4, 5, 6]), + (1720221731.792885, [], [1, 2, 3, 4, 5, 6]), + (1720221733.892091, [], [1, 2, 3, 4, 5, 6]), + (1720221736.114027, [], [1, 2, 3, 4, 5, 6]), + (1720221738.1731, [], [1, 2, 3, 4, 5, 6]), + (1720221740.137735, [], [1, 2, 3, 4, 5, 6]), + (1720221742.219472, [], [1, 2, 3, 4, 5, 6]), + (1720319188.083254, [], [1, 2, 3, 4, 5, 6]), + (1720319190.195166, [], [1, 2, 3, 4, 5, 6]), + (1720333160.336537, [], [1, 2, 3, 4, 5, 6]), + (1720333162.39224, [], [1, 2, 3, 4, 5, 6]), + (1720350382.882768, [], [1, 2, 3, 4, 5, 6]), + (1720350384.998862, [], [1, 2, 3, 4, 5, 6]), + (1720350385.400746, [], [1, 2, 3, 4, 5, 6]), + (1720350387.504804, [], [1, 2, 3, 4, 5, 6]), + (1720350390.868713, [], [1, 2, 3, 4, 5, 6]), + (1720350392.929211, [], [1, 2, 3, 4, 5, 6]), + (1720482928.905461, [], [1, 2, 3, 4, 5, 6]), + (1720482987.630373, [], [1, 2, 3, 4, 5, 6]), + (1720549510.694147, [], [1, 2, 3, 4, 5, 6]), + (1720549582.87966, [], [1, 2, 3, 4, 5, 6]), + (1720549584.95341, [], [1, 2, 3, 4, 5, 6]), + (1720581476.586746, [], [1, 2, 3, 4, 5, 6]), + (1720581478.656771, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719977177.729628, [], [1, 2, 3, 4, 5, 6]), (1720393638.078415, [], [1, 2, 3, 4, 5, 6])], + [ + (1719980378.113974, [], [1, 2, 3, 4, 5, 6]), + (1720443102.049493, [], [1, 2, 3, 4, 5, 6]), + (1720590770.939412, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719979883.308045, [], [1, 2, 3, 4, 5, 6]), + (1720230654.923495, [], [1, 2, 3, 4, 5, 6]), + (1720310908.910099, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719964829.898192, [], [1, 2, 3, 4, 5, 6]), + (1719964832.003811, [], [1, 2, 3, 4, 5, 6]), + (1719985240.876339, [], [1, 2, 3, 4, 5, 6]), + (1719985242.911416, [], [1, 2, 3, 4, 5, 6]), + (1719985243.633507, [], [1, 2, 3, 4, 5, 6]), + (1719985245.665729, [], [1, 2, 3, 4, 5, 6]), + (1720060650.829248, [], [1, 2, 3, 4, 5, 6]), + (1720060759.718692, [], [1, 2, 3, 4, 5, 6]), + (1720060761.830242, [], [1, 2, 3, 4, 5, 6]), + (1720070260.443094, [], [1, 2, 3, 4, 5, 6]), + (1720070280.911994, [], [1, 2, 3, 4, 5, 6]), + (1720070282.979246, [], [1, 2, 3, 4, 5, 6]), + (1720134645.425223, [], [1, 2, 3, 4, 5, 6]), + (1720134793.819981, [], [1, 2, 3, 4, 5, 6]), + (1720134795.932398, [], [1, 2, 3, 4, 5, 6]), + (1720155938.192604, [], [1, 2, 3, 4, 5, 6]), + (1720155940.320279, [], [1, 2, 3, 4, 5, 6]), + (1720155945.041101, [], [1, 2, 3, 4, 5, 6]), + (1720155947.088061, [], [1, 2, 3, 4, 5, 6]), + (1720236895.111761, [], [1, 2, 3, 4, 5, 6]), + (1720236912.473535, [], [1, 2, 3, 4, 5, 6]), + (1720236914.593968, [], [1, 2, 3, 4, 5, 6]), + (1720236917.655587, [], [1, 2, 3, 4, 5, 6]), + (1720318871.824625, [], [1, 2, 3, 4, 5, 6]), + (1720318935.358285, [], [1, 2, 3, 4, 5, 6]), + (1720318937.446561, [], [1, 2, 3, 4, 5, 6]), + (1720318940.05207, [], [1, 2, 3, 4, 5, 6]), + (1720318942.106239, [], [1, 2, 3, 4, 5, 6]), + (1720405217.370251, [], [1, 2, 3, 4, 5, 6]), + (1720405312.528519, [], [1, 2, 3, 4, 5, 6]), + (1720405314.627163, [], [1, 2, 3, 4, 5, 6]), + (1720413100.204244, [], [1, 2, 3, 4, 5, 6]), + (1720413102.291035, [], [1, 2, 3, 4, 5, 6]), + (1720496542.308228, [], [1, 2, 3, 4, 5, 6]), + (1720574260.260325, [], [1, 2, 3, 4, 5, 6]), + (1720574343.117651, [], [1, 2, 3, 4, 5, 6]), + (1720574345.20748, [], [1, 2, 3, 4, 5, 6]), + (1720578705.104516, [], [1, 2, 3, 4, 5, 6]), + (1720578717.159504, [], [1, 2, 3, 4, 5, 6]), + (1720578719.26077, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720071370.538676, [], [1, 2, 3, 4, 5, 6])], + [(1719972220.86175, [], [1, 2, 3, 4, 5, 6]), (1720227223.558904, [], [1, 2, 3, 4, 5, 6])], + [ + (1720047692.206123, [], [1, 2, 3, 4, 5, 6]), + (1720074479.043983, [], [1, 2, 3, 4, 5, 6]), + (1720221755.131247, [], [1, 2, 3, 4, 5, 6]), + (1720343377.429715, [], [1, 2, 3, 4, 5, 6]), + (1720581159.65796, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720054906.379171, [], [1, 2, 3, 4, 5, 6]), + (1720326827.193456, [], [1, 2, 3, 4, 5, 6]), + (1720395837.565662, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719972411.855532, [], [1, 2, 3, 4, 5, 6]), + (1719972538.863121, [], [1, 2, 3, 4, 5, 6]), + (1719972540.935712, [], [1, 2, 3, 4, 5, 6]), + (1720063717.900878, [], [1, 2, 3, 4, 5, 6]), + (1720063719.954111, [], [1, 2, 3, 4, 5, 6]), + (1720070114.807467, [], [1, 2, 3, 4, 5, 6]), + (1720070235.024434, [], [1, 2, 3, 4, 5, 6]), + (1720070237.14674, [], [1, 2, 3, 4, 5, 6]), + (1720097819.236115, [], [1, 2, 3, 4, 5, 6]), + (1720097978.260021, [], [1, 2, 3, 4, 5, 6]), + (1720097980.382821, [], [1, 2, 3, 4, 5, 6]), + (1720151026.716063, [], [1, 2, 3, 4, 5, 6]), + (1720151173.670938, [], [1, 2, 3, 4, 5, 6]), + (1720151175.717239, [], [1, 2, 3, 4, 5, 6]), + (1720166439.941955, [], [1, 2, 3, 4, 5, 6]), + (1720166583.693905, [], [1, 2, 3, 4, 5, 6]), + (1720166585.791065, [], [1, 2, 3, 4, 5, 6]), + (1720181553.630642, [], [1, 2, 3, 4, 5, 6]), + (1720181555.746202, [], [1, 2, 3, 4, 5, 6]), + (1720242210.300006, [], [1, 2, 3, 4, 5, 6]), + (1720242331.451228, [], [1, 2, 3, 4, 5, 6]), + (1720316730.127117, [], [1, 2, 3, 4, 5, 6]), + (1720316751.481651, [], [1, 2, 3, 4, 5, 6]), + (1720350332.517593, [], [1, 2, 3, 4, 5, 6]), + (1720350427.724851, [], [1, 2, 3, 4, 5, 6]), + (1720350429.836812, [], [1, 2, 3, 4, 5, 6]), + (1720396153.382808, [], [1, 2, 3, 4, 5, 6]), + (1720396199.106453, [], [1, 2, 3, 4, 5, 6]), + (1720396201.15929, [], [1, 2, 3, 4, 5, 6]), + (1720424092.525755, [], [1, 2, 3, 4, 5, 6]), + (1720424190.959176, [], [1, 2, 3, 4, 5, 6]), + (1720424193.037739, [], [1, 2, 3, 4, 5, 6]), + (1720492456.877253, [], [1, 2, 3, 4, 5, 6]), + (1720492529.103048, [], [1, 2, 3, 4, 5, 6]), + (1720492531.198928, [], [1, 2, 3, 4, 5, 6]), + (1720583806.008143, [], [1, 2, 3, 4, 5, 6]), + (1720583868.43082, [], [1, 2, 3, 4, 5, 6]), + (1720648763.855471, [], [1, 2, 3, 4, 5, 6]), + (1720648878.799852, [], [1, 2, 3, 4, 5, 6]), + (1720648880.882297, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720071793.774403, [], [1, 2, 3, 4, 5, 6]), + (1720309002.505766, [], [1, 2, 3, 4, 5, 6]), + (1720367384.379119, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719978345.677095, [], [1, 2, 3, 4, 5, 6]), (1720134660.416426, [], [1, 2, 3, 4, 5, 6])], + [ + (1720056400.339178, [], [1, 2, 3, 4, 5, 6]), + (1720137451.906538, [], [1, 2, 3, 4, 5, 6]), + (1720581731.115191, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719974999.631834, [], [1, 2, 3, 4, 5, 6]), (1720503857.499785, [], [1, 2, 3, 4, 5, 6])], + [(1720325249.830373, [], [1, 2, 3, 4, 5, 6])], + [ + (1719970175.486046, [], [1, 2, 3, 4, 5, 6]), + (1720061532.244847, [], [1, 2, 3, 4, 5, 6]), + (1720387059.054565, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720157797.242967, [], [1, 2, 3, 4, 5, 6])], + [(1720490173.84352, [], [1, 2, 3, 4, 5, 6])], + [(1720568387.145132, [], [1, 2, 3, 4, 5, 6])], + [(1720027447.264569, [], [1, 2, 3, 4, 5, 6])], + [(1719979106.899872, [], [1, 2, 3, 4, 5, 6]), (1720417473.653713, [], [1, 2, 3, 4, 5, 6])], + [(1720153359.982848, [], [1, 2, 3, 4, 5, 6]), (1720468837.459019, [], [1, 2, 3, 4, 5, 6])], + [(1720047669.218866, [], [1, 2, 3, 4, 5, 6])], + [(1720230050.113895, [], [1, 2, 3, 4, 5, 6])], + [ + (1719975411.228945, [], [1, 2, 3, 4, 5, 6]), + (1720235199.496284, [], [1, 2, 3, 4, 5, 6]), + (1720403154.17646, [], [1, 2, 3, 4, 5, 6]), + (1720626578.282517, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719978136.275137, [], [1, 2, 3, 4, 5, 6]), (1720331670.572264, [], [1, 2, 3, 4, 5, 6])], + [ + (1719975669.597909, [], [1, 2, 3, 4, 5, 6]), + (1719975763.25366, [], [1, 2, 3, 4, 5, 6]), + (1720055306.937976, [], [1, 2, 3, 4, 5, 6]), + (1720055449.351479, [], [1, 2, 3, 4, 5, 6]), + (1720067433.572041, [], [1, 2, 3, 4, 5, 6]), + (1720067452.84519, [], [1, 2, 3, 4, 5, 6]), + (1720067454.935816, [], [1, 2, 3, 4, 5, 6]), + (1720233716.974937, [], [1, 2, 3, 4, 5, 6]), + (1720233884.056907, [], [1, 2, 3, 4, 5, 6]), + (1720233886.107033, [], [1, 2, 3, 4, 5, 6]), + (1720238869.144339, [], [1, 2, 3, 4, 5, 6]), + (1720239054.729577, [], [1, 2, 3, 4, 5, 6]), + (1720239056.811577, [], [1, 2, 3, 4, 5, 6]), + (1720248048.594017, [], [1, 2, 3, 4, 5, 6]), + (1720248147.506317, [], [1, 2, 3, 4, 5, 6]), + (1720248149.540209, [], [1, 2, 3, 4, 5, 6]), + (1720323761.342714, [], [1, 2, 3, 4, 5, 6]), + (1720323763.381547, [], [1, 2, 3, 4, 5, 6]), + (1720400825.240853, [], [1, 2, 3, 4, 5, 6]), + (1720400844.815642, [], [1, 2, 3, 4, 5, 6]), + (1720410954.1329, [], [1, 2, 3, 4, 5, 6]), + (1720410956.230411, [], [1, 2, 3, 4, 5, 6]), + (1720410956.661655, [], [1, 2, 3, 4, 5, 6]), + (1720410958.800282, [], [1, 2, 3, 4, 5, 6]), + (1720414005.128157, [], [1, 2, 3, 4, 5, 6]), + (1720414035.742095, [], [1, 2, 3, 4, 5, 6]), + (1720414037.861356, [], [1, 2, 3, 4, 5, 6]), + (1720414039.522054, [], [1, 2, 3, 4, 5, 6]), + (1720414041.622559, [], [1, 2, 3, 4, 5, 6]), + (1720449836.553695, [], [1, 2, 3, 4, 5, 6]), + (1720449909.88067, [], [1, 2, 3, 4, 5, 6]), + (1720449912.006572, [], [1, 2, 3, 4, 5, 6]), + (1720504478.640048, [], [1, 2, 3, 4, 5, 6]), + (1720504584.183246, [], [1, 2, 3, 4, 5, 6]), + (1720504586.273448, [], [1, 2, 3, 4, 5, 6]), + (1720589586.941948, [], [1, 2, 3, 4, 5, 6]), + (1720589732.653657, [], [1, 2, 3, 4, 5, 6]), + (1720589734.757411, [], [1, 2, 3, 4, 5, 6]), + (1720589735.718174, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719987925.192586, [], [1, 2, 3, 4, 5, 6]), (1720319498.157106, [], [1, 2, 3, 4, 5, 6])], + [(1720140316.935341, [], [1, 2, 3, 4, 5, 6]), (1720581286.138288, [], [1, 2, 3, 4, 5, 6])], + [ + (1719984942.453601, [], [1, 2, 3, 4, 5, 6]), + (1720334036.972544, [], [1, 2, 3, 4, 5, 6]), + (1720568302.136228, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720231990.896895, [], [1, 2, 3, 4, 5, 6]), (1720320392.727402, [], [1, 2, 3, 4, 5, 6])], + [(1720151072.246138, [], [1, 2, 3, 4, 5, 6]), (1720309428.675922, [], [1, 2, 3, 4, 5, 6])], + [(1720652752.302257, [], [1, 2, 3, 4, 5, 6])], + [ + (1719977332.758786, [], [1, 2, 3, 4, 5, 6]), + (1720135118.942837, [], [1, 2, 3, 4, 5, 6]), + (1720498977.766189, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720054300.10225, [], [1, 2, 3, 4, 5, 6]), (1720419250.119038, [], [1, 2, 3, 4, 5, 6])], + [ + (1720170242.586928, [], [1, 2, 3, 4, 5, 6]), + (1720322954.401713, [], [1, 2, 3, 4, 5, 6]), + (1720500416.057333, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719976447.157218, [], [1, 2, 3, 4, 5, 6])], + [(1720134454.623643, [], [1, 2, 3, 4, 5, 6]), (1720482790.529945, [], [1, 2, 3, 4, 5, 6])], + [(1720575291.374898, [], [1, 2, 3, 4, 5, 6])], + [(1720575147.912954, [], [1, 2, 3, 4, 5, 6])], + [ + (1719997197.65312, [], [1, 2, 3, 4, 5, 6]), + (1720137704.47896, [], [1, 2, 3, 4, 5, 6]), + (1720226085.527498, [], [1, 2, 3, 4, 5, 6]), + (1720306837.86921, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720314781.298338, [], [1, 2, 3, 4, 5, 6]), (1720443503.319112, [], [1, 2, 3, 4, 5, 6])], + [ + (1719976515.23989, [], [1, 2, 3, 4, 5, 6]), + (1720225806.720086, [], [1, 2, 3, 4, 5, 6]), + (1720388901.256231, [], [1, 2, 3, 4, 5, 6]), + (1720490185.842396, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720568142.650151, [], [1, 2, 3, 4, 5, 6])], + [(1720587602.828532, [], [1, 2, 3, 4, 5, 6])], + [(1720228569.783763, [], [1, 2, 3, 4, 5, 6]), (1720577136.698764, [], [1, 2, 3, 4, 5, 6])], + [ + (1720058398.793045, [], [1, 2, 3, 4, 5, 6]), + (1720317616.711315, [], [1, 2, 3, 4, 5, 6]), + (1720498994.241943, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719988512.009335, [], [1, 2, 3, 4, 5, 6]), + (1720411879.880695, [], [1, 2, 3, 4, 5, 6]), + (1720575546.218164, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720245099.046699, [], [1, 2, 3, 4, 5, 6]), (1720652539.847041, [], [1, 2, 3, 4, 5, 6])], + [ + (1719965518.303227, [], [1, 2, 3, 4, 5, 6]), + (1720241249.736668, [], [1, 2, 3, 4, 5, 6]), + (1720410560.906617, [], [1, 2, 3, 4, 5, 6]), + (1720566388.427971, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720033619.669265, [], [1, 2, 3, 4, 5, 6]), + (1720309514.690673, [], [1, 2, 3, 4, 5, 6]), + (1720584737.484501, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719981137.891986, [], [1, 2, 3, 4, 5, 6]), + (1719981255.525287, [], [1, 2, 3, 4, 5, 6]), + (1719981257.57542, [], [1, 2, 3, 4, 5, 6]), + (1720156254.934266, [], [1, 2, 3, 4, 5, 6]), + (1720156432.088183, [], [1, 2, 3, 4, 5, 6]), + (1720221245.352908, [], [1, 2, 3, 4, 5, 6]), + (1720221247.415618, [], [1, 2, 3, 4, 5, 6]), + (1720306695.430622, [], [1, 2, 3, 4, 5, 6]), + (1720306697.509606, [], [1, 2, 3, 4, 5, 6]), + (1720399726.625066, [], [1, 2, 3, 4, 5, 6]), + (1720399728.675873, [], [1, 2, 3, 4, 5, 6]), + (1720486842.405361, [], [1, 2, 3, 4, 5, 6]), + (1720486974.649877, [], [1, 2, 3, 4, 5, 6]), + (1720494605.919949, [], [1, 2, 3, 4, 5, 6]), + (1720494724.480053, [], [1, 2, 3, 4, 5, 6]), + (1720494726.541559, [], [1, 2, 3, 4, 5, 6]), + (1720572824.284783, [], [1, 2, 3, 4, 5, 6]), + (1720572826.355789, [], [1, 2, 3, 4, 5, 6]), + (1720652512.753893, [], [1, 2, 3, 4, 5, 6]), + (1720652514.833743, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720044224.653908, [], [1, 2, 3, 4, 5, 6]), (1720583176.852571, [], [1, 2, 3, 4, 5, 6])], + [(1720567262.122889, [], [1, 2, 3, 4, 5, 6])], + [(1720518049.925836, [], [1, 2, 3, 4, 5, 6])], + [(1720148280.678113, [], [1, 2, 3, 4, 5, 6]), (1720391739.484219, [], [1, 2, 3, 4, 5, 6])], + [ + (1719983654.268169, [], [1, 2, 3, 4, 5, 6]), + (1719983761.844014, [], [1, 2, 3, 4, 5, 6]), + (1719983763.902973, [], [1, 2, 3, 4, 5, 6]), + (1720014262.846562, [], [1, 2, 3, 4, 5, 6]), + (1720014264.966534, [], [1, 2, 3, 4, 5, 6]), + (1720014268.064236, [], [1, 2, 3, 4, 5, 6]), + (1720014270.176366, [], [1, 2, 3, 4, 5, 6]), + (1720062164.847608, [], [1, 2, 3, 4, 5, 6]), + (1720062166.93557, [], [1, 2, 3, 4, 5, 6]), + (1720070760.286042, [], [1, 2, 3, 4, 5, 6]), + (1720070793.879274, [], [1, 2, 3, 4, 5, 6]), + (1720070795.974998, [], [1, 2, 3, 4, 5, 6]), + (1720136175.682667, [], [1, 2, 3, 4, 5, 6]), + (1720136177.782735, [], [1, 2, 3, 4, 5, 6]), + (1720150756.421019, [], [1, 2, 3, 4, 5, 6]), + (1720150758.537073, [], [1, 2, 3, 4, 5, 6]), + (1720226712.358545, [], [1, 2, 3, 4, 5, 6]), + (1720320316.371588, [], [1, 2, 3, 4, 5, 6]), + (1720396676.623722, [], [1, 2, 3, 4, 5, 6]), + (1720396759.330429, [], [1, 2, 3, 4, 5, 6]), + (1720482810.511366, [], [1, 2, 3, 4, 5, 6]), + (1720482891.609285, [], [1, 2, 3, 4, 5, 6]), + (1720482893.739553, [], [1, 2, 3, 4, 5, 6]), + (1720502988.652815, [], [1, 2, 3, 4, 5, 6]), + (1720503034.447086, [], [1, 2, 3, 4, 5, 6]), + (1720503036.52898, [], [1, 2, 3, 4, 5, 6]), + (1720503036.606516, [], [1, 2, 3, 4, 5, 6]), + (1720503038.712119, [], [1, 2, 3, 4, 5, 6]), + (1720566567.148583, [], [1, 2, 3, 4, 5, 6]), + (1720566710.618717, [], [1, 2, 3, 4, 5, 6]), + (1720624425.022175, [], [1, 2, 3, 4, 5, 6]), + (1720624567.571474, [], [1, 2, 3, 4, 5, 6]), + (1720624569.66289, [], [1, 2, 3, 4, 5, 6]), + (1720652508.525789, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719978793.297818, [], [1, 2, 3, 4, 5, 6]), (1720312690.624643, [], [1, 2, 3, 4, 5, 6])], + [(1720408103.17786, [], [1, 2, 3, 4, 5, 6]), (1720496665.901316, [], [1, 2, 3, 4, 5, 6])], + [(1720397084.267673, [], [1, 2, 3, 4, 5, 6]), (1720499411.209847, [], [1, 2, 3, 4, 5, 6])], + [ + (1720111853.777887, [], [1, 2, 3, 4, 5, 6]), + (1720111923.412934, [], [1, 2, 3, 4, 5, 6]), + (1720139482.167685, [], [1, 2, 3, 4, 5, 6]), + (1720139533.842338, [], [1, 2, 3, 4, 5, 6]), + (1720139535.907287, [], [1, 2, 3, 4, 5, 6]), + (1720139540.267313, [], [1, 2, 3, 4, 5, 6]), + (1720139542.34773, [], [1, 2, 3, 4, 5, 6]), + (1720139547.051966, [], [1, 2, 3, 4, 5, 6]), + (1720139549.136732, [], [1, 2, 3, 4, 5, 6]), + (1720464344.794745, [], [1, 2, 3, 4, 5, 6]), + (1720464401.900918, [], [1, 2, 3, 4, 5, 6]), + (1720464404.029255, [], [1, 2, 3, 4, 5, 6]), + (1720498850.875209, [], [1, 2, 3, 4, 5, 6]), + (1720499103.608103, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719973523.458065, [], [1, 2, 3, 4, 5, 6]), (1720233566.787523, [], [1, 2, 3, 4, 5, 6])], + [(1720407928.090004, [], [1, 2, 3, 4, 5, 6])], + [(1720032729.148346, [], [1, 2, 3, 4, 5, 6]), (1720062532.225999, [], [1, 2, 3, 4, 5, 6])], + [(1720034095.862663, [], [1, 2, 3, 4, 5, 6]), (1720491285.681862, [], [1, 2, 3, 4, 5, 6])], + [(1720096472.997597, [], [1, 2, 3, 4, 5, 6]), (1720568056.766425, [], [1, 2, 3, 4, 5, 6])], + [(1720138718.911672, [], [1, 2, 3, 4, 5, 6])], + [ + (1720336998.597537, [], [1, 2, 3, 4, 5, 6]), + (1720489473.142035, [], [1, 2, 3, 4, 5, 6]), + (1720574315.596422, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720577328.151149, [], [1, 2, 3, 4, 5, 6])], + [(1720072713.69671, [], [1, 2, 3, 4, 5, 6]), (1720231002.690818, [], [1, 2, 3, 4, 5, 6])], + [(1719966317.997493, [], [1, 2, 3, 4, 5, 6]), (1720238108.647106, [], [1, 2, 3, 4, 5, 6])], + [(1720146847.656681, [], [1, 2, 3, 4, 5, 6])], + [(1720239981.42926, [], [1, 2, 3, 4, 5, 6])], + [(1720081339.444776, [], [1, 2, 3, 4, 5, 6]), (1720234051.371763, [], [1, 2, 3, 4, 5, 6])], + [(1720236937.844197, [], [1, 2, 3, 4, 5, 6]), (1720501314.981075, [], [1, 2, 3, 4, 5, 6])], + [(1720495611.198831, [], [1, 2, 3, 4, 5, 6])], + [(1720071452.84595, [], [1, 2, 3, 4, 5, 6])], + [(1720320971.754361, [], [1, 2, 3, 4, 5, 6])], + [ + (1719982790.224924, [], [1, 2, 3, 4, 5, 6]), + (1719982861.078823, [], [1, 2, 3, 4, 5, 6]), + (1719982863.122702, [], [1, 2, 3, 4, 5, 6]), + (1720052453.241504, [], [1, 2, 3, 4, 5, 6]), + (1720052505.408448, [], [1, 2, 3, 4, 5, 6]), + (1720052507.485592, [], [1, 2, 3, 4, 5, 6]), + (1720078456.868981, [], [1, 2, 3, 4, 5, 6]), + (1720137047.584706, [], [1, 2, 3, 4, 5, 6]), + (1720137124.096958, [], [1, 2, 3, 4, 5, 6]), + (1720137126.192241, [], [1, 2, 3, 4, 5, 6]), + (1720155528.420602, [], [1, 2, 3, 4, 5, 6]), + (1720155596.835697, [], [1, 2, 3, 4, 5, 6]), + (1720155598.919376, [], [1, 2, 3, 4, 5, 6]), + (1720204090.330488, [], [1, 2, 3, 4, 5, 6]), + (1720204222.690243, [], [1, 2, 3, 4, 5, 6]), + (1720204224.805824, [], [1, 2, 3, 4, 5, 6]), + (1720232760.467367, [], [1, 2, 3, 4, 5, 6]), + (1720232859.977733, [], [1, 2, 3, 4, 5, 6]), + (1720242903.930897, [], [1, 2, 3, 4, 5, 6]), + (1720242906.021355, [], [1, 2, 3, 4, 5, 6]), + (1720309697.411345, [], [1, 2, 3, 4, 5, 6]), + (1720309699.483954, [], [1, 2, 3, 4, 5, 6]), + (1720406346.354509, [], [1, 2, 3, 4, 5, 6]), + (1720406523.466919, [], [1, 2, 3, 4, 5, 6]), + (1720406525.535072, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720065979.154591, [], [1, 2, 3, 4, 5, 6]), (1720325699.423285, [], [1, 2, 3, 4, 5, 6])], + [(1720244750.093352, [], [1, 2, 3, 4, 5, 6]), (1720394343.192185, [], [1, 2, 3, 4, 5, 6])], + [(1720193298.590097, [], [1, 2, 3, 4, 5, 6]), (1720315677.193089, [], [1, 2, 3, 4, 5, 6])], + [(1720501281.07252, [], [1, 2, 3, 4, 5, 6])], + [(1720055721.622214, [], [1, 2, 3, 4, 5, 6])], + [ + (1720137839.895581, [], [1, 2, 3, 4, 5, 6]), + (1720231251.548774, [], [1, 2, 3, 4, 5, 6]), + (1720350224.693877, [], [1, 2, 3, 4, 5, 6]), + (1720519304.741337, [], [1, 2, 3, 4, 5, 6]), + (1720586487.784295, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719969181.053709, [], [1, 2, 3, 4, 5, 6]), (1720434586.266895, [], [1, 2, 3, 4, 5, 6])], + [(1720070912.148493, [], [1, 2, 3, 4, 5, 6])], + [(1720244703.673132, [], [1, 2, 3, 4, 5, 6]), (1720494833.034907, [], [1, 2, 3, 4, 5, 6])], + [ + (1720053732.993216, [], [1, 2, 3, 4, 5, 6]), + (1720053735.086697, [], [1, 2, 3, 4, 5, 6]), + (1720081490.114819, [], [1, 2, 3, 4, 5, 6]), + (1720081492.188923, [], [1, 2, 3, 4, 5, 6]), + (1720108329.744396, [], [1, 2, 3, 4, 5, 6]), + (1720108420.858541, [], [1, 2, 3, 4, 5, 6]), + (1720108422.93886, [], [1, 2, 3, 4, 5, 6]), + (1720142971.786605, [], [1, 2, 3, 4, 5, 6]), + (1720143021.896153, [], [1, 2, 3, 4, 5, 6]), + (1720149975.921352, [], [1, 2, 3, 4, 5, 6]), + (1720150041.125351, [], [1, 2, 3, 4, 5, 6]), + (1720150043.15518, [], [1, 2, 3, 4, 5, 6]), + (1720200733.408027, [], [1, 2, 3, 4, 5, 6]), + (1720200744.366236, [], [1, 2, 3, 4, 5, 6]), + (1720200746.48024, [], [1, 2, 3, 4, 5, 6]), + (1720226248.428928, [], [1, 2, 3, 4, 5, 6]), + (1720226387.261389, [], [1, 2, 3, 4, 5, 6]), + (1720325189.273212, [], [1, 2, 3, 4, 5, 6]), + (1720367266.448359, [], [1, 2, 3, 4, 5, 6]), + (1720367268.528501, [], [1, 2, 3, 4, 5, 6]), + (1720397514.119584, [], [1, 2, 3, 4, 5, 6]), + (1720397583.541623, [], [1, 2, 3, 4, 5, 6]), + (1720397585.62972, [], [1, 2, 3, 4, 5, 6]), + (1720407649.068004, [], [1, 2, 3, 4, 5, 6]), + (1720407859.450723, [], [1, 2, 3, 4, 5, 6]), + (1720407861.5267, [], [1, 2, 3, 4, 5, 6]), + (1720418226.184583, [], [1, 2, 3, 4, 5, 6]), + (1720418312.907521, [], [1, 2, 3, 4, 5, 6]), + (1720418312.959891, [], [1, 2, 3, 4, 5, 6]), + (1720418314.508588, [], [1, 2, 3, 4, 5, 6]), + (1720429033.410454, [], [1, 2, 3, 4, 5, 6]), + (1720429217.5183, [], [1, 2, 3, 4, 5, 6]), + (1720429219.58254, [], [1, 2, 3, 4, 5, 6]), + (1720476196.299215, [], [1, 2, 3, 4, 5, 6]), + (1720476290.414317, [], [1, 2, 3, 4, 5, 6]), + (1720476292.497993, [], [1, 2, 3, 4, 5, 6]), + (1720496668.635514, [], [1, 2, 3, 4, 5, 6]), + (1720496670.762669, [], [1, 2, 3, 4, 5, 6]), + (1720566807.578929, [], [1, 2, 3, 4, 5, 6]), + (1720566881.524889, [], [1, 2, 3, 4, 5, 6]), + (1720566883.613068, [], [1, 2, 3, 4, 5, 6]), + (1720575742.398153, [], [1, 2, 3, 4, 5, 6]), + (1720575760.407369, [], [1, 2, 3, 4, 5, 6]), + (1720575762.530879, [], [1, 2, 3, 4, 5, 6]), + (1720623060.799492, [], [1, 2, 3, 4, 5, 6]), + (1720623163.775703, [], [1, 2, 3, 4, 5, 6]), + (1720623165.819144, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720490829.088908, [], [1, 2, 3, 4, 5, 6])], + [ + (1720222040.449568, [], [1, 2, 3, 4, 5, 6]), + (1720328183.580613, [], [1, 2, 3, 4, 5, 6]), + (1720581997.108309, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720631726.024509, [], [1, 2, 3, 4, 5, 6])], + [ + (1719969186.42388, [], [1, 2, 3, 4, 5, 6]), + (1720236467.453142, [], [1, 2, 3, 4, 5, 6]), + (1720460294.599805, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720328624.599959, [], [1, 2, 3, 4, 5, 6]), + (1720411036.02508, [], [1, 2, 3, 4, 5, 6]), + (1720470233.314202, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719966062.758672, [], [1, 2, 3, 4, 5, 6]), + (1720057471.705526, [], [1, 2, 3, 4, 5, 6]), + (1720325034.717518, [], [1, 2, 3, 4, 5, 6]), + (1720407309.902625, [], [1, 2, 3, 4, 5, 6]), + (1720573477.911506, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720063887.70449, [], [1, 2, 3, 4, 5, 6])], + [(1720343326.152899, [], [1, 2, 3, 4, 5, 6])], + [(1720411362.644921, [], [1, 2, 3, 4, 5, 6])], + [(1720395606.751317, [], [1, 2, 3, 4, 5, 6])], + [(1720155980.858558, [], [1, 2, 3, 4, 5, 6])], + [(1720450339.669296, [], [1, 2, 3, 4, 5, 6])], + [(1719981567.460091, [], [1, 2, 3, 4, 5, 6]), (1720587320.169523, [], [1, 2, 3, 4, 5, 6])], + [(1720245122.915738, [], [1, 2, 3, 4, 5, 6])], + [(1719970229.063219, [], [1, 2, 3, 4, 5, 6]), (1720488361.805483, [], [1, 2, 3, 4, 5, 6])], + [(1720320009.047059, [], [1, 2, 3, 4, 5, 6])], + [(1720139484.708505, [], [1, 2, 3, 4, 5, 6]), (1720396780.73649, [], [1, 2, 3, 4, 5, 6])], + [(1720238094.386701, [], [1, 2, 3, 4, 5, 6])], + [(1720627574.598265, [], [1, 2, 3, 4, 5, 6])], + [(1720136834.089355, [], [1, 2, 3, 4, 5, 6]), (1720396824.609765, [], [1, 2, 3, 4, 5, 6])], + [(1720225652.369657, [], [1, 2, 3, 4, 5, 6])], + [ + (1719982133.012616, [], [1, 2, 3, 4, 5, 6]), + (1719982177.631804, [], [1, 2, 3, 4, 5, 6]), + (1719982179.720602, [], [1, 2, 3, 4, 5, 6]), + (1720006591.274361, [], [1, 2, 3, 4, 5, 6]), + (1720006644.930183, [], [1, 2, 3, 4, 5, 6]), + (1720006647.03435, [], [1, 2, 3, 4, 5, 6]), + (1720460548.964008, [], [1, 2, 3, 4, 5, 6]), + (1720460614.237345, [], [1, 2, 3, 4, 5, 6]), + (1720460616.332418, [], [1, 2, 3, 4, 5, 6]), + (1720585282.645498, [], [1, 2, 3, 4, 5, 6]), + (1720585293.462072, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720370572.550118, [], [1, 2, 3, 4, 5, 6])], + [ + (1719973160.879923, [], [1, 2, 3, 4, 5, 6]), + (1720329101.982409, [], [1, 2, 3, 4, 5, 6]), + (1720581501.430356, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720063998.039445, [], [1, 2, 3, 4, 5, 6]), + (1720232764.384684, [], [1, 2, 3, 4, 5, 6]), + (1720502473.633051, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720153647.635598, [], [1, 2, 3, 4, 5, 6]), + (1720225923.85076, [], [1, 2, 3, 4, 5, 6]), + (1720413430.570698, [], [1, 2, 3, 4, 5, 6]), + (1720584131.042756, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719966759.043742, [], [1, 2, 3, 4, 5, 6])], + [(1720405936.570297, [], [1, 2, 3, 4, 5, 6])], + [(1720144919.519677, [], [1, 2, 3, 4, 5, 6]), (1720402676.1685, [], [1, 2, 3, 4, 5, 6])], + [(1720402994.034134, [], [1, 2, 3, 4, 5, 6]), (1720497341.728864, [], [1, 2, 3, 4, 5, 6])], + [ + (1719973785.927392, [], [1, 2, 3, 4, 5, 6]), + (1720142506.754009, [], [1, 2, 3, 4, 5, 6]), + (1720312482.395361, [], [1, 2, 3, 4, 5, 6]), + (1720578049.42885, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720143203.796648, [], [1, 2, 3, 4, 5, 6]), (1720504600.034248, [], [1, 2, 3, 4, 5, 6])], + [(1720138317.024564, [], [1, 2, 3, 4, 5, 6]), (1720307922.860078, [], [1, 2, 3, 4, 5, 6])], + [(1720576710.045341, [], [1, 2, 3, 4, 5, 6])], + [ + (1720237948.24219, [], [1, 2, 3, 4, 5, 6]), + (1720322691.233406, [], [1, 2, 3, 4, 5, 6]), + (1720412663.957815, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720342019.617667, [], [1, 2, 3, 4, 5, 6]), + (1720342090.227667, [], [1, 2, 3, 4, 5, 6]), + (1720342263.731169, [], [1, 2, 3, 4, 5, 6]), + (1720342307.569989, [], [1, 2, 3, 4, 5, 6]), + (1720342413.538738, [], [1, 2, 3, 4, 5, 6]), + (1720342570.868506, [], [1, 2, 3, 4, 5, 6]), + (1720342664.423143, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720053725.982337, [], [1, 2, 3, 4, 5, 6]), + (1720137089.95596, [], [1, 2, 3, 4, 5, 6]), + (1720250340.159455, [], [1, 2, 3, 4, 5, 6]), + (1720408080.82431, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720502215.54816, [], [1, 2, 3, 4, 5, 6])], + [(1720051018.757074, [], [1, 2, 3, 4, 5, 6]), (1720221304.68857, [], [1, 2, 3, 4, 5, 6])], + [ + (1720055639.220711, [], [1, 2, 3, 4, 5, 6]), + (1720242136.136068, [], [1, 2, 3, 4, 5, 6]), + (1720501308.452889, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720210019.832882, [], [1, 2, 3, 4, 5, 6])], + [(1720222496.41532, [], [1, 2, 3, 4, 5, 6])], + [(1720221892.596089, [], [1, 2, 3, 4, 5, 6]), (1720488555.303827, [], [1, 2, 3, 4, 5, 6])], + [ + (1720055240.779901, [], [1, 2, 3, 4, 5, 6]), + (1720485059.84637, [], [1, 2, 3, 4, 5, 6]), + (1720520102.630634, [], [1, 2, 3, 4, 5, 6]), + (1720591031.4354, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720570592.888394, [], [1, 2, 3, 4, 5, 6])], + [ + (1720059956.606064, [], [1, 2, 3, 4, 5, 6]), + (1720232781.82764, [], [1, 2, 3, 4, 5, 6]), + (1720489307.963369, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720466563.789269, [], [1, 2, 3, 4, 5, 6])], + [(1720120332.505828, [], [1, 2, 3, 4, 5, 6]), (1720501386.247192, [], [1, 2, 3, 4, 5, 6])], + [ + (1720045443.968104, [], [1, 2, 3, 4, 5, 6]), + (1720337612.000658, [], [1, 2, 3, 4, 5, 6]), + (1720484793.823359, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720240516.409323, [], [1, 2, 3, 4, 5, 6]), (1720508486.303913, [], [1, 2, 3, 4, 5, 6])], + [ + (1720056682.445295, [], [1, 2, 3, 4, 5, 6]), + (1720239570.480365, [], [1, 2, 3, 4, 5, 6]), + (1720399243.691516, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720065346.577694, [], [1, 2, 3, 4, 5, 6]), + (1720111179.563476, [], [1, 2, 3, 4, 5, 6]), + (1720152182.18393, [], [1, 2, 3, 4, 5, 6]), + (1720456368.150945, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720037842.027886, [], [1, 2, 3, 4, 5, 6])], + [(1720051512.155726, [], [1, 2, 3, 4, 5, 6]), (1720316085.436368, [], [1, 2, 3, 4, 5, 6])], + [ + (1720153922.872643, [], [1, 2, 3, 4, 5, 6]), + (1720316484.292604, [], [1, 2, 3, 4, 5, 6]), + (1720481626.562697, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720304528.044157, [], [1, 2, 3, 4, 5, 6]), (1720587171.914424, [], [1, 2, 3, 4, 5, 6])], + [ + (1719969690.052003, [], [1, 2, 3, 4, 5, 6]), + (1720098093.259497, [], [1, 2, 3, 4, 5, 6]), + (1720589467.401983, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720182994.851728, [], [1, 2, 3, 4, 5, 6]), (1720490206.204252, [], [1, 2, 3, 4, 5, 6])], + [(1720305269.133214, [], [1, 2, 3, 4, 5, 6]), (1720580679.401674, [], [1, 2, 3, 4, 5, 6])], + [(1720582113.001824, [], [1, 2, 3, 4, 5, 6])], + [ + (1719971867.373391, [], [1, 2, 3, 4, 5, 6]), + (1719971869.452767, [], [1, 2, 3, 4, 5, 6]), + (1719983561.418747, [], [1, 2, 3, 4, 5, 6]), + (1719983615.306689, [], [1, 2, 3, 4, 5, 6]), + (1719983617.371374, [], [1, 2, 3, 4, 5, 6]), + (1719983622.154397, [], [1, 2, 3, 4, 5, 6]), + (1719983624.239597, [], [1, 2, 3, 4, 5, 6]), + (1720057585.854293, [], [1, 2, 3, 4, 5, 6]), + (1720127843.991043, [], [1, 2, 3, 4, 5, 6]), + (1720127952.545227, [], [1, 2, 3, 4, 5, 6]), + (1720150451.197164, [], [1, 2, 3, 4, 5, 6]), + (1720150472.889245, [], [1, 2, 3, 4, 5, 6]), + (1720229579.372015, [], [1, 2, 3, 4, 5, 6]), + (1720229585.29839, [], [1, 2, 3, 4, 5, 6]), + (1720229587.33746, [], [1, 2, 3, 4, 5, 6]), + (1720272362.151724, [], [1, 2, 3, 4, 5, 6]), + (1720272395.494166, [], [1, 2, 3, 4, 5, 6]), + (1720272397.584197, [], [1, 2, 3, 4, 5, 6]), + (1720325287.360716, [], [1, 2, 3, 4, 5, 6]), + (1720325289.430457, [], [1, 2, 3, 4, 5, 6]), + (1720392144.674955, [], [1, 2, 3, 4, 5, 6]), + (1720392146.786158, [], [1, 2, 3, 4, 5, 6]), + (1720406690.885685, [], [1, 2, 3, 4, 5, 6]), + (1720406692.950513, [], [1, 2, 3, 4, 5, 6]), + (1720486441.134231, [], [1, 2, 3, 4, 5, 6]), + (1720486443.192435, [], [1, 2, 3, 4, 5, 6]), + (1720648828.296221, [], [1, 2, 3, 4, 5, 6]), + (1720648830.340132, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719977053.236432, [], [1, 2, 3, 4, 5, 6])], + [(1720146886.388756, [], [1, 2, 3, 4, 5, 6])], + [(1720147721.983335, [], [1, 2, 3, 4, 5, 6]), (1720577319.095652, [], [1, 2, 3, 4, 5, 6])], + [(1720187232.833461, [], [1, 2, 3, 4, 5, 6])], + [(1720309745.334443, [], [1, 2, 3, 4, 5, 6]), (1720525020.981442, [], [1, 2, 3, 4, 5, 6])], + [(1719985270.896874, [], [1, 2, 3, 4, 5, 6]), (1720147203.361104, [], [1, 2, 3, 4, 5, 6])], + [(1719975189.590595, [], [1, 2, 3, 4, 5, 6])], + [ + (1720153681.561666, [], [1, 2, 3, 4, 5, 6]), + (1720315141.854012, [], [1, 2, 3, 4, 5, 6]), + (1720483759.06017, [], [1, 2, 3, 4, 5, 6]), + (1720632532.362134, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719969377.021113, [], [1, 2, 3, 4, 5, 6]), + (1719969547.865829, [], [1, 2, 3, 4, 5, 6]), + (1720050670.589639, [], [1, 2, 3, 4, 5, 6]), + (1720050713.412665, [], [1, 2, 3, 4, 5, 6]), + (1720139076.150907, [], [1, 2, 3, 4, 5, 6]), + (1720139087.933212, [], [1, 2, 3, 4, 5, 6]), + (1720139090.022598, [], [1, 2, 3, 4, 5, 6]), + (1720139092.090332, [], [1, 2, 3, 4, 5, 6]), + (1720148904.698605, [], [1, 2, 3, 4, 5, 6]), + (1720197454.202625, [], [1, 2, 3, 4, 5, 6]), + (1720197456.301898, [], [1, 2, 3, 4, 5, 6]), + (1720221957.937687, [], [1, 2, 3, 4, 5, 6]), + (1720222151.210074, [], [1, 2, 3, 4, 5, 6]), + (1720222153.281944, [], [1, 2, 3, 4, 5, 6]), + (1720231319.785278, [], [1, 2, 3, 4, 5, 6]), + (1720314287.823226, [], [1, 2, 3, 4, 5, 6]), + (1720314375.707773, [], [1, 2, 3, 4, 5, 6]), + (1720314377.787834, [], [1, 2, 3, 4, 5, 6]), + (1720331369.745063, [], [1, 2, 3, 4, 5, 6]), + (1720331582.949466, [], [1, 2, 3, 4, 5, 6]), + (1720331585.058912, [], [1, 2, 3, 4, 5, 6]), + (1720399235.526545, [], [1, 2, 3, 4, 5, 6]), + (1720399237.6268, [], [1, 2, 3, 4, 5, 6]), + (1720410762.341061, [], [1, 2, 3, 4, 5, 6]), + (1720410808.990309, [], [1, 2, 3, 4, 5, 6]), + (1720410811.040448, [], [1, 2, 3, 4, 5, 6]), + (1720493330.828194, [], [1, 2, 3, 4, 5, 6]), + (1720493516.887173, [], [1, 2, 3, 4, 5, 6]), + (1720501442.580123, [], [1, 2, 3, 4, 5, 6]), + (1720501548.316894, [], [1, 2, 3, 4, 5, 6]), + (1720501550.379738, [], [1, 2, 3, 4, 5, 6]), + (1720573012.279738, [], [1, 2, 3, 4, 5, 6]), + (1720573204.24471, [], [1, 2, 3, 4, 5, 6]), + (1720573206.359087, [], [1, 2, 3, 4, 5, 6]), + (1720573210.996145, [], [1, 2, 3, 4, 5, 6]), + (1720573213.096745, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719984464.146305, [], [1, 2, 3, 4, 5, 6])], + [(1719969484.575186, [], [1, 2, 3, 4, 5, 6])], + [(1719967098.321792, [], [1, 2, 3, 4, 5, 6]), (1720140304.171738, [], [1, 2, 3, 4, 5, 6])], + [ + (1720067679.407113, [], [1, 2, 3, 4, 5, 6]), + (1720240007.297001, [], [1, 2, 3, 4, 5, 6]), + (1720499615.946055, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719984745.989291, [], [1, 2, 3, 4, 5, 6]), + (1720088802.060799, [], [1, 2, 3, 4, 5, 6]), + (1720226330.102201, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720057325.702019, [], [1, 2, 3, 4, 5, 6]), (1720499465.567145, [], [1, 2, 3, 4, 5, 6])], + [ + (1720055478.668518, [], [1, 2, 3, 4, 5, 6]), + (1720055619.422527, [], [1, 2, 3, 4, 5, 6]), + (1720138025.392906, [], [1, 2, 3, 4, 5, 6]), + (1720138074.32289, [], [1, 2, 3, 4, 5, 6]), + (1720232045.90559, [], [1, 2, 3, 4, 5, 6]), + (1720232073.337701, [], [1, 2, 3, 4, 5, 6]), + (1720278094.793407, [], [1, 2, 3, 4, 5, 6]), + (1720278096.912409, [], [1, 2, 3, 4, 5, 6]), + (1720278099.569789, [], [1, 2, 3, 4, 5, 6]), + (1720278101.660519, [], [1, 2, 3, 4, 5, 6]), + (1720324663.973123, [], [1, 2, 3, 4, 5, 6]), + (1720324666.034118, [], [1, 2, 3, 4, 5, 6]), + (1720412864.0991, [], [1, 2, 3, 4, 5, 6]), + (1720412932.896312, [], [1, 2, 3, 4, 5, 6]), + (1720412934.95735, [], [1, 2, 3, 4, 5, 6]), + (1720493768.204791, [], [1, 2, 3, 4, 5, 6]), + (1720493848.668367, [], [1, 2, 3, 4, 5, 6]), + (1720493850.800293, [], [1, 2, 3, 4, 5, 6]), + (1720493853.855696, [], [1, 2, 3, 4, 5, 6]), + (1720578407.565863, [], [1, 2, 3, 4, 5, 6]), + (1720578455.012928, [], [1, 2, 3, 4, 5, 6]), + (1720578457.12311, [], [1, 2, 3, 4, 5, 6]), + (1720592507.954368, [], [1, 2, 3, 4, 5, 6]), + (1720592695.674207, [], [1, 2, 3, 4, 5, 6]), + (1720592697.763035, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720448820.538088, [], [1, 2, 3, 4, 5, 6]), + (1720448848.354821, [], [1, 2, 3, 4, 5, 6]), + (1720448968.980221, [], [1, 2, 3, 4, 5, 6]), + (1720449109.647373, [], [1, 2, 3, 4, 5, 6]), + (1720449132.605916, [], [1, 2, 3, 4, 5, 6]), + (1720449141.226924, [], [1, 2, 3, 4, 5, 6]), + (1720449174.132961, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720143295.563285, [], [1, 2, 3, 4, 5, 6])], + [ + (1720009875.184202, [], [1, 2, 3, 4, 5, 6]), + (1720064301.403426, [], [1, 2, 3, 4, 5, 6]), + (1720221459.433168, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720316122.630709, [], [1, 2, 3, 4, 5, 6]), (1720625396.811387, [], [1, 2, 3, 4, 5, 6])], + [(1720064525.079458, [], [1, 2, 3, 4, 5, 6])], + [(1720600790.059805, [], [1, 2, 3, 4, 5, 6])], + [(1720053513.239524, [], [1, 2, 3, 4, 5, 6]), (1720533559.490134, [], [1, 2, 3, 4, 5, 6])], + [(1720222657.803241, [], [1, 2, 3, 4, 5, 6])], + [ + (1719971419.792625, [], [1, 2, 3, 4, 5, 6]), + (1720239049.653382, [], [1, 2, 3, 4, 5, 6]), + (1720497253.487835, [], [1, 2, 3, 4, 5, 6]), + (1720571009.60795, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719978213.57048, [], [1, 2, 3, 4, 5, 6]), + (1719978402.543586, [], [1, 2, 3, 4, 5, 6]), + (1720067921.564313, [], [1, 2, 3, 4, 5, 6]), + (1720068031.2973, [], [1, 2, 3, 4, 5, 6]), + (1720068033.364045, [], [1, 2, 3, 4, 5, 6]), + (1720076693.193638, [], [1, 2, 3, 4, 5, 6]), + (1720076695.234922, [], [1, 2, 3, 4, 5, 6]), + (1720088372.082518, [], [1, 2, 3, 4, 5, 6]), + (1720088448.747115, [], [1, 2, 3, 4, 5, 6]), + (1720222636.476764, [], [1, 2, 3, 4, 5, 6]), + (1720222701.214913, [], [1, 2, 3, 4, 5, 6]), + (1720311136.481341, [], [1, 2, 3, 4, 5, 6]), + (1720311279.356667, [], [1, 2, 3, 4, 5, 6]), + (1720311281.435353, [], [1, 2, 3, 4, 5, 6]), + (1720321937.516249, [], [1, 2, 3, 4, 5, 6]), + (1720321977.750869, [], [1, 2, 3, 4, 5, 6]), + (1720321979.826956, [], [1, 2, 3, 4, 5, 6]), + (1720321983.309368, [], [1, 2, 3, 4, 5, 6]), + (1720417820.177018, [], [1, 2, 3, 4, 5, 6]), + (1720417888.907443, [], [1, 2, 3, 4, 5, 6]), + (1720482544.485269, [], [1, 2, 3, 4, 5, 6]), + (1720482650.874077, [], [1, 2, 3, 4, 5, 6]), + (1720571012.586842, [], [1, 2, 3, 4, 5, 6]), + (1720571014.653099, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720067135.000485, [], [1, 2, 3, 4, 5, 6]), + (1720226886.323383, [], [1, 2, 3, 4, 5, 6]), + (1720626810.190995, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720021468.494681, [], [1, 2, 3, 4, 5, 6]), (1720244311.296556, [], [1, 2, 3, 4, 5, 6])], + [ + (1720054497.052088, [], [1, 2, 3, 4, 5, 6]), + (1720315797.04068, [], [1, 2, 3, 4, 5, 6]), + (1720396623.976121, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719970439.050635, [], [1, 2, 3, 4, 5, 6]), (1720411294.606462, [], [1, 2, 3, 4, 5, 6])], + [ + (1720047660.240807, [], [1, 2, 3, 4, 5, 6]), + (1720209425.126479, [], [1, 2, 3, 4, 5, 6]), + (1720417042.301423, [], [1, 2, 3, 4, 5, 6]), + (1720579466.836909, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720068666.058135, [], [1, 2, 3, 4, 5, 6]), + (1720224717.712974, [], [1, 2, 3, 4, 5, 6]), + (1720313644.184984, [], [1, 2, 3, 4, 5, 6]), + (1720417247.572309, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720217112.012918, [], [1, 2, 3, 4, 5, 6])], + [(1720228893.793094, [], [1, 2, 3, 4, 5, 6])], + [ + (1719965114.583168, [], [1, 2, 3, 4, 5, 6]), + (1720221700.128257, [], [1, 2, 3, 4, 5, 6]), + (1720359492.65181, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720149938.452021, [], [1, 2, 3, 4, 5, 6]), + (1720150083.518978, [], [1, 2, 3, 4, 5, 6]), + (1720150100.711862, [], [1, 2, 3, 4, 5, 6]), + (1720403516.136956, [], [1, 2, 3, 4, 5, 6]), + (1720403602.399166, [], [1, 2, 3, 4, 5, 6]), + (1720403688.061721, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720016151.530651, [], [1, 2, 3, 4, 5, 6]), + (1720126052.51206, [], [1, 2, 3, 4, 5, 6]), + (1720243360.967974, [], [1, 2, 3, 4, 5, 6]), + (1720567481.805169, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720259903.388453, [], [1, 2, 3, 4, 5, 6]), (1720495071.607118, [], [1, 2, 3, 4, 5, 6])], + [ + (1719978731.351246, [], [1, 2, 3, 4, 5, 6]), + (1720142275.008236, [], [1, 2, 3, 4, 5, 6]), + (1720225627.748133, [], [1, 2, 3, 4, 5, 6]), + (1720599835.060544, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720308817.017884, [], [1, 2, 3, 4, 5, 6]), (1720500376.721695, [], [1, 2, 3, 4, 5, 6])], + [ + (1720062080.162523, [], [1, 2, 3, 4, 5, 6]), + (1720424051.051867, [], [1, 2, 3, 4, 5, 6]), + (1720577193.657241, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720226358.301934, [], [1, 2, 3, 4, 5, 6]), (1720611516.599998, [], [1, 2, 3, 4, 5, 6])], + [(1720142831.087971, [], [1, 2, 3, 4, 5, 6]), (1720568727.59182, [], [1, 2, 3, 4, 5, 6])], + [(1720045127.801767, [], [1, 2, 3, 4, 5, 6])], + [(1720598254.557545, [], [1, 2, 3, 4, 5, 6])], + [(1720230498.737196, [], [1, 2, 3, 4, 5, 6]), (1720502519.921733, [], [1, 2, 3, 4, 5, 6])], + [(1720149819.132452, [], [1, 2, 3, 4, 5, 6]), (1720317818.669453, [], [1, 2, 3, 4, 5, 6])], + [(1719965630.184525, [], [1, 2, 3, 4, 5, 6]), (1720566194.006106, [], [1, 2, 3, 4, 5, 6])], + [(1719996710.23806, [], [1, 2, 3, 4, 5, 6])], + [(1720053587.04154, [], [1, 2, 3, 4, 5, 6]), (1720476400.319672, [], [1, 2, 3, 4, 5, 6])], + [(1720238998.499612, [], [1, 2, 3, 4, 5, 6])], + [(1720049964.339669, [], [1, 2, 3, 4, 5, 6]), (1720503256.459045, [], [1, 2, 3, 4, 5, 6])], + [(1720629914.75266, [], [1, 2, 3, 4, 5, 6])], + [ + (1720067406.552276, [], [1, 2, 3, 4, 5, 6]), + (1720192823.078475, [], [1, 2, 3, 4, 5, 6]), + (1720615636.068682, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720050726.320669, [], [1, 2, 3, 4, 5, 6]), + (1720159164.117987, [], [1, 2, 3, 4, 5, 6]), + (1720583837.972687, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720470505.483407, [], [1, 2, 3, 4, 5, 6]), (1720589293.330858, [], [1, 2, 3, 4, 5, 6])], + [ + (1719990309.924021, [], [1, 2, 3, 4, 5, 6]), + (1720242385.881249, [], [1, 2, 3, 4, 5, 6]), + (1720648573.041044, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720059240.88106, [], [1, 2, 3, 4, 5, 6]), (1720486550.385795, [], [1, 2, 3, 4, 5, 6])], + [(1720232277.114726, [], [1, 2, 3, 4, 5, 6])], + [(1720156360.413945, [], [1, 2, 3, 4, 5, 6]), (1720415380.907597, [], [1, 2, 3, 4, 5, 6])], + [(1720143721.130937, [], [1, 2, 3, 4, 5, 6])], + [(1720093040.94431, [], [1, 2, 3, 4, 5, 6]), (1720230385.831757, [], [1, 2, 3, 4, 5, 6])], + [(1720313919.101562, [], [1, 2, 3, 4, 5, 6]), (1720600894.542752, [], [1, 2, 3, 4, 5, 6])], + [(1720008883.059792, [], [1, 2, 3, 4, 5, 6]), (1720151981.800615, [], [1, 2, 3, 4, 5, 6])], + [(1720583883.771582, [], [1, 2, 3, 4, 5, 6])], + [(1720054595.476172, [], [1, 2, 3, 4, 5, 6]), (1720494101.96425, [], [1, 2, 3, 4, 5, 6])], + [ + (1719975987.869421, [], [1, 2, 3, 4, 5, 6]), + (1720072012.445937, [], [1, 2, 3, 4, 5, 6]), + (1720141541.892965, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719974700.775073, [], [1, 2, 3, 4, 5, 6]), + (1719974810.784479, [], [1, 2, 3, 4, 5, 6]), + (1720022010.687673, [], [1, 2, 3, 4, 5, 6]), + (1720022125.15125, [], [1, 2, 3, 4, 5, 6]), + (1720022127.183082, [], [1, 2, 3, 4, 5, 6]), + (1720022127.850327, [], [1, 2, 3, 4, 5, 6]), + (1720022129.972437, [], [1, 2, 3, 4, 5, 6]), + (1720149346.519881, [], [1, 2, 3, 4, 5, 6]), + (1720149423.39517, [], [1, 2, 3, 4, 5, 6]), + (1720232515.945385, [], [1, 2, 3, 4, 5, 6]), + (1720232642.031851, [], [1, 2, 3, 4, 5, 6]), + (1720232644.151326, [], [1, 2, 3, 4, 5, 6]), + (1720232649.102724, [], [1, 2, 3, 4, 5, 6]), + (1720232651.213687, [], [1, 2, 3, 4, 5, 6]), + (1720291284.378849, [], [1, 2, 3, 4, 5, 6]), + (1720291307.651917, [], [1, 2, 3, 4, 5, 6]), + (1720317724.65539, [], [1, 2, 3, 4, 5, 6]), + (1720317962.176994, [], [1, 2, 3, 4, 5, 6]), + (1720317962.221761, [], [1, 2, 3, 4, 5, 6]), + (1720317967.870483, [], [1, 2, 3, 4, 5, 6]), + (1720416284.403485, [], [1, 2, 3, 4, 5, 6]), + (1720416286.45094, [], [1, 2, 3, 4, 5, 6]), + (1720446964.44037, [], [1, 2, 3, 4, 5, 6]), + (1720447111.491786, [], [1, 2, 3, 4, 5, 6]), + (1720447113.551591, [], [1, 2, 3, 4, 5, 6]), + (1720500857.609857, [], [1, 2, 3, 4, 5, 6]), + (1720500933.241251, [], [1, 2, 3, 4, 5, 6]), + (1720500935.342693, [], [1, 2, 3, 4, 5, 6]), + (1720550391.631024, [], [1, 2, 3, 4, 5, 6]), + (1720550393.677097, [], [1, 2, 3, 4, 5, 6]), + (1720571962.115275, [], [1, 2, 3, 4, 5, 6]), + (1720571964.156322, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720300973.659698, [], [1, 2, 3, 4, 5, 6]), (1720502088.420309, [], [1, 2, 3, 4, 5, 6])], + [ + (1720226060.114355, [], [1, 2, 3, 4, 5, 6]), + (1720367668.242413, [], [1, 2, 3, 4, 5, 6]), + (1720580879.469873, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720148122.993839, [], [1, 2, 3, 4, 5, 6]), + (1720283848.988921, [], [1, 2, 3, 4, 5, 6]), + (1720392902.670008, [], [1, 2, 3, 4, 5, 6]), + (1720547569.939146, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720164561.277691, [], [1, 2, 3, 4, 5, 6]), (1720322322.293618, [], [1, 2, 3, 4, 5, 6])], + [(1720394391.029382, [], [1, 2, 3, 4, 5, 6])], + [(1720578227.91725, [], [1, 2, 3, 4, 5, 6])], + [(1720427348.104988, [], [1, 2, 3, 4, 5, 6]), (1720586312.438776, [], [1, 2, 3, 4, 5, 6])], + [ + (1719967279.972433, [], [1, 2, 3, 4, 5, 6]), + (1719967282.055508, [], [1, 2, 3, 4, 5, 6]), + (1719986090.097845, [], [1, 2, 3, 4, 5, 6]), + (1719986173.00659, [], [1, 2, 3, 4, 5, 6]), + (1719986175.082864, [], [1, 2, 3, 4, 5, 6]), + (1720034526.875582, [], [1, 2, 3, 4, 5, 6]), + (1720061201.725715, [], [1, 2, 3, 4, 5, 6]), + (1720061294.240057, [], [1, 2, 3, 4, 5, 6]), + (1720061296.35589, [], [1, 2, 3, 4, 5, 6]), + (1720155141.396653, [], [1, 2, 3, 4, 5, 6]), + (1720155143.510508, [], [1, 2, 3, 4, 5, 6]), + (1720155145.301155, [], [1, 2, 3, 4, 5, 6]), + (1720155147.393972, [], [1, 2, 3, 4, 5, 6]), + (1720231098.024705, [], [1, 2, 3, 4, 5, 6]), + (1720231317.54759, [], [1, 2, 3, 4, 5, 6]), + (1720231319.611985, [], [1, 2, 3, 4, 5, 6]), + (1720271983.621164, [], [1, 2, 3, 4, 5, 6]), + (1720271985.710974, [], [1, 2, 3, 4, 5, 6]), + (1720316981.40392, [], [1, 2, 3, 4, 5, 6]), + (1720317019.941522, [], [1, 2, 3, 4, 5, 6]), + (1720317022.040965, [], [1, 2, 3, 4, 5, 6]), + (1720411936.226228, [], [1, 2, 3, 4, 5, 6]), + (1720411963.208146, [], [1, 2, 3, 4, 5, 6]), + (1720479757.589657, [], [1, 2, 3, 4, 5, 6]), + (1720479839.302922, [], [1, 2, 3, 4, 5, 6]), + (1720582109.835415, [], [1, 2, 3, 4, 5, 6]), + (1720582111.914294, [], [1, 2, 3, 4, 5, 6]), + (1720652093.707438, [], [1, 2, 3, 4, 5, 6]), + (1720652211.598303, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720579951.356488, [], [1, 2, 3, 4, 5, 6])], + [(1720593973.655643, [], [1, 2, 3, 4, 5, 6])], + [ + (1720061475.003195, [], [1, 2, 3, 4, 5, 6]), + (1720270392.101123, [], [1, 2, 3, 4, 5, 6]), + (1720415797.057544, [], [1, 2, 3, 4, 5, 6]), + (1720574029.592383, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719987865.032004, [], [1, 2, 3, 4, 5, 6]), (1720212776.214811, [], [1, 2, 3, 4, 5, 6])], + [(1720315089.869542, [], [1, 2, 3, 4, 5, 6]), (1720578088.622431, [], [1, 2, 3, 4, 5, 6])], + [(1720575422.335555, [], [1, 2, 3, 4, 5, 6])], + [(1720329438.482756, [], [1, 2, 3, 4, 5, 6]), (1720443842.432414, [], [1, 2, 3, 4, 5, 6])], + [ + (1720135846.308239, [], [1, 2, 3, 4, 5, 6]), + (1720221161.535587, [], [1, 2, 3, 4, 5, 6]), + (1720326226.738859, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719977789.721113, [], [1, 2, 3, 4, 5, 6]), + (1719977899.031956, [], [1, 2, 3, 4, 5, 6]), + (1719977901.119465, [], [1, 2, 3, 4, 5, 6]), + (1719982587.985388, [], [1, 2, 3, 4, 5, 6]), + (1719982666.211377, [], [1, 2, 3, 4, 5, 6]), + (1719982668.29279, [], [1, 2, 3, 4, 5, 6]), + (1719982672.56956, [], [1, 2, 3, 4, 5, 6]), + (1720063592.708606, [], [1, 2, 3, 4, 5, 6]), + (1720063594.776009, [], [1, 2, 3, 4, 5, 6]), + (1720145103.906614, [], [1, 2, 3, 4, 5, 6]), + (1720145165.665926, [], [1, 2, 3, 4, 5, 6]), + (1720157026.459569, [], [1, 2, 3, 4, 5, 6]), + (1720223512.011646, [], [1, 2, 3, 4, 5, 6]), + (1720223586.453989, [], [1, 2, 3, 4, 5, 6]), + (1720223588.535794, [], [1, 2, 3, 4, 5, 6]), + (1720329405.565358, [], [1, 2, 3, 4, 5, 6]), + (1720398313.307695, [], [1, 2, 3, 4, 5, 6]), + (1720398429.724071, [], [1, 2, 3, 4, 5, 6]), + (1720414381.775047, [], [1, 2, 3, 4, 5, 6]), + (1720446240.471098, [], [1, 2, 3, 4, 5, 6]), + (1720481889.793923, [], [1, 2, 3, 4, 5, 6]), + (1720481891.93036, [], [1, 2, 3, 4, 5, 6]), + (1720489136.015971, [], [1, 2, 3, 4, 5, 6]), + (1720489247.728734, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720318482.752639, [], [1, 2, 3, 4, 5, 6])], + [ + (1720242162.48487, [], [1, 2, 3, 4, 5, 6]), + (1720503535.294123, [], [1, 2, 3, 4, 5, 6]), + (1720590538.582039, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720148407.104121, [], [1, 2, 3, 4, 5, 6])], + [(1720154168.367205, [], [1, 2, 3, 4, 5, 6]), (1720568213.544423, [], [1, 2, 3, 4, 5, 6])], + [ + (1720069001.717509, [], [1, 2, 3, 4, 5, 6]), + (1720346135.538471, [], [1, 2, 3, 4, 5, 6]), + (1720489854.284499, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719967260.706099, [], [1, 2, 3, 4, 5, 6]), + (1720082538.484733, [], [1, 2, 3, 4, 5, 6]), + (1720240732.567635, [], [1, 2, 3, 4, 5, 6]), + (1720395713.187024, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719968640.279026, [], [1, 2, 3, 4, 5, 6]), + (1720058387.048155, [], [1, 2, 3, 4, 5, 6]), + (1720240163.514327, [], [1, 2, 3, 4, 5, 6]), + (1720391336.792179, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720310285.653948, [], [1, 2, 3, 4, 5, 6]), (1720589147.207321, [], [1, 2, 3, 4, 5, 6])], + [(1719973140.021275, [], [1, 2, 3, 4, 5, 6]), (1720504055.006021, [], [1, 2, 3, 4, 5, 6])], + [(1720115792.85023, [], [1, 2, 3, 4, 5, 6])], + [ + (1720140689.444004, [], [1, 2, 3, 4, 5, 6]), + (1720312169.980048, [], [1, 2, 3, 4, 5, 6]), + (1720399894.527727, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720316227.642169, [], [1, 2, 3, 4, 5, 6]), (1720484121.740556, [], [1, 2, 3, 4, 5, 6])], + [ + (1720150629.632571, [], [1, 2, 3, 4, 5, 6]), + (1720312593.72112, [], [1, 2, 3, 4, 5, 6]), + (1720584121.246833, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719966806.196729, [], [1, 2, 3, 4, 5, 6]), (1720492831.262792, [], [1, 2, 3, 4, 5, 6])], + [ + (1720069584.25825, [], [1, 2, 3, 4, 5, 6]), + (1720233172.76065, [], [1, 2, 3, 4, 5, 6]), + (1720317363.164219, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720227600.733956, [], [1, 2, 3, 4, 5, 6]), + (1720227600.784387, [], [1, 2, 3, 4, 5, 6]), + (1720227605.27419, [], [1, 2, 3, 4, 5, 6]), + (1720269710.791405, [], [1, 2, 3, 4, 5, 6]), + (1720269759.332462, [], [1, 2, 3, 4, 5, 6]), + (1720326344.424672, [], [1, 2, 3, 4, 5, 6]), + (1720369614.287387, [], [1, 2, 3, 4, 5, 6]), + (1720369719.27491, [], [1, 2, 3, 4, 5, 6]), + (1720369719.331218, [], [1, 2, 3, 4, 5, 6]), + (1720369721.899004, [], [1, 2, 3, 4, 5, 6]), + (1720385493.685201, [], [1, 2, 3, 4, 5, 6]), + (1720385551.219825, [], [1, 2, 3, 4, 5, 6]), + (1720385553.316418, [], [1, 2, 3, 4, 5, 6]), + (1720450115.39061, [], [1, 2, 3, 4, 5, 6]), + (1720450117.502598, [], [1, 2, 3, 4, 5, 6]), + (1720450118.78177, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719969800.978378, [], [1, 2, 3, 4, 5, 6]), + (1720222415.35262, [], [1, 2, 3, 4, 5, 6]), + (1720434706.74629, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720237451.24597, [], [1, 2, 3, 4, 5, 6]), (1720585495.150654, [], [1, 2, 3, 4, 5, 6])], + [(1719970937.04025, [], [1, 2, 3, 4, 5, 6])], + [ + (1719983075.420902, [], [1, 2, 3, 4, 5, 6]), + (1720313367.078665, [], [1, 2, 3, 4, 5, 6]), + (1720413122.113225, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720155749.238687, [], [1, 2, 3, 4, 5, 6]), (1720491353.243799, [], [1, 2, 3, 4, 5, 6])], + [(1720060021.000595, [], [1, 2, 3, 4, 5, 6])], + [(1719988378.536367, [], [1, 2, 3, 4, 5, 6]), (1720228662.183092, [], [1, 2, 3, 4, 5, 6])], + [(1719981886.782157, [], [1, 2, 3, 4, 5, 6]), (1720156878.496962, [], [1, 2, 3, 4, 5, 6])], + [(1720582313.689559, [], [1, 2, 3, 4, 5, 6])], + [(1720232302.477057, [], [1, 2, 3, 4, 5, 6]), (1720493756.958556, [], [1, 2, 3, 4, 5, 6])], + [(1720295778.241704, [], [1, 2, 3, 4, 5, 6])], + [(1720021503.203052, [], [1, 2, 3, 4, 5, 6]), (1720325452.491454, [], [1, 2, 3, 4, 5, 6])], + [(1720527219.478404, [], [1, 2, 3, 4, 5, 6]), (1720567646.306507, [], [1, 2, 3, 4, 5, 6])], + [(1720223792.29193, [], [1, 2, 3, 4, 5, 6])], + [ + (1720006636.772706, [], [1, 2, 3, 4, 5, 6]), + (1720006795.60427, [], [1, 2, 3, 4, 5, 6]), + (1720006845.799981, [], [1, 2, 3, 4, 5, 6]), + (1720007022.741945, [], [1, 2, 3, 4, 5, 6]), + (1720007095.581047, [], [1, 2, 3, 4, 5, 6]), + (1720007134.850115, [], [1, 2, 3, 4, 5, 6]), + (1720025117.762503, [], [1, 2, 3, 4, 5, 6]), + (1720025308.512649, [], [1, 2, 3, 4, 5, 6]), + (1720025310.568037, [], [1, 2, 3, 4, 5, 6]), + (1720052547.163003, [], [1, 2, 3, 4, 5, 6]), + (1720052600.03312, [], [1, 2, 3, 4, 5, 6]), + (1720068046.902248, [], [1, 2, 3, 4, 5, 6]), + (1720068213.189912, [], [1, 2, 3, 4, 5, 6]), + (1720144711.311281, [], [1, 2, 3, 4, 5, 6]), + (1720144713.407177, [], [1, 2, 3, 4, 5, 6]), + (1720222638.332245, [], [1, 2, 3, 4, 5, 6]), + (1720222640.418838, [], [1, 2, 3, 4, 5, 6]), + (1720242141.813366, [], [1, 2, 3, 4, 5, 6]), + (1720242245.921587, [], [1, 2, 3, 4, 5, 6]), + (1720242248.011768, [], [1, 2, 3, 4, 5, 6]), + (1720333146.03005, [], [1, 2, 3, 4, 5, 6]), + (1720333287.562561, [], [1, 2, 3, 4, 5, 6]), + (1720333289.592652, [], [1, 2, 3, 4, 5, 6]), + (1720333292.319879, [], [1, 2, 3, 4, 5, 6]), + (1720333294.386109, [], [1, 2, 3, 4, 5, 6]), + (1720396984.211837, [], [1, 2, 3, 4, 5, 6]), + (1720397094.401782, [], [1, 2, 3, 4, 5, 6]), + (1720486134.144443, [], [1, 2, 3, 4, 5, 6]), + (1720486136.211044, [], [1, 2, 3, 4, 5, 6]), + (1720486140.873481, [], [1, 2, 3, 4, 5, 6]), + (1720486142.970428, [], [1, 2, 3, 4, 5, 6]), + (1720497754.706526, [], [1, 2, 3, 4, 5, 6]), + (1720497979.155047, [], [1, 2, 3, 4, 5, 6]), + (1720531991.462042, [], [1, 2, 3, 4, 5, 6]), + (1720532199.030662, [], [1, 2, 3, 4, 5, 6]), + (1720588796.771517, [], [1, 2, 3, 4, 5, 6]), + (1720588842.077879, [], [1, 2, 3, 4, 5, 6]), + (1720588844.116306, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720239926.764196, [], [1, 2, 3, 4, 5, 6])], + [(1720395045.1902, [], [1, 2, 3, 4, 5, 6])], + [(1720431147.297621, [], [1, 2, 3, 4, 5, 6])], + [(1720240748.713179, [], [1, 2, 3, 4, 5, 6])], + [(1719972432.742571, [], [1, 2, 3, 4, 5, 6])], + [(1720410198.607466, [], [1, 2, 3, 4, 5, 6]), (1720566548.549011, [], [1, 2, 3, 4, 5, 6])], + [(1720455428.865155, [], [1, 2, 3, 4, 5, 6])], + [(1720498325.755933, [], [1, 2, 3, 4, 5, 6])], + [ + (1719983684.033908, [], [1, 2, 3, 4, 5, 6]), + (1720319741.991515, [], [1, 2, 3, 4, 5, 6]), + (1720414800.645761, [], [1, 2, 3, 4, 5, 6]), + (1720484979.12583, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720134283.600008, [], [1, 2, 3, 4, 5, 6])], + [(1720409485.01654, [], [1, 2, 3, 4, 5, 6])], + [ + (1719981074.661088, [], [1, 2, 3, 4, 5, 6]), + (1720143880.41593, [], [1, 2, 3, 4, 5, 6]), + (1720229983.175788, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720060903.203334, [], [1, 2, 3, 4, 5, 6])], + [ + (1719968419.743912, [], [1, 2, 3, 4, 5, 6]), + (1719968490.438903, [], [1, 2, 3, 4, 5, 6]), + (1719968620.857174, [], [1, 2, 3, 4, 5, 6]), + (1720498112.351156, [], [1, 2, 3, 4, 5, 6]), + (1720498358.36836, [], [1, 2, 3, 4, 5, 6]), + (1720498468.250047, [], [1, 2, 3, 4, 5, 6]), + (1720574778.111823, [], [1, 2, 3, 4, 5, 6]), + (1720574806.5479, [], [1, 2, 3, 4, 5, 6]), + (1720574917.425735, [], [1, 2, 3, 4, 5, 6]), + (1720574933.603291, [], [1, 2, 3, 4, 5, 6]), + (1720575020.164914, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720406407.483318, [], [1, 2, 3, 4, 5, 6])], + [(1720412099.352018, [], [1, 2, 3, 4, 5, 6]), (1720498223.084881, [], [1, 2, 3, 4, 5, 6])], + [ + (1719979024.598321, [], [1, 2, 3, 4, 5, 6]), + (1720114791.984992, [], [1, 2, 3, 4, 5, 6]), + (1720241390.157269, [], [1, 2, 3, 4, 5, 6]), + (1720500283.345509, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720569522.382331, [], [1, 2, 3, 4, 5, 6])], + [(1720146840.111051, [], [1, 2, 3, 4, 5, 6]), (1720287268.372643, [], [1, 2, 3, 4, 5, 6])], + [(1720583508.926048, [], [1, 2, 3, 4, 5, 6])], + [ + (1720229146.528014, [], [1, 2, 3, 4, 5, 6]), + (1720229340.131801, [], [1, 2, 3, 4, 5, 6]), + (1720229424.480475, [], [1, 2, 3, 4, 5, 6]), + (1720229565.859999, [], [1, 2, 3, 4, 5, 6]), + (1720229567.783491, [], [1, 2, 3, 4, 5, 6]), + (1720229693.297904, [], [1, 2, 3, 4, 5, 6]), + (1720229755.453165, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720098291.146186, [], [1, 2, 3, 4, 5, 6])], + [(1719983104.788269, [], [1, 2, 3, 4, 5, 6]), (1720070626.816099, [], [1, 2, 3, 4, 5, 6])], + [ + (1720226820.995006, [], [1, 2, 3, 4, 5, 6]), + (1720316639.892049, [], [1, 2, 3, 4, 5, 6]), + (1720589368.875624, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720070877.576019, [], [1, 2, 3, 4, 5, 6]), (1720234703.959519, [], [1, 2, 3, 4, 5, 6])], + [ + (1719978870.060134, [], [1, 2, 3, 4, 5, 6]), + (1720137971.413991, [], [1, 2, 3, 4, 5, 6]), + (1720491059.303159, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719995043.481796, [], [1, 2, 3, 4, 5, 6]), (1720148819.805573, [], [1, 2, 3, 4, 5, 6])], + [ + (1720052005.359573, [], [1, 2, 3, 4, 5, 6]), + (1720052127.565063, [], [1, 2, 3, 4, 5, 6]), + (1720052129.679258, [], [1, 2, 3, 4, 5, 6]), + (1720064915.795875, [], [1, 2, 3, 4, 5, 6]), + (1720064917.840723, [], [1, 2, 3, 4, 5, 6]), + (1720064919.250429, [], [1, 2, 3, 4, 5, 6]), + (1720140563.359858, [], [1, 2, 3, 4, 5, 6]), + (1720140686.221967, [], [1, 2, 3, 4, 5, 6]), + (1720147133.126896, [], [1, 2, 3, 4, 5, 6]), + (1720154606.237768, [], [1, 2, 3, 4, 5, 6]), + (1720208312.107821, [], [1, 2, 3, 4, 5, 6]), + (1720208397.77235, [], [1, 2, 3, 4, 5, 6]), + (1720208399.88578, [], [1, 2, 3, 4, 5, 6]), + (1720226692.740751, [], [1, 2, 3, 4, 5, 6]), + (1720226809.874422, [], [1, 2, 3, 4, 5, 6]), + (1720226811.929607, [], [1, 2, 3, 4, 5, 6]), + (1720320735.680282, [], [1, 2, 3, 4, 5, 6]), + (1720320737.781583, [], [1, 2, 3, 4, 5, 6]), + (1720394544.101953, [], [1, 2, 3, 4, 5, 6]), + (1720394546.228449, [], [1, 2, 3, 4, 5, 6]), + (1720411628.159882, [], [1, 2, 3, 4, 5, 6]), + (1720411765.678009, [], [1, 2, 3, 4, 5, 6]), + (1720411765.737071, [], [1, 2, 3, 4, 5, 6]), + (1720411771.063593, [], [1, 2, 3, 4, 5, 6]), + (1720493021.815332, [], [1, 2, 3, 4, 5, 6]), + (1720493023.89141, [], [1, 2, 3, 4, 5, 6]), + (1720547092.818141, [], [1, 2, 3, 4, 5, 6]), + (1720547133.337079, [], [1, 2, 3, 4, 5, 6]), + (1720566405.934125, [], [1, 2, 3, 4, 5, 6]), + (1720566407.979963, [], [1, 2, 3, 4, 5, 6]), + (1720592934.864349, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720407281.391395, [], [1, 2, 3, 4, 5, 6]), (1720578489.911262, [], [1, 2, 3, 4, 5, 6])], + [(1720393905.799101, [], [1, 2, 3, 4, 5, 6])], + [ + (1719965431.440319, [], [1, 2, 3, 4, 5, 6]), + (1719965547.770505, [], [1, 2, 3, 4, 5, 6]), + (1719965549.880668, [], [1, 2, 3, 4, 5, 6]), + (1720010279.644796, [], [1, 2, 3, 4, 5, 6]), + (1720010481.117481, [], [1, 2, 3, 4, 5, 6]), + (1720060297.061777, [], [1, 2, 3, 4, 5, 6]), + (1720060299.106745, [], [1, 2, 3, 4, 5, 6]), + (1720072795.790373, [], [1, 2, 3, 4, 5, 6]), + (1720072933.175213, [], [1, 2, 3, 4, 5, 6]), + (1720138923.382269, [], [1, 2, 3, 4, 5, 6]), + (1720138952.892452, [], [1, 2, 3, 4, 5, 6]), + (1720138954.952138, [], [1, 2, 3, 4, 5, 6]), + (1720243737.055635, [], [1, 2, 3, 4, 5, 6]), + (1720243742.725476, [], [1, 2, 3, 4, 5, 6]), + (1720243744.812736, [], [1, 2, 3, 4, 5, 6]), + (1720278868.092914, [], [1, 2, 3, 4, 5, 6]), + (1720278981.120539, [], [1, 2, 3, 4, 5, 6]), + (1720278983.221413, [], [1, 2, 3, 4, 5, 6]), + (1720312851.319112, [], [1, 2, 3, 4, 5, 6]), + (1720312961.59678, [], [1, 2, 3, 4, 5, 6]), + (1720312963.701002, [], [1, 2, 3, 4, 5, 6]), + (1720401167.589016, [], [1, 2, 3, 4, 5, 6]), + (1720401192.232905, [], [1, 2, 3, 4, 5, 6]), + (1720488671.153932, [], [1, 2, 3, 4, 5, 6]), + (1720488673.262556, [], [1, 2, 3, 4, 5, 6]), + (1720498148.914747, [], [1, 2, 3, 4, 5, 6]), + (1720498151.01221, [], [1, 2, 3, 4, 5, 6]), + (1720585902.00157, [], [1, 2, 3, 4, 5, 6]), + (1720585904.068243, [], [1, 2, 3, 4, 5, 6]), + (1720627230.183177, [], [1, 2, 3, 4, 5, 6]), + (1720627251.343451, [], [1, 2, 3, 4, 5, 6]), + (1720627253.395817, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720049050.269443, [], [1, 2, 3, 4, 5, 6])], + [(1720406587.77676, [], [1, 2, 3, 4, 5, 6])], + [ + (1720201120.604139, [], [1, 2, 3, 4, 5, 6]), + (1720237348.670203, [], [1, 2, 3, 4, 5, 6]), + (1720503188.882528, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720137961.069782, [], [1, 2, 3, 4, 5, 6]), (1720233994.333193, [], [1, 2, 3, 4, 5, 6])], + [(1720148673.115174, [], [1, 2, 3, 4, 5, 6])], + [ + (1720017472.013793, [], [1, 2, 3, 4, 5, 6]), + (1720238395.438066, [], [1, 2, 3, 4, 5, 6]), + (1720481118.520931, [], [1, 2, 3, 4, 5, 6]), + (1720624077.141735, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720460985.277631, [], [1, 2, 3, 4, 5, 6])], + [(1720065960.10824, [], [1, 2, 3, 4, 5, 6]), (1720568092.250721, [], [1, 2, 3, 4, 5, 6])], + [(1719964803.220143, [], [1, 2, 3, 4, 5, 6]), (1720072690.78503, [], [1, 2, 3, 4, 5, 6])], + [(1719973118.028284, [], [1, 2, 3, 4, 5, 6])], + [(1720148963.270876, [], [1, 2, 3, 4, 5, 6])], + [ + (1720055800.056897, [], [1, 2, 3, 4, 5, 6]), + (1720147428.656208, [], [1, 2, 3, 4, 5, 6]), + (1720237025.123131, [], [1, 2, 3, 4, 5, 6]), + (1720326902.440989, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719967443.988967, [], [1, 2, 3, 4, 5, 6]), + (1719967507.96168, [], [1, 2, 3, 4, 5, 6]), + (1719967510.01003, [], [1, 2, 3, 4, 5, 6]), + (1719967510.547419, [], [1, 2, 3, 4, 5, 6]), + (1719967512.630086, [], [1, 2, 3, 4, 5, 6]), + (1720138300.130825, [], [1, 2, 3, 4, 5, 6]), + (1720138300.228601, [], [1, 2, 3, 4, 5, 6]), + (1720138302.137449, [], [1, 2, 3, 4, 5, 6]), + (1720266243.760636, [], [1, 2, 3, 4, 5, 6]), + (1720266262.29505, [], [1, 2, 3, 4, 5, 6]), + (1720266262.382243, [], [1, 2, 3, 4, 5, 6]), + (1720266267.714044, [], [1, 2, 3, 4, 5, 6]), + (1720376066.44502, [], [1, 2, 3, 4, 5, 6]), + (1720376075.005446, [], [1, 2, 3, 4, 5, 6]), + (1720376075.055395, [], [1, 2, 3, 4, 5, 6]), + (1720376078.271297, [], [1, 2, 3, 4, 5, 6]), + (1720495615.317205, [], [1, 2, 3, 4, 5, 6]), + (1720495625.121167, [], [1, 2, 3, 4, 5, 6]), + (1720495627.190587, [], [1, 2, 3, 4, 5, 6]), + (1720495631.668389, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720094115.933922, [], [1, 2, 3, 4, 5, 6])], + [(1720327035.126978, [], [1, 2, 3, 4, 5, 6]), (1720652576.382878, [], [1, 2, 3, 4, 5, 6])], + [(1720494001.577927, [], [1, 2, 3, 4, 5, 6])], + [ + (1720102356.301353, [], [1, 2, 3, 4, 5, 6]), + (1720244955.2084, [], [1, 2, 3, 4, 5, 6]), + (1720393949.41044, [], [1, 2, 3, 4, 5, 6]), + (1720576986.579566, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720033048.609785, [], [1, 2, 3, 4, 5, 6])], + [(1720402968.773862, [], [1, 2, 3, 4, 5, 6])], + [(1720230211.716966, [], [1, 2, 3, 4, 5, 6])], + [ + (1720059787.289306, [], [1, 2, 3, 4, 5, 6]), + (1720397378.208597, [], [1, 2, 3, 4, 5, 6]), + (1720481196.422422, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720003149.057462, [], [1, 2, 3, 4, 5, 6]), + (1720003372.883061, [], [1, 2, 3, 4, 5, 6]), + (1720003374.955179, [], [1, 2, 3, 4, 5, 6]), + (1720039541.861276, [], [1, 2, 3, 4, 5, 6]), + (1720039688.427965, [], [1, 2, 3, 4, 5, 6]), + (1720039690.485555, [], [1, 2, 3, 4, 5, 6]), + (1720048625.116329, [], [1, 2, 3, 4, 5, 6]), + (1720048725.117697, [], [1, 2, 3, 4, 5, 6]), + (1720141659.610639, [], [1, 2, 3, 4, 5, 6]), + (1720141661.665952, [], [1, 2, 3, 4, 5, 6]), + (1720196426.042225, [], [1, 2, 3, 4, 5, 6]), + (1720196487.09087, [], [1, 2, 3, 4, 5, 6]), + (1720196489.183893, [], [1, 2, 3, 4, 5, 6]), + (1720207066.952798, [], [1, 2, 3, 4, 5, 6]), + (1720207237.857105, [], [1, 2, 3, 4, 5, 6]), + (1720207239.919375, [], [1, 2, 3, 4, 5, 6]), + (1720271033.503072, [], [1, 2, 3, 4, 5, 6]), + (1720271035.587795, [], [1, 2, 3, 4, 5, 6]), + (1720583123.471438, [], [1, 2, 3, 4, 5, 6]), + (1720583125.576798, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720154856.626343, [], [1, 2, 3, 4, 5, 6]), + (1720226072.346309, [], [1, 2, 3, 4, 5, 6]), + (1720310601.449016, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720242303.35601, [], [1, 2, 3, 4, 5, 6])], + [(1720078404.748142, [], [1, 2, 3, 4, 5, 6]), (1720147584.809447, [], [1, 2, 3, 4, 5, 6])], + [(1720178488.289574, [], [1, 2, 3, 4, 5, 6]), (1720306985.894457, [], [1, 2, 3, 4, 5, 6])], + [(1720146748.830901, [], [1, 2, 3, 4, 5, 6]), (1720406666.368212, [], [1, 2, 3, 4, 5, 6])], + [ + (1720023013.684634, [], [1, 2, 3, 4, 5, 6]), + (1720091577.184398, [], [1, 2, 3, 4, 5, 6]), + (1720415121.299085, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720056649.932043, [], [1, 2, 3, 4, 5, 6])], + [ + (1720323285.584787, [], [1, 2, 3, 4, 5, 6]), + (1720415154.592994, [], [1, 2, 3, 4, 5, 6]), + (1720437978.9498, [], [1, 2, 3, 4, 5, 6]), + (1720473849.744602, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719984649.0919, [], [1, 2, 3, 4, 5, 6]), + (1719984690.14033, [], [1, 2, 3, 4, 5, 6]), + (1720049900.611104, [], [1, 2, 3, 4, 5, 6]), + (1720049902.719326, [], [1, 2, 3, 4, 5, 6]), + (1720070202.827545, [], [1, 2, 3, 4, 5, 6]), + (1720070219.8164, [], [1, 2, 3, 4, 5, 6]), + (1720070221.892056, [], [1, 2, 3, 4, 5, 6]), + (1720137406.074377, [], [1, 2, 3, 4, 5, 6]), + (1720137495.69452, [], [1, 2, 3, 4, 5, 6]), + (1720137497.797134, [], [1, 2, 3, 4, 5, 6]), + (1720328661.139393, [], [1, 2, 3, 4, 5, 6]), + (1720328739.939669, [], [1, 2, 3, 4, 5, 6]), + (1720498901.295947, [], [1, 2, 3, 4, 5, 6]), + (1720570987.624349, [], [1, 2, 3, 4, 5, 6]), + (1720602646.235039, [], [1, 2, 3, 4, 5, 6]), + (1720602812.376711, [], [1, 2, 3, 4, 5, 6]), + (1720602814.446349, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719974528.289353, [], [1, 2, 3, 4, 5, 6]), + (1720395723.591687, [], [1, 2, 3, 4, 5, 6]), + (1720617442.004095, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719975592.337919, [], [1, 2, 3, 4, 5, 6])], + [(1720057591.780745, [], [1, 2, 3, 4, 5, 6]), (1720488152.255523, [], [1, 2, 3, 4, 5, 6])], + [ + (1720148926.955422, [], [1, 2, 3, 4, 5, 6]), + (1720232410.538746, [], [1, 2, 3, 4, 5, 6]), + (1720408447.752538, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720242892.942203, [], [1, 2, 3, 4, 5, 6]), (1720322823.10199, [], [1, 2, 3, 4, 5, 6])], + [(1720400088.852099, [], [1, 2, 3, 4, 5, 6]), (1720652752.741385, [], [1, 2, 3, 4, 5, 6])], + [(1720412428.936544, [], [1, 2, 3, 4, 5, 6]), (1720574790.414977, [], [1, 2, 3, 4, 5, 6])], + [(1720069130.346249, [], [1, 2, 3, 4, 5, 6])], + [ + (1720157382.402748, [], [1, 2, 3, 4, 5, 6]), + (1720157476.064866, [], [1, 2, 3, 4, 5, 6]), + (1720157570.728611, [], [1, 2, 3, 4, 5, 6]), + (1720157662.381552, [], [1, 2, 3, 4, 5, 6]), + (1720168580.805279, [], [1, 2, 3, 4, 5, 6]), + (1720168760.793692, [], [1, 2, 3, 4, 5, 6]), + (1720230288.646191, [], [1, 2, 3, 4, 5, 6]), + (1720230430.103977, [], [1, 2, 3, 4, 5, 6]), + (1720243393.667459, [], [1, 2, 3, 4, 5, 6]), + (1720311604.919662, [], [1, 2, 3, 4, 5, 6]), + (1720311771.258364, [], [1, 2, 3, 4, 5, 6]), + (1720311773.310317, [], [1, 2, 3, 4, 5, 6]), + (1720324823.664232, [], [1, 2, 3, 4, 5, 6]), + (1720324825.721978, [], [1, 2, 3, 4, 5, 6]), + (1720393374.344255, [], [1, 2, 3, 4, 5, 6]), + (1720410680.226051, [], [1, 2, 3, 4, 5, 6]), + (1720410682.252163, [], [1, 2, 3, 4, 5, 6]), + (1720498394.961086, [], [1, 2, 3, 4, 5, 6]), + (1720498440.73496, [], [1, 2, 3, 4, 5, 6]), + (1720569716.948564, [], [1, 2, 3, 4, 5, 6]), + (1720569812.275586, [], [1, 2, 3, 4, 5, 6]), + (1720569814.333894, [], [1, 2, 3, 4, 5, 6]), + (1720569814.53133, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719978988.407662, [], [1, 2, 3, 4, 5, 6]), + (1719978990.511958, [], [1, 2, 3, 4, 5, 6]), + (1719984066.593696, [], [1, 2, 3, 4, 5, 6]), + (1719984323.803693, [], [1, 2, 3, 4, 5, 6]), + (1719984325.863773, [], [1, 2, 3, 4, 5, 6]), + (1720152078.595081, [], [1, 2, 3, 4, 5, 6]), + (1720225565.930941, [], [1, 2, 3, 4, 5, 6]), + (1720280378.036955, [], [1, 2, 3, 4, 5, 6]), + (1720326955.218979, [], [1, 2, 3, 4, 5, 6]), + (1720326957.292481, [], [1, 2, 3, 4, 5, 6]), + (1720331017.031137, [], [1, 2, 3, 4, 5, 6]), + (1720331019.121504, [], [1, 2, 3, 4, 5, 6]), + (1720410756.685202, [], [1, 2, 3, 4, 5, 6]), + (1720410758.796614, [], [1, 2, 3, 4, 5, 6]), + (1720417802.859919, [], [1, 2, 3, 4, 5, 6]), + (1720417804.989442, [], [1, 2, 3, 4, 5, 6]), + (1720487313.059882, [], [1, 2, 3, 4, 5, 6]), + (1720487498.533155, [], [1, 2, 3, 4, 5, 6]), + (1720487500.652063, [], [1, 2, 3, 4, 5, 6]), + (1720487503.708405, [], [1, 2, 3, 4, 5, 6]), + (1720487505.805861, [], [1, 2, 3, 4, 5, 6]), + (1720501546.266299, [], [1, 2, 3, 4, 5, 6]), + (1720501655.51812, [], [1, 2, 3, 4, 5, 6]), + (1720575741.153236, [], [1, 2, 3, 4, 5, 6]), + (1720575891.79104, [], [1, 2, 3, 4, 5, 6]), + (1720589520.786652, [], [1, 2, 3, 4, 5, 6]), + (1720589642.390304, [], [1, 2, 3, 4, 5, 6]), + (1720589644.452771, [], [1, 2, 3, 4, 5, 6]), + (1720615233.591986, [], [1, 2, 3, 4, 5, 6]), + (1720615337.890481, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719971542.018584, [], [1, 2, 3, 4, 5, 6]), + (1719971788.12398, [], [1, 2, 3, 4, 5, 6]), + (1720117268.913487, [], [1, 2, 3, 4, 5, 6]), + (1720117270.991206, [], [1, 2, 3, 4, 5, 6]), + (1720143198.612101, [], [1, 2, 3, 4, 5, 6]), + (1720143429.084839, [], [1, 2, 3, 4, 5, 6]), + (1720238625.308642, [], [1, 2, 3, 4, 5, 6]), + (1720238757.81922, [], [1, 2, 3, 4, 5, 6]), + (1720238759.894117, [], [1, 2, 3, 4, 5, 6]), + (1720330550.917977, [], [1, 2, 3, 4, 5, 6]), + (1720330626.459228, [], [1, 2, 3, 4, 5, 6]), + (1720378937.313156, [], [1, 2, 3, 4, 5, 6]), + (1720379038.375789, [], [1, 2, 3, 4, 5, 6]), + (1720386358.224787, [], [1, 2, 3, 4, 5, 6]), + (1720386360.275601, [], [1, 2, 3, 4, 5, 6]), + (1720416486.117358, [], [1, 2, 3, 4, 5, 6]), + (1720416608.109114, [], [1, 2, 3, 4, 5, 6]), + (1720493716.833205, [], [1, 2, 3, 4, 5, 6]), + (1720493844.641363, [], [1, 2, 3, 4, 5, 6]), + (1720493846.67691, [], [1, 2, 3, 4, 5, 6]), + (1720568118.486107, [], [1, 2, 3, 4, 5, 6]), + (1720568219.230995, [], [1, 2, 3, 4, 5, 6]), + (1720568221.334344, [], [1, 2, 3, 4, 5, 6]), + (1720574746.351324, [], [1, 2, 3, 4, 5, 6]), + (1720574815.297689, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720233195.120615, [], [1, 2, 3, 4, 5, 6]), + (1720393731.964556, [], [1, 2, 3, 4, 5, 6]), + (1720570257.699261, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720149655.238203, [], [1, 2, 3, 4, 5, 6]), + (1720352361.227124, [], [1, 2, 3, 4, 5, 6]), + (1720578697.147852, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720411277.985506, [], [1, 2, 3, 4, 5, 6]), (1720572981.673421, [], [1, 2, 3, 4, 5, 6])], + [(1720569584.93865, [], [1, 2, 3, 4, 5, 6])], + [(1720311303.894177, [], [1, 2, 3, 4, 5, 6])], + [(1720576463.87807, [], [1, 2, 3, 4, 5, 6])], + [ + (1719982989.782732, [], [1, 2, 3, 4, 5, 6]), + (1720080708.007665, [], [1, 2, 3, 4, 5, 6]), + (1720234553.333259, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719983711.203136, [], [1, 2, 3, 4, 5, 6]), (1720395076.590109, [], [1, 2, 3, 4, 5, 6])], + [ + (1719968905.802345, [], [1, 2, 3, 4, 5, 6]), + (1720054751.228152, [], [1, 2, 3, 4, 5, 6]), + (1720393228.571573, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720151965.57438, [], [1, 2, 3, 4, 5, 6]), + (1720265917.280767, [], [1, 2, 3, 4, 5, 6]), + (1720414597.498797, [], [1, 2, 3, 4, 5, 6]), + (1720569352.211054, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720139623.448558, [], [1, 2, 3, 4, 5, 6]), (1720413909.371495, [], [1, 2, 3, 4, 5, 6])], + [ + (1720332156.972433, [], [1, 2, 3, 4, 5, 6]), + (1720486770.808084, [], [1, 2, 3, 4, 5, 6]), + (1720570506.129092, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720046377.309817, [], [1, 2, 3, 4, 5, 6]), (1720144405.103977, [], [1, 2, 3, 4, 5, 6])], + [(1720311749.460887, [], [1, 2, 3, 4, 5, 6]), (1720480404.801297, [], [1, 2, 3, 4, 5, 6])], + [(1719965504.779832, [], [1, 2, 3, 4, 5, 6])], + [(1720489219.425884, [], [1, 2, 3, 4, 5, 6])], + [(1720480774.306063, [], [1, 2, 3, 4, 5, 6])], + [(1719968486.759348, [], [1, 2, 3, 4, 5, 6]), (1720229505.650825, [], [1, 2, 3, 4, 5, 6])], + [(1720122526.844622, [], [1, 2, 3, 4, 5, 6]), (1720142320.524851, [], [1, 2, 3, 4, 5, 6])], + [(1720320995.267452, [], [1, 2, 3, 4, 5, 6])], + [ + (1719984296.990609, [], [1, 2, 3, 4, 5, 6]), + (1719984350.22369, [], [1, 2, 3, 4, 5, 6]), + (1719984352.257572, [], [1, 2, 3, 4, 5, 6]), + (1720052997.807277, [], [1, 2, 3, 4, 5, 6]), + (1720053049.304507, [], [1, 2, 3, 4, 5, 6]), + (1720053051.378602, [], [1, 2, 3, 4, 5, 6]), + (1720150389.546489, [], [1, 2, 3, 4, 5, 6]), + (1720150391.660121, [], [1, 2, 3, 4, 5, 6]), + (1720168392.833864, [], [1, 2, 3, 4, 5, 6]), + (1720168394.931787, [], [1, 2, 3, 4, 5, 6]), + (1720218901.13549, [], [1, 2, 3, 4, 5, 6]), + (1720218984.364651, [], [1, 2, 3, 4, 5, 6]), + (1720218986.444335, [], [1, 2, 3, 4, 5, 6]), + (1720236871.413173, [], [1, 2, 3, 4, 5, 6]), + (1720236873.52, [], [1, 2, 3, 4, 5, 6]), + (1720318899.245869, [], [1, 2, 3, 4, 5, 6]), + (1720319077.080816, [], [1, 2, 3, 4, 5, 6]), + (1720319079.181328, [], [1, 2, 3, 4, 5, 6]), + (1720421585.966107, [], [1, 2, 3, 4, 5, 6]), + (1720421692.177002, [], [1, 2, 3, 4, 5, 6]), + (1720421694.269891, [], [1, 2, 3, 4, 5, 6]), + (1720484559.101295, [], [1, 2, 3, 4, 5, 6]), + (1720484634.686657, [], [1, 2, 3, 4, 5, 6]), + (1720484636.791229, [], [1, 2, 3, 4, 5, 6]), + (1720484640.876498, [], [1, 2, 3, 4, 5, 6]), + (1720484642.914839, [], [1, 2, 3, 4, 5, 6]), + (1720568978.955929, [], [1, 2, 3, 4, 5, 6]), + (1720569083.551067, [], [1, 2, 3, 4, 5, 6]), + (1720603472.634189, [], [1, 2, 3, 4, 5, 6]), + (1720603622.57534, [], [1, 2, 3, 4, 5, 6]), + (1720603624.69381, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720204831.715905, [], [1, 2, 3, 4, 5, 6])], + [(1719985836.773241, [], [1, 2, 3, 4, 5, 6]), (1720227063.151216, [], [1, 2, 3, 4, 5, 6])], + [(1720226998.434162, [], [1, 2, 3, 4, 5, 6])], + [(1720413326.470543, [], [1, 2, 3, 4, 5, 6])], + [(1720484747.542658, [], [1, 2, 3, 4, 5, 6])], + [ + (1719975290.47648, [], [1, 2, 3, 4, 5, 6]), + (1719975421.539502, [], [1, 2, 3, 4, 5, 6]), + (1719975423.609947, [], [1, 2, 3, 4, 5, 6]), + (1719975424.130571, [], [1, 2, 3, 4, 5, 6]), + (1719975426.224942, [], [1, 2, 3, 4, 5, 6]), + (1720024823.782769, [], [1, 2, 3, 4, 5, 6]), + (1720024943.32157, [], [1, 2, 3, 4, 5, 6]), + (1720024945.350078, [], [1, 2, 3, 4, 5, 6]), + (1720024945.905366, [], [1, 2, 3, 4, 5, 6]), + (1720056619.663053, [], [1, 2, 3, 4, 5, 6]), + (1720056822.318399, [], [1, 2, 3, 4, 5, 6]), + (1720056824.36183, [], [1, 2, 3, 4, 5, 6]), + (1720072281.168332, [], [1, 2, 3, 4, 5, 6]), + (1720072283.222603, [], [1, 2, 3, 4, 5, 6]), + (1720134154.949613, [], [1, 2, 3, 4, 5, 6]), + (1720134376.323715, [], [1, 2, 3, 4, 5, 6]), + (1720134378.416906, [], [1, 2, 3, 4, 5, 6]), + (1720140112.874786, [], [1, 2, 3, 4, 5, 6]), + (1720140131.322854, [], [1, 2, 3, 4, 5, 6]), + (1720140133.38169, [], [1, 2, 3, 4, 5, 6]), + (1720238635.597737, [], [1, 2, 3, 4, 5, 6]), + (1720238637.672121, [], [1, 2, 3, 4, 5, 6]), + (1720418306.625113, [], [1, 2, 3, 4, 5, 6]), + (1720418333.5673, [], [1, 2, 3, 4, 5, 6]), + (1720487528.439985, [], [1, 2, 3, 4, 5, 6]), + (1720487546.337876, [], [1, 2, 3, 4, 5, 6]), + (1720487548.449392, [], [1, 2, 3, 4, 5, 6]), + (1720502509.125496, [], [1, 2, 3, 4, 5, 6]), + (1720502624.411704, [], [1, 2, 3, 4, 5, 6]), + (1720585053.028856, [], [1, 2, 3, 4, 5, 6]), + (1720585055.08891, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719982052.592392, [], [1, 2, 3, 4, 5, 6]), + (1719982258.203523, [], [1, 2, 3, 4, 5, 6]), + (1719985183.079021, [], [1, 2, 3, 4, 5, 6]), + (1719985305.780432, [], [1, 2, 3, 4, 5, 6]), + (1720055777.47168, [], [1, 2, 3, 4, 5, 6]), + (1720071284.174477, [], [1, 2, 3, 4, 5, 6]), + (1720152558.44266, [], [1, 2, 3, 4, 5, 6]), + (1720152671.333552, [], [1, 2, 3, 4, 5, 6]), + (1720152673.415669, [], [1, 2, 3, 4, 5, 6]), + (1720182134.94743, [], [1, 2, 3, 4, 5, 6]), + (1720182137.028427, [], [1, 2, 3, 4, 5, 6]), + (1720182138.842693, [], [1, 2, 3, 4, 5, 6]), + (1720182140.958073, [], [1, 2, 3, 4, 5, 6]), + (1720227575.333539, [], [1, 2, 3, 4, 5, 6]), + (1720227736.260264, [], [1, 2, 3, 4, 5, 6]), + (1720227738.300477, [], [1, 2, 3, 4, 5, 6]), + (1720236068.538351, [], [1, 2, 3, 4, 5, 6]), + (1720236070.60483, [], [1, 2, 3, 4, 5, 6]), + (1720317757.071545, [], [1, 2, 3, 4, 5, 6]), + (1720317866.130343, [], [1, 2, 3, 4, 5, 6]), + (1720317868.22788, [], [1, 2, 3, 4, 5, 6]), + (1720330462.980036, [], [1, 2, 3, 4, 5, 6]), + (1720330707.655663, [], [1, 2, 3, 4, 5, 6]), + (1720330709.750072, [], [1, 2, 3, 4, 5, 6]), + (1720373940.747523, [], [1, 2, 3, 4, 5, 6]), + (1720374027.697475, [], [1, 2, 3, 4, 5, 6]), + (1720374029.799405, [], [1, 2, 3, 4, 5, 6]), + (1720406670.90306, [], [1, 2, 3, 4, 5, 6]), + (1720406844.478936, [], [1, 2, 3, 4, 5, 6]), + (1720406846.592556, [], [1, 2, 3, 4, 5, 6]), + (1720406851.281701, [], [1, 2, 3, 4, 5, 6]), + (1720412576.66958, [], [1, 2, 3, 4, 5, 6]), + (1720412652.412012, [], [1, 2, 3, 4, 5, 6]), + (1720412654.533239, [], [1, 2, 3, 4, 5, 6]), + (1720486184.910769, [], [1, 2, 3, 4, 5, 6]), + (1720571066.49819, [], [1, 2, 3, 4, 5, 6]), + (1720626129.788949, [], [1, 2, 3, 4, 5, 6]), + (1720626261.332132, [], [1, 2, 3, 4, 5, 6]), + (1720626263.446226, [], [1, 2, 3, 4, 5, 6]), + (1720626267.27108, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719972691.157799, [], [1, 2, 3, 4, 5, 6]), + (1719972822.458675, [], [1, 2, 3, 4, 5, 6]), + (1719972824.589752, [], [1, 2, 3, 4, 5, 6]), + (1719993329.829737, [], [1, 2, 3, 4, 5, 6]), + (1720053155.834123, [], [1, 2, 3, 4, 5, 6]), + (1720053293.330528, [], [1, 2, 3, 4, 5, 6]), + (1720084358.281667, [], [1, 2, 3, 4, 5, 6]), + (1720084522.554824, [], [1, 2, 3, 4, 5, 6]), + (1720084524.658959, [], [1, 2, 3, 4, 5, 6]), + (1720153146.842639, [], [1, 2, 3, 4, 5, 6]), + (1720153159.620793, [], [1, 2, 3, 4, 5, 6]), + (1720223041.359927, [], [1, 2, 3, 4, 5, 6]), + (1720223107.178767, [], [1, 2, 3, 4, 5, 6]), + (1720223109.301943, [], [1, 2, 3, 4, 5, 6]), + (1720243608.145196, [], [1, 2, 3, 4, 5, 6]), + (1720243715.813915, [], [1, 2, 3, 4, 5, 6]), + (1720310055.295457, [], [1, 2, 3, 4, 5, 6]), + (1720310225.190394, [], [1, 2, 3, 4, 5, 6]), + (1720310227.250668, [], [1, 2, 3, 4, 5, 6]), + (1720374255.295948, [], [1, 2, 3, 4, 5, 6]), + (1720374257.390432, [], [1, 2, 3, 4, 5, 6]), + (1720397033.790744, [], [1, 2, 3, 4, 5, 6]), + (1720397192.93351, [], [1, 2, 3, 4, 5, 6]), + (1720489562.012912, [], [1, 2, 3, 4, 5, 6]), + (1720489620.124167, [], [1, 2, 3, 4, 5, 6]), + (1720489622.2461, [], [1, 2, 3, 4, 5, 6]), + (1720577615.944083, [], [1, 2, 3, 4, 5, 6]), + (1720595908.263871, [], [1, 2, 3, 4, 5, 6]), + (1720596022.795818, [], [1, 2, 3, 4, 5, 6]), + (1720596024.909409, [], [1, 2, 3, 4, 5, 6]), + (1720596025.112291, [], [1, 2, 3, 4, 5, 6]), + (1720596027.181848, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720410184.878056, [], [1, 2, 3, 4, 5, 6])], + [(1720446097.457008, [], [1, 2, 3, 4, 5, 6]), (1720582142.651169, [], [1, 2, 3, 4, 5, 6])], + [(1720496385.651227, [], [1, 2, 3, 4, 5, 6]), (1720588018.159792, [], [1, 2, 3, 4, 5, 6])], + [(1719975737.968693, [], [1, 2, 3, 4, 5, 6]), (1720069758.403541, [], [1, 2, 3, 4, 5, 6])], + [(1720573220.196789, [], [1, 2, 3, 4, 5, 6])], + [(1720435170.4772, [], [1, 2, 3, 4, 5, 6])], + [(1720156838.062846, [], [1, 2, 3, 4, 5, 6]), (1720588244.606338, [], [1, 2, 3, 4, 5, 6])], + [(1720072706.921977, [], [1, 2, 3, 4, 5, 6]), (1720588899.722119, [], [1, 2, 3, 4, 5, 6])], + [(1720058343.607628, [], [1, 2, 3, 4, 5, 6])], + [(1720314365.315505, [], [1, 2, 3, 4, 5, 6])], + [(1720502417.751936, [], [1, 2, 3, 4, 5, 6])], + [(1720302708.367359, [], [1, 2, 3, 4, 5, 6]), (1720585704.559633, [], [1, 2, 3, 4, 5, 6])], + [ + (1719984540.656777, [], [1, 2, 3, 4, 5, 6]), + (1720146973.8651, [], [1, 2, 3, 4, 5, 6]), + (1720341798.159409, [], [1, 2, 3, 4, 5, 6]), + (1720482149.273983, [], [1, 2, 3, 4, 5, 6]), + (1720570969.604085, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720311167.154928, [], [1, 2, 3, 4, 5, 6]), (1720404884.472902, [], [1, 2, 3, 4, 5, 6])], + [(1720481370.176729, [], [1, 2, 3, 4, 5, 6])], + [(1720098969.778426, [], [1, 2, 3, 4, 5, 6]), (1720542708.023885, [], [1, 2, 3, 4, 5, 6])], + [ + (1720149583.597081, [], [1, 2, 3, 4, 5, 6]), + (1720314574.406545, [], [1, 2, 3, 4, 5, 6]), + (1720416038.659142, [], [1, 2, 3, 4, 5, 6]), + (1720572347.697131, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720033450.660601, [], [1, 2, 3, 4, 5, 6]), + (1720033450.752555, [], [1, 2, 3, 4, 5, 6]), + (1720033455.770905, [], [1, 2, 3, 4, 5, 6]), + (1720400227.89913, [], [1, 2, 3, 4, 5, 6]), + (1720400250.299243, [], [1, 2, 3, 4, 5, 6]), + (1720400252.394995, [], [1, 2, 3, 4, 5, 6]), + (1720417432.186774, [], [1, 2, 3, 4, 5, 6]), + (1720417504.33498, [], [1, 2, 3, 4, 5, 6]), + (1720417506.39095, [], [1, 2, 3, 4, 5, 6]), + (1720417509.515927, [], [1, 2, 3, 4, 5, 6]), + (1720417511.647347, [], [1, 2, 3, 4, 5, 6]), + (1720417512.311827, [], [1, 2, 3, 4, 5, 6]), + (1720512787.544525, [], [1, 2, 3, 4, 5, 6]), + (1720512787.637452, [], [1, 2, 3, 4, 5, 6]), + (1720512790.509437, [], [1, 2, 3, 4, 5, 6]), + (1720546384.085434, [], [1, 2, 3, 4, 5, 6]), + (1720546402.635026, [], [1, 2, 3, 4, 5, 6]), + (1720546404.721606, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720091612.414745, [], [1, 2, 3, 4, 5, 6]), (1720394180.692823, [], [1, 2, 3, 4, 5, 6])], + [(1720499565.692616, [], [1, 2, 3, 4, 5, 6])], + [ + (1720050050.500015, [], [1, 2, 3, 4, 5, 6]), + (1720050118.092842, [], [1, 2, 3, 4, 5, 6]), + (1720050225.108458, [], [1, 2, 3, 4, 5, 6]), + (1720065727.65261, [], [1, 2, 3, 4, 5, 6]), + (1720065830.735126, [], [1, 2, 3, 4, 5, 6]), + (1720065888.617825, [], [1, 2, 3, 4, 5, 6]), + (1720065986.346168, [], [1, 2, 3, 4, 5, 6]), + (1720066099.675624, [], [1, 2, 3, 4, 5, 6]), + (1720066274.481661, [], [1, 2, 3, 4, 5, 6]), + (1720066349.195281, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720151340.048882, [], [1, 2, 3, 4, 5, 6]), + (1720314849.375028, [], [1, 2, 3, 4, 5, 6]), + (1720413869.9313, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720054419.118301, [], [1, 2, 3, 4, 5, 6]), (1720399142.008777, [], [1, 2, 3, 4, 5, 6])], + [ + (1720070403.925696, [], [1, 2, 3, 4, 5, 6]), + (1720244978.0606, [], [1, 2, 3, 4, 5, 6]), + (1720588083.280232, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720142944.669634, [], [1, 2, 3, 4, 5, 6]), + (1720317829.682224, [], [1, 2, 3, 4, 5, 6]), + (1720402172.873968, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720135813.27587, [], [1, 2, 3, 4, 5, 6]), + (1720344219.879026, [], [1, 2, 3, 4, 5, 6]), + (1720587780.127476, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720307062.497702, [], [1, 2, 3, 4, 5, 6])], + [(1720145491.250495, [], [1, 2, 3, 4, 5, 6]), (1720586242.178403, [], [1, 2, 3, 4, 5, 6])], + [(1720586566.015615, [], [1, 2, 3, 4, 5, 6])], + [(1720409077.369118, [], [1, 2, 3, 4, 5, 6]), (1720569722.833936, [], [1, 2, 3, 4, 5, 6])], + [(1720098442.029928, [], [1, 2, 3, 4, 5, 6]), (1720391796.053942, [], [1, 2, 3, 4, 5, 6])], + [(1720243240.863801, [], [1, 2, 3, 4, 5, 6]), (1720492060.909226, [], [1, 2, 3, 4, 5, 6])], + [ + (1719967064.859664, [], [1, 2, 3, 4, 5, 6]), + (1720055971.205432, [], [1, 2, 3, 4, 5, 6]), + (1720056017.075129, [], [1, 2, 3, 4, 5, 6]), + (1720069354.406111, [], [1, 2, 3, 4, 5, 6]), + (1720069356.466395, [], [1, 2, 3, 4, 5, 6]), + (1720153990.829373, [], [1, 2, 3, 4, 5, 6]), + (1720154034.130574, [], [1, 2, 3, 4, 5, 6]), + (1720232518.365492, [], [1, 2, 3, 4, 5, 6]), + (1720232668.084829, [], [1, 2, 3, 4, 5, 6]), + (1720232670.147567, [], [1, 2, 3, 4, 5, 6]), + (1720247796.598987, [], [1, 2, 3, 4, 5, 6]), + (1720310742.132713, [], [1, 2, 3, 4, 5, 6]), + (1720310784.012123, [], [1, 2, 3, 4, 5, 6]), + (1720320091.334971, [], [1, 2, 3, 4, 5, 6]), + (1720357505.367765, [], [1, 2, 3, 4, 5, 6]), + (1720357507.406388, [], [1, 2, 3, 4, 5, 6]), + (1720404625.988586, [], [1, 2, 3, 4, 5, 6]), + (1720404726.50447, [], [1, 2, 3, 4, 5, 6]), + (1720404728.609789, [], [1, 2, 3, 4, 5, 6]), + (1720417440.696768, [], [1, 2, 3, 4, 5, 6]), + (1720460381.831877, [], [1, 2, 3, 4, 5, 6]), + (1720460489.831088, [], [1, 2, 3, 4, 5, 6]), + (1720492881.459734, [], [1, 2, 3, 4, 5, 6]), + (1720492883.570789, [], [1, 2, 3, 4, 5, 6]), + (1720580680.591028, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719975556.382414, [], [1, 2, 3, 4, 5, 6]), (1720231475.932226, [], [1, 2, 3, 4, 5, 6])], + [(1720569569.754826, [], [1, 2, 3, 4, 5, 6])], + [(1720043952.413223, [], [1, 2, 3, 4, 5, 6]), (1720225500.222696, [], [1, 2, 3, 4, 5, 6])], + [ + (1719967819.052883, [], [1, 2, 3, 4, 5, 6]), + (1720234292.697748, [], [1, 2, 3, 4, 5, 6]), + (1720397113.348799, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720087477.672876, [], [1, 2, 3, 4, 5, 6]), (1720438489.760021, [], [1, 2, 3, 4, 5, 6])], + [(1720577383.739689, [], [1, 2, 3, 4, 5, 6])], + [ + (1720047896.111507, [], [1, 2, 3, 4, 5, 6]), + (1720200244.93862, [], [1, 2, 3, 4, 5, 6]), + (1720464543.942733, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719970307.394382, [], [1, 2, 3, 4, 5, 6])], + [(1719982131.954439, [], [1, 2, 3, 4, 5, 6]), (1720238111.874625, [], [1, 2, 3, 4, 5, 6])], + [(1719966189.201726, [], [1, 2, 3, 4, 5, 6]), (1720150700.452652, [], [1, 2, 3, 4, 5, 6])], + [(1720142072.057736, [], [1, 2, 3, 4, 5, 6])], + [(1720063956.632264, [], [1, 2, 3, 4, 5, 6])], + [(1720057020.243682, [], [1, 2, 3, 4, 5, 6])], + [ + (1719973656.343743, [], [1, 2, 3, 4, 5, 6]), + (1719973767.615562, [], [1, 2, 3, 4, 5, 6]), + (1719973769.702368, [], [1, 2, 3, 4, 5, 6]), + (1720050422.073716, [], [1, 2, 3, 4, 5, 6]), + (1720060932.515015, [], [1, 2, 3, 4, 5, 6]), + (1720061076.268193, [], [1, 2, 3, 4, 5, 6]), + (1720061078.375626, [], [1, 2, 3, 4, 5, 6]), + (1720061082.695369, [], [1, 2, 3, 4, 5, 6]), + (1720061084.803345, [], [1, 2, 3, 4, 5, 6]), + (1720061088.695247, [], [1, 2, 3, 4, 5, 6]), + (1720061090.795592, [], [1, 2, 3, 4, 5, 6]), + (1720135057.814031, [], [1, 2, 3, 4, 5, 6]), + (1720135295.655111, [], [1, 2, 3, 4, 5, 6]), + (1720135297.734383, [], [1, 2, 3, 4, 5, 6]), + (1720156608.706907, [], [1, 2, 3, 4, 5, 6]), + (1720156610.771323, [], [1, 2, 3, 4, 5, 6]), + (1720208160.885537, [], [1, 2, 3, 4, 5, 6]), + (1720208274.821579, [], [1, 2, 3, 4, 5, 6]), + (1720208276.929569, [], [1, 2, 3, 4, 5, 6]), + (1720223270.224257, [], [1, 2, 3, 4, 5, 6]), + (1720223272.316827, [], [1, 2, 3, 4, 5, 6]), + (1720223275.15326, [], [1, 2, 3, 4, 5, 6]), + (1720261350.082829, [], [1, 2, 3, 4, 5, 6]), + (1720261423.329391, [], [1, 2, 3, 4, 5, 6]), + (1720261425.427693, [], [1, 2, 3, 4, 5, 6]), + (1720319448.712298, [], [1, 2, 3, 4, 5, 6]), + (1720319512.283877, [], [1, 2, 3, 4, 5, 6]), + (1720319514.384024, [], [1, 2, 3, 4, 5, 6]), + (1720397163.860459, [], [1, 2, 3, 4, 5, 6]), + (1720397201.824506, [], [1, 2, 3, 4, 5, 6]), + (1720397203.898302, [], [1, 2, 3, 4, 5, 6]), + (1720487465.098454, [], [1, 2, 3, 4, 5, 6]), + (1720487616.241062, [], [1, 2, 3, 4, 5, 6]), + (1720576783.799559, [], [1, 2, 3, 4, 5, 6]), + (1720576837.625767, [], [1, 2, 3, 4, 5, 6]), + (1720576839.747181, [], [1, 2, 3, 4, 5, 6]), + (1720621584.709553, [], [1, 2, 3, 4, 5, 6]), + (1720621686.14789, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720210871.32264, [], [1, 2, 3, 4, 5, 6]), (1720324564.785043, [], [1, 2, 3, 4, 5, 6])], + [ + (1719976074.774068, [], [1, 2, 3, 4, 5, 6]), + (1720432422.057214, [], [1, 2, 3, 4, 5, 6]), + (1720498059.505822, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720537307.322626, [], [1, 2, 3, 4, 5, 6])], + [(1720051279.943281, [], [1, 2, 3, 4, 5, 6]), (1720326635.291429, [], [1, 2, 3, 4, 5, 6])], + [ + (1720317156.788498, [], [1, 2, 3, 4, 5, 6]), + (1720409687.362687, [], [1, 2, 3, 4, 5, 6]), + (1720499324.086042, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720058380.956986, [], [1, 2, 3, 4, 5, 6]), (1720150021.258812, [], [1, 2, 3, 4, 5, 6])], + [ + (1720053489.906165, [], [1, 2, 3, 4, 5, 6]), + (1720139673.741326, [], [1, 2, 3, 4, 5, 6]), + (1720257769.454421, [], [1, 2, 3, 4, 5, 6]), + (1720393246.483443, [], [1, 2, 3, 4, 5, 6]), + (1720653126.121555, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719980029.84453, [], [1, 2, 3, 4, 5, 6])], + [(1720579706.660021, [], [1, 2, 3, 4, 5, 6])], + [(1720044200.360238, [], [1, 2, 3, 4, 5, 6])], + [(1720081853.12837, [], [1, 2, 3, 4, 5, 6])], + [(1720052881.805602, [], [1, 2, 3, 4, 5, 6])], + [ + (1720072654.6007, [], [1, 2, 3, 4, 5, 6]), + (1720238922.414211, [], [1, 2, 3, 4, 5, 6]), + (1720410048.118631, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720307869.769519, [], [1, 2, 3, 4, 5, 6])], + [ + (1720016591.216479, [], [1, 2, 3, 4, 5, 6]), + (1720157097.134758, [], [1, 2, 3, 4, 5, 6]), + (1720238731.063819, [], [1, 2, 3, 4, 5, 6]), + (1720575486.387284, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719965711.424761, [], [1, 2, 3, 4, 5, 6]), + (1719965713.531779, [], [1, 2, 3, 4, 5, 6]), + (1720049361.440421, [], [1, 2, 3, 4, 5, 6]), + (1720049363.495467, [], [1, 2, 3, 4, 5, 6]), + (1720070584.34326, [], [1, 2, 3, 4, 5, 6]), + (1720070586.439897, [], [1, 2, 3, 4, 5, 6]), + (1720070588.168108, [], [1, 2, 3, 4, 5, 6]), + (1720154076.359366, [], [1, 2, 3, 4, 5, 6]), + (1720154271.555582, [], [1, 2, 3, 4, 5, 6]), + (1720221139.621509, [], [1, 2, 3, 4, 5, 6]), + (1720221264.378154, [], [1, 2, 3, 4, 5, 6]), + (1720221266.479342, [], [1, 2, 3, 4, 5, 6]), + (1720239415.452192, [], [1, 2, 3, 4, 5, 6]), + (1720239475.014596, [], [1, 2, 3, 4, 5, 6]), + (1720239477.07742, [], [1, 2, 3, 4, 5, 6]), + (1720313035.217622, [], [1, 2, 3, 4, 5, 6]), + (1720313041.373706, [], [1, 2, 3, 4, 5, 6]), + (1720313043.420222, [], [1, 2, 3, 4, 5, 6]), + (1720406631.8599, [], [1, 2, 3, 4, 5, 6]), + (1720406659.023715, [], [1, 2, 3, 4, 5, 6]), + (1720484615.165994, [], [1, 2, 3, 4, 5, 6]), + (1720484638.913162, [], [1, 2, 3, 4, 5, 6]), + (1720497880.450011, [], [1, 2, 3, 4, 5, 6]), + (1720497934.842426, [], [1, 2, 3, 4, 5, 6]), + (1720497936.912581, [], [1, 2, 3, 4, 5, 6]), + (1720540604.563371, [], [1, 2, 3, 4, 5, 6]), + (1720540779.42356, [], [1, 2, 3, 4, 5, 6]), + (1720540781.553641, [], [1, 2, 3, 4, 5, 6]), + (1720570083.468668, [], [1, 2, 3, 4, 5, 6]), + (1720570174.103962, [], [1, 2, 3, 4, 5, 6]), + (1720570176.16906, [], [1, 2, 3, 4, 5, 6]), + (1720583667.401678, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719984388.470208, [], [1, 2, 3, 4, 5, 6]), + (1720057777.644161, [], [1, 2, 3, 4, 5, 6]), + (1720057953.012529, [], [1, 2, 3, 4, 5, 6]), + (1720057955.119335, [], [1, 2, 3, 4, 5, 6]), + (1720148795.685708, [], [1, 2, 3, 4, 5, 6]), + (1720148805.802813, [], [1, 2, 3, 4, 5, 6]), + (1720148807.834184, [], [1, 2, 3, 4, 5, 6]), + (1720234649.035149, [], [1, 2, 3, 4, 5, 6]), + (1720234705.911474, [], [1, 2, 3, 4, 5, 6]), + (1720321956.32096, [], [1, 2, 3, 4, 5, 6]), + (1720321958.41442, [], [1, 2, 3, 4, 5, 6]), + (1720409662.220157, [], [1, 2, 3, 4, 5, 6]), + (1720409664.333692, [], [1, 2, 3, 4, 5, 6]), + (1720447795.315077, [], [1, 2, 3, 4, 5, 6]), + (1720447797.391813, [], [1, 2, 3, 4, 5, 6]), + (1720483016.135213, [], [1, 2, 3, 4, 5, 6]), + (1720483018.21033, [], [1, 2, 3, 4, 5, 6]), + (1720483019.948558, [], [1, 2, 3, 4, 5, 6]), + (1720573042.040836, [], [1, 2, 3, 4, 5, 6]), + (1720573166.473551, [], [1, 2, 3, 4, 5, 6]), + (1720624631.359534, [], [1, 2, 3, 4, 5, 6]), + (1720624673.478312, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720072684.014623, [], [1, 2, 3, 4, 5, 6]), + (1720308176.896274, [], [1, 2, 3, 4, 5, 6]), + (1720404626.250723, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719970599.437881, [], [1, 2, 3, 4, 5, 6]), + (1720066959.831691, [], [1, 2, 3, 4, 5, 6]), + (1720067155.392921, [], [1, 2, 3, 4, 5, 6]), + (1720067157.488109, [], [1, 2, 3, 4, 5, 6]), + (1720155932.952678, [], [1, 2, 3, 4, 5, 6]), + (1720156052.447154, [], [1, 2, 3, 4, 5, 6]), + (1720156054.565087, [], [1, 2, 3, 4, 5, 6]), + (1720176991.157569, [], [1, 2, 3, 4, 5, 6]), + (1720177007.156433, [], [1, 2, 3, 4, 5, 6]), + (1720197632.204363, [], [1, 2, 3, 4, 5, 6]), + (1720197634.246364, [], [1, 2, 3, 4, 5, 6]), + (1720245139.96838, [], [1, 2, 3, 4, 5, 6]), + (1720245142.060531, [], [1, 2, 3, 4, 5, 6]), + (1720313085.938317, [], [1, 2, 3, 4, 5, 6]), + (1720313087.991269, [], [1, 2, 3, 4, 5, 6]), + (1720382887.239454, [], [1, 2, 3, 4, 5, 6]), + (1720383102.784337, [], [1, 2, 3, 4, 5, 6]), + (1720383104.858248, [], [1, 2, 3, 4, 5, 6]), + (1720401645.882852, [], [1, 2, 3, 4, 5, 6]), + (1720401875.751914, [], [1, 2, 3, 4, 5, 6]), + (1720401877.871081, [], [1, 2, 3, 4, 5, 6]), + (1720401879.349072, [], [1, 2, 3, 4, 5, 6]), + (1720401881.439362, [], [1, 2, 3, 4, 5, 6]), + (1720414595.608826, [], [1, 2, 3, 4, 5, 6]), + (1720414633.289105, [], [1, 2, 3, 4, 5, 6]), + (1720414635.359202, [], [1, 2, 3, 4, 5, 6]), + (1720417003.580682, [], [1, 2, 3, 4, 5, 6]), + (1720417074.130853, [], [1, 2, 3, 4, 5, 6]), + (1720417076.197409, [], [1, 2, 3, 4, 5, 6]), + (1720480715.553431, [], [1, 2, 3, 4, 5, 6]), + (1720480828.705337, [], [1, 2, 3, 4, 5, 6]), + (1720480830.783164, [], [1, 2, 3, 4, 5, 6]), + (1720579482.271054, [], [1, 2, 3, 4, 5, 6]), + (1720579503.249382, [], [1, 2, 3, 4, 5, 6]), + (1720579505.309044, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720320578.9281, [], [1, 2, 3, 4, 5, 6]), + (1720320637.501704, [], [1, 2, 3, 4, 5, 6]), + (1720320671.3461, [], [1, 2, 3, 4, 5, 6]), + (1720320700.900689, [], [1, 2, 3, 4, 5, 6]), + (1720326925.640353, [], [1, 2, 3, 4, 5, 6]), + (1720326927.740401, [], [1, 2, 3, 4, 5, 6]), + (1720397880.433215, [], [1, 2, 3, 4, 5, 6]), + (1720397991.949085, [], [1, 2, 3, 4, 5, 6]), + (1720407395.883774, [], [1, 2, 3, 4, 5, 6]), + (1720478571.564518, [], [1, 2, 3, 4, 5, 6]), + (1720478573.689929, [], [1, 2, 3, 4, 5, 6]), + (1720496055.710657, [], [1, 2, 3, 4, 5, 6]), + (1720496250.423433, [], [1, 2, 3, 4, 5, 6]), + (1720496252.533919, [], [1, 2, 3, 4, 5, 6]), + (1720567595.861171, [], [1, 2, 3, 4, 5, 6]), + (1720567634.8402, [], [1, 2, 3, 4, 5, 6]), + (1720567636.90682, [], [1, 2, 3, 4, 5, 6]), + (1720652785.237133, [], [1, 2, 3, 4, 5, 6]), + (1720652836.758383, [], [1, 2, 3, 4, 5, 6]), + (1720652838.851539, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720076323.446198, [], [1, 2, 3, 4, 5, 6]), + (1720076387.202961, [], [1, 2, 3, 4, 5, 6]), + (1720076463.503404, [], [1, 2, 3, 4, 5, 6]), + (1720235511.111341, [], [1, 2, 3, 4, 5, 6]), + (1720235587.152102, [], [1, 2, 3, 4, 5, 6]), + (1720235604.104726, [], [1, 2, 3, 4, 5, 6]), + (1720235788.441489, [], [1, 2, 3, 4, 5, 6]), + (1720235897.829327, [], [1, 2, 3, 4, 5, 6]), + (1720235943.361057, [], [1, 2, 3, 4, 5, 6]), + (1720236088.122922, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719969865.146509, [], [1, 2, 3, 4, 5, 6])], + [ + (1720088372.900286, [], [1, 2, 3, 4, 5, 6]), + (1720220494.799398, [], [1, 2, 3, 4, 5, 6]), + (1720488909.409034, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720063420.61895, [], [1, 2, 3, 4, 5, 6]), + (1720320803.577679, [], [1, 2, 3, 4, 5, 6]), + (1720401999.385093, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720051291.94966, [], [1, 2, 3, 4, 5, 6]), (1720313692.587964, [], [1, 2, 3, 4, 5, 6])], + [(1720509709.170957, [], [1, 2, 3, 4, 5, 6]), (1720652928.475583, [], [1, 2, 3, 4, 5, 6])], + [(1719976500.586248, [], [1, 2, 3, 4, 5, 6])], + [(1720063184.061031, [], [1, 2, 3, 4, 5, 6])], + [(1720147998.634564, [], [1, 2, 3, 4, 5, 6]), (1720575037.093899, [], [1, 2, 3, 4, 5, 6])], + [(1720594897.858543, [], [1, 2, 3, 4, 5, 6])], + [ + (1720238660.290085, [], [1, 2, 3, 4, 5, 6]), + (1720306835.46462, [], [1, 2, 3, 4, 5, 6]), + (1720401110.356341, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719970976.422012, [], [1, 2, 3, 4, 5, 6]), + (1720051629.137902, [], [1, 2, 3, 4, 5, 6]), + (1720301759.327348, [], [1, 2, 3, 4, 5, 6]), + (1720646663.705407, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720077214.628033, [], [1, 2, 3, 4, 5, 6]), (1720579842.451312, [], [1, 2, 3, 4, 5, 6])], + [(1720403179.578891, [], [1, 2, 3, 4, 5, 6]), (1720573175.772465, [], [1, 2, 3, 4, 5, 6])], + [ + (1720418161.36421, [], [1, 2, 3, 4, 5, 6]), + (1720418260.71249, [], [1, 2, 3, 4, 5, 6]), + (1720418315.726571, [], [1, 2, 3, 4, 5, 6]), + (1720418380.031953, [], [1, 2, 3, 4, 5, 6]), + (1720491482.634884, [], [1, 2, 3, 4, 5, 6]), + (1720491528.332034, [], [1, 2, 3, 4, 5, 6]), + (1720491530.434212, [], [1, 2, 3, 4, 5, 6]), + (1720573999.084897, [], [1, 2, 3, 4, 5, 6]), + (1720574047.543743, [], [1, 2, 3, 4, 5, 6]), + (1720574049.630747, [], [1, 2, 3, 4, 5, 6]), + (1720616534.181229, [], [1, 2, 3, 4, 5, 6]), + (1720616536.227681, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719971505.975792, [], [1, 2, 3, 4, 5, 6]), + (1720309386.016213, [], [1, 2, 3, 4, 5, 6]), + (1720570539.167487, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720026981.201845, [], [1, 2, 3, 4, 5, 6]), + (1720063393.228975, [], [1, 2, 3, 4, 5, 6]), + (1720569870.489752, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720151334.562097, [], [1, 2, 3, 4, 5, 6]), + (1720311454.894847, [], [1, 2, 3, 4, 5, 6]), + (1720483363.072169, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720051176.858561, [], [1, 2, 3, 4, 5, 6]), (1720567049.0934, [], [1, 2, 3, 4, 5, 6])], + [ + (1720300278.98565, [], [1, 2, 3, 4, 5, 6]), + (1720397622.151994, [], [1, 2, 3, 4, 5, 6]), + (1720487075.583534, [], [1, 2, 3, 4, 5, 6]), + (1720572927.092976, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720588311.663694, [], [1, 2, 3, 4, 5, 6])], + [(1720323338.447054, [], [1, 2, 3, 4, 5, 6])], + [(1720499740.21156, [], [1, 2, 3, 4, 5, 6])], + [(1720239215.924016, [], [1, 2, 3, 4, 5, 6]), (1720407168.197067, [], [1, 2, 3, 4, 5, 6])], + [(1720496803.3956, [], [1, 2, 3, 4, 5, 6])], + [(1720578053.220463, [], [1, 2, 3, 4, 5, 6])], + [(1720400566.962842, [], [1, 2, 3, 4, 5, 6]), (1720652817.676145, [], [1, 2, 3, 4, 5, 6])], + [ + (1720234566.739671, [], [1, 2, 3, 4, 5, 6]), + (1720335553.524142, [], [1, 2, 3, 4, 5, 6]), + (1720576366.993741, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720058095.694475, [], [1, 2, 3, 4, 5, 6])], + [(1720499846.305083, [], [1, 2, 3, 4, 5, 6])], + [(1720069736.856188, [], [1, 2, 3, 4, 5, 6]), (1720327054.018462, [], [1, 2, 3, 4, 5, 6])], + [(1720446989.50202, [], [1, 2, 3, 4, 5, 6]), (1720579246.321269, [], [1, 2, 3, 4, 5, 6])], + [ + (1720065515.046196, [], [1, 2, 3, 4, 5, 6]), + (1720237193.252454, [], [1, 2, 3, 4, 5, 6]), + (1720402549.014306, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719965737.195869, [], [1, 2, 3, 4, 5, 6]), + (1720057334.427369, [], [1, 2, 3, 4, 5, 6]), + (1720221205.840325, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720366343.985963, [], [1, 2, 3, 4, 5, 6])], + [(1720195598.557753, [], [1, 2, 3, 4, 5, 6])], + [(1719980678.939359, [], [1, 2, 3, 4, 5, 6]), (1720144995.169791, [], [1, 2, 3, 4, 5, 6])], + [(1720583721.214132, [], [1, 2, 3, 4, 5, 6])], + [ + (1720054537.756175, [], [1, 2, 3, 4, 5, 6]), + (1720182546.976397, [], [1, 2, 3, 4, 5, 6]), + (1720415420.418491, [], [1, 2, 3, 4, 5, 6]), + (1720491014.558376, [], [1, 2, 3, 4, 5, 6]), + (1720568712.840731, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720061881.320656, [], [1, 2, 3, 4, 5, 6]), + (1720352102.705661, [], [1, 2, 3, 4, 5, 6]), + (1720405007.368123, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720578542.112522, [], [1, 2, 3, 4, 5, 6]), (1720652582.644175, [], [1, 2, 3, 4, 5, 6])], + [(1720243826.422296, [], [1, 2, 3, 4, 5, 6])], + [ + (1719980177.888359, [], [1, 2, 3, 4, 5, 6]), + (1720151191.015847, [], [1, 2, 3, 4, 5, 6]), + (1720578744.147878, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720401711.559261, [], [1, 2, 3, 4, 5, 6])], + [ + (1720166076.219132, [], [1, 2, 3, 4, 5, 6]), + (1720603429.438791, [], [1, 2, 3, 4, 5, 6]), + (1720653029.910009, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720060428.267185, [], [1, 2, 3, 4, 5, 6]), (1720330543.204866, [], [1, 2, 3, 4, 5, 6])], + [(1720023596.681592, [], [1, 2, 3, 4, 5, 6]), (1720492712.578171, [], [1, 2, 3, 4, 5, 6])], + [ + (1719969468.250895, [], [1, 2, 3, 4, 5, 6]), + (1719969673.12603, [], [1, 2, 3, 4, 5, 6]), + (1719984075.563213, [], [1, 2, 3, 4, 5, 6]), + (1719984158.542506, [], [1, 2, 3, 4, 5, 6]), + (1719984160.639094, [], [1, 2, 3, 4, 5, 6]), + (1719984161.840978, [], [1, 2, 3, 4, 5, 6]), + (1720063496.706949, [], [1, 2, 3, 4, 5, 6]), + (1720063498.73801, [], [1, 2, 3, 4, 5, 6]), + (1720071811.706281, [], [1, 2, 3, 4, 5, 6]), + (1720071892.339384, [], [1, 2, 3, 4, 5, 6]), + (1720071894.401443, [], [1, 2, 3, 4, 5, 6]), + (1720141092.670014, [], [1, 2, 3, 4, 5, 6]), + (1720141281.129314, [], [1, 2, 3, 4, 5, 6]), + (1720141283.221705, [], [1, 2, 3, 4, 5, 6]), + (1720242813.561025, [], [1, 2, 3, 4, 5, 6]), + (1720242887.120065, [], [1, 2, 3, 4, 5, 6]), + (1720242889.197122, [], [1, 2, 3, 4, 5, 6]), + (1720314744.527265, [], [1, 2, 3, 4, 5, 6]), + (1720314759.642908, [], [1, 2, 3, 4, 5, 6]), + (1720314761.711826, [], [1, 2, 3, 4, 5, 6]), + (1720371097.307425, [], [1, 2, 3, 4, 5, 6]), + (1720371255.548011, [], [1, 2, 3, 4, 5, 6]), + (1720387058.372995, [], [1, 2, 3, 4, 5, 6]), + (1720387060.502073, [], [1, 2, 3, 4, 5, 6]), + (1720404975.528018, [], [1, 2, 3, 4, 5, 6]), + (1720405017.654969, [], [1, 2, 3, 4, 5, 6]), + (1720405019.759385, [], [1, 2, 3, 4, 5, 6]), + (1720415081.995346, [], [1, 2, 3, 4, 5, 6]), + (1720415260.662438, [], [1, 2, 3, 4, 5, 6]), + (1720415262.742795, [], [1, 2, 3, 4, 5, 6]), + (1720485117.023333, [], [1, 2, 3, 4, 5, 6]), + (1720485119.095263, [], [1, 2, 3, 4, 5, 6]), + (1720499098.798714, [], [1, 2, 3, 4, 5, 6]), + (1720499235.930954, [], [1, 2, 3, 4, 5, 6]), + (1720499238.042676, [], [1, 2, 3, 4, 5, 6]), + (1720569739.038396, [], [1, 2, 3, 4, 5, 6]), + (1720569853.204944, [], [1, 2, 3, 4, 5, 6]), + (1720569855.2363, [], [1, 2, 3, 4, 5, 6]), + (1720602936.713875, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720242969.422529, [], [1, 2, 3, 4, 5, 6])], + [ + (1719964838.834772, [], [1, 2, 3, 4, 5, 6]), + (1720091821.44426, [], [1, 2, 3, 4, 5, 6]), + (1720233192.310563, [], [1, 2, 3, 4, 5, 6]), + (1720328141.79034, [], [1, 2, 3, 4, 5, 6]), + (1720496224.014897, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720152285.903631, [], [1, 2, 3, 4, 5, 6]), + (1720243334.372125, [], [1, 2, 3, 4, 5, 6]), + (1720379463.678962, [], [1, 2, 3, 4, 5, 6]), + (1720542353.379097, [], [1, 2, 3, 4, 5, 6]), + (1720649368.688756, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720226523.433881, [], [1, 2, 3, 4, 5, 6]), + (1720226623.918185, [], [1, 2, 3, 4, 5, 6]), + (1720226651.194519, [], [1, 2, 3, 4, 5, 6]), + (1720226742.683406, [], [1, 2, 3, 4, 5, 6]), + (1720330187.550014, [], [1, 2, 3, 4, 5, 6]), + (1720330210.231169, [], [1, 2, 3, 4, 5, 6]), + (1720410272.539479, [], [1, 2, 3, 4, 5, 6]), + (1720410274.655647, [], [1, 2, 3, 4, 5, 6]), + (1720480303.2625, [], [1, 2, 3, 4, 5, 6]), + (1720480415.671856, [], [1, 2, 3, 4, 5, 6]), + (1720480417.738288, [], [1, 2, 3, 4, 5, 6]), + (1720504693.498524, [], [1, 2, 3, 4, 5, 6]), + (1720504764.21831, [], [1, 2, 3, 4, 5, 6]), + (1720504766.268173, [], [1, 2, 3, 4, 5, 6]), + (1720568377.567722, [], [1, 2, 3, 4, 5, 6]), + (1720568452.706691, [], [1, 2, 3, 4, 5, 6]), + (1720568454.778127, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720150751.139246, [], [1, 2, 3, 4, 5, 6])], + [ + (1720064945.077586, [], [1, 2, 3, 4, 5, 6]), + (1720176851.77124, [], [1, 2, 3, 4, 5, 6]), + (1720413751.53369, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720067667.982332, [], [1, 2, 3, 4, 5, 6]), + (1720498323.491767, [], [1, 2, 3, 4, 5, 6]), + (1720640332.912224, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720586416.962046, [], [1, 2, 3, 4, 5, 6])], + [(1720403065.106609, [], [1, 2, 3, 4, 5, 6]), (1720468529.097883, [], [1, 2, 3, 4, 5, 6])], + [(1719976409.626599, [], [1, 2, 3, 4, 5, 6]), (1720617974.74258, [], [1, 2, 3, 4, 5, 6])], + [(1720155789.338418, [], [1, 2, 3, 4, 5, 6])], + [(1719965523.519862, [], [1, 2, 3, 4, 5, 6])], + [(1720492317.02938, [], [1, 2, 3, 4, 5, 6])], + [ + (1719971602.527103, [], [1, 2, 3, 4, 5, 6]), + (1720069918.036547, [], [1, 2, 3, 4, 5, 6]), + (1720149900.77775, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720143447.493022, [], [1, 2, 3, 4, 5, 6]), (1720292005.708479, [], [1, 2, 3, 4, 5, 6])], + [(1720316731.010367, [], [1, 2, 3, 4, 5, 6])], + [(1720061643.180585, [], [1, 2, 3, 4, 5, 6])], + [ + (1719998587.453659, [], [1, 2, 3, 4, 5, 6]), + (1720141642.077196, [], [1, 2, 3, 4, 5, 6]), + (1720308402.56405, [], [1, 2, 3, 4, 5, 6]), + (1720416584.28358, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720587211.681421, [], [1, 2, 3, 4, 5, 6])], + [(1720155992.271335, [], [1, 2, 3, 4, 5, 6]), (1720572458.818891, [], [1, 2, 3, 4, 5, 6])], + [(1720052898.053761, [], [1, 2, 3, 4, 5, 6])], + [(1720221610.587492, [], [1, 2, 3, 4, 5, 6]), (1720312064.403238, [], [1, 2, 3, 4, 5, 6])], + [ + (1720147178.948005, [], [1, 2, 3, 4, 5, 6]), + (1720315892.264762, [], [1, 2, 3, 4, 5, 6]), + (1720484335.142158, [], [1, 2, 3, 4, 5, 6]), + (1720625426.867126, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720225964.225383, [], [1, 2, 3, 4, 5, 6]), (1720486617.901554, [], [1, 2, 3, 4, 5, 6])], + [(1720064206.744859, [], [1, 2, 3, 4, 5, 6]), (1720148855.512919, [], [1, 2, 3, 4, 5, 6])], + [ + (1719978022.859036, [], [1, 2, 3, 4, 5, 6]), + (1720225065.814898, [], [1, 2, 3, 4, 5, 6]), + (1720379679.901663, [], [1, 2, 3, 4, 5, 6]), + (1720486481.106043, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720072107.565425, [], [1, 2, 3, 4, 5, 6]), (1720244247.598994, [], [1, 2, 3, 4, 5, 6])], + [(1720418305.8177, [], [1, 2, 3, 4, 5, 6])], + [(1719982059.871483, [], [1, 2, 3, 4, 5, 6])], + [(1719978817.113542, [], [1, 2, 3, 4, 5, 6])], + [(1720138229.977179, [], [1, 2, 3, 4, 5, 6])], + [(1720069967.627991, [], [1, 2, 3, 4, 5, 6]), (1720327850.533176, [], [1, 2, 3, 4, 5, 6])], + [(1720047008.96098, [], [1, 2, 3, 4, 5, 6]), (1720399885.70332, [], [1, 2, 3, 4, 5, 6])], + [(1720241326.183043, [], [1, 2, 3, 4, 5, 6])], + [ + (1719974240.573502, [], [1, 2, 3, 4, 5, 6]), + (1719974319.570753, [], [1, 2, 3, 4, 5, 6]), + (1719974321.645618, [], [1, 2, 3, 4, 5, 6]), + (1720023281.111928, [], [1, 2, 3, 4, 5, 6]), + (1720023484.341612, [], [1, 2, 3, 4, 5, 6]), + (1720023486.442918, [], [1, 2, 3, 4, 5, 6]), + (1720056803.840688, [], [1, 2, 3, 4, 5, 6]), + (1720056805.906524, [], [1, 2, 3, 4, 5, 6]), + (1720056810.106719, [], [1, 2, 3, 4, 5, 6]), + (1720056812.20004, [], [1, 2, 3, 4, 5, 6]), + (1720070833.346034, [], [1, 2, 3, 4, 5, 6]), + (1720070835.405627, [], [1, 2, 3, 4, 5, 6]), + (1720070839.751918, [], [1, 2, 3, 4, 5, 6]), + (1720070841.8631, [], [1, 2, 3, 4, 5, 6]), + (1720143274.991396, [], [1, 2, 3, 4, 5, 6]), + (1720143497.358536, [], [1, 2, 3, 4, 5, 6]), + (1720205396.067954, [], [1, 2, 3, 4, 5, 6]), + (1720205567.621928, [], [1, 2, 3, 4, 5, 6]), + (1720235968.291387, [], [1, 2, 3, 4, 5, 6]), + (1720236089.012578, [], [1, 2, 3, 4, 5, 6]), + (1720236091.096483, [], [1, 2, 3, 4, 5, 6]), + (1720299309.484376, [], [1, 2, 3, 4, 5, 6]), + (1720299348.029909, [], [1, 2, 3, 4, 5, 6]), + (1720299350.111093, [], [1, 2, 3, 4, 5, 6]), + (1720320587.866423, [], [1, 2, 3, 4, 5, 6]), + (1720320589.944508, [], [1, 2, 3, 4, 5, 6]), + (1720400218.389368, [], [1, 2, 3, 4, 5, 6]), + (1720400220.487059, [], [1, 2, 3, 4, 5, 6]), + (1720492976.763916, [], [1, 2, 3, 4, 5, 6]), + (1720493019.503907, [], [1, 2, 3, 4, 5, 6]), + (1720493021.579652, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720122662.758187, [], [1, 2, 3, 4, 5, 6])], + [ + (1720005466.226878, [], [1, 2, 3, 4, 5, 6]), + (1720152200.991189, [], [1, 2, 3, 4, 5, 6]), + (1720481835.844194, [], [1, 2, 3, 4, 5, 6]), + (1720580183.828864, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720070662.89957, [], [1, 2, 3, 4, 5, 6])], + [(1720142183.650314, [], [1, 2, 3, 4, 5, 6]), (1720411252.551579, [], [1, 2, 3, 4, 5, 6])], + [(1720072507.675137, [], [1, 2, 3, 4, 5, 6]), (1720238913.204492, [], [1, 2, 3, 4, 5, 6])], + [(1720218011.114445, [], [1, 2, 3, 4, 5, 6])], + [(1720302385.101079, [], [1, 2, 3, 4, 5, 6])], + [(1720570186.762002, [], [1, 2, 3, 4, 5, 6])], + [(1720157661.668233, [], [1, 2, 3, 4, 5, 6])], + [ + (1720002096.475822, [], [1, 2, 3, 4, 5, 6]), + (1720002098.548489, [], [1, 2, 3, 4, 5, 6]), + (1720066947.715378, [], [1, 2, 3, 4, 5, 6]), + (1720066949.844651, [], [1, 2, 3, 4, 5, 6]), + (1720105199.7729, [], [1, 2, 3, 4, 5, 6]), + (1720105370.978068, [], [1, 2, 3, 4, 5, 6]), + (1720105373.072451, [], [1, 2, 3, 4, 5, 6]), + (1720134686.761223, [], [1, 2, 3, 4, 5, 6]), + (1720134688.87969, [], [1, 2, 3, 4, 5, 6]), + (1720154938.58341, [], [1, 2, 3, 4, 5, 6]), + (1720219977.007902, [], [1, 2, 3, 4, 5, 6]), + (1720219979.064108, [], [1, 2, 3, 4, 5, 6]), + (1720250673.20197, [], [1, 2, 3, 4, 5, 6]), + (1720250796.014257, [], [1, 2, 3, 4, 5, 6]), + (1720313894.440119, [], [1, 2, 3, 4, 5, 6]), + (1720313896.495204, [], [1, 2, 3, 4, 5, 6]), + (1720313896.774105, [], [1, 2, 3, 4, 5, 6]), + (1720396853.1643, [], [1, 2, 3, 4, 5, 6]), + (1720396855.257174, [], [1, 2, 3, 4, 5, 6]), + (1720489852.456446, [], [1, 2, 3, 4, 5, 6]), + (1720489986.86769, [], [1, 2, 3, 4, 5, 6]), + (1720569682.852233, [], [1, 2, 3, 4, 5, 6]), + (1720569767.225411, [], [1, 2, 3, 4, 5, 6]), + (1720569769.334261, [], [1, 2, 3, 4, 5, 6]), + (1720581192.763754, [], [1, 2, 3, 4, 5, 6]), + (1720581262.544992, [], [1, 2, 3, 4, 5, 6]), + (1720581264.629216, [], [1, 2, 3, 4, 5, 6]), + (1720581266.203535, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720226441.129883, [], [1, 2, 3, 4, 5, 6]), + (1720226519.948161, [], [1, 2, 3, 4, 5, 6]), + (1720226639.444269, [], [1, 2, 3, 4, 5, 6]), + (1720226731.198095, [], [1, 2, 3, 4, 5, 6]), + (1720226779.385516, [], [1, 2, 3, 4, 5, 6]), + (1720226788.674966, [], [1, 2, 3, 4, 5, 6]), + (1720226923.560385, [], [1, 2, 3, 4, 5, 6]), + (1720487951.436457, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720038002.665527, [], [1, 2, 3, 4, 5, 6]), + (1720488750.698306, [], [1, 2, 3, 4, 5, 6]), + (1720589885.270178, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720580260.501907, [], [1, 2, 3, 4, 5, 6])], + [(1720237662.32438, [], [1, 2, 3, 4, 5, 6]), (1720309542.106408, [], [1, 2, 3, 4, 5, 6])], + [(1720573441.412558, [], [1, 2, 3, 4, 5, 6])], + [(1720598006.382998, [], [1, 2, 3, 4, 5, 6])], + [(1720249262.676111, [], [1, 2, 3, 4, 5, 6])], + [ + (1719968867.096755, [], [1, 2, 3, 4, 5, 6]), + (1720406515.635103, [], [1, 2, 3, 4, 5, 6]), + (1720568473.896114, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720063183.618875, [], [1, 2, 3, 4, 5, 6])], + [(1720313109.473272, [], [1, 2, 3, 4, 5, 6]), (1720418083.174351, [], [1, 2, 3, 4, 5, 6])], + [(1720106024.609, [], [1, 2, 3, 4, 5, 6])], + [(1720058454.321955, [], [1, 2, 3, 4, 5, 6])], + [ + (1720062639.625591, [], [1, 2, 3, 4, 5, 6]), + (1720221670.858026, [], [1, 2, 3, 4, 5, 6]), + (1720496857.495022, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719974856.395033, [], [1, 2, 3, 4, 5, 6]), + (1720053608.017225, [], [1, 2, 3, 4, 5, 6]), + (1720053669.477447, [], [1, 2, 3, 4, 5, 6]), + (1720053671.560518, [], [1, 2, 3, 4, 5, 6]), + (1720062649.578553, [], [1, 2, 3, 4, 5, 6]), + (1720062651.66265, [], [1, 2, 3, 4, 5, 6]), + (1720062653.377042, [], [1, 2, 3, 4, 5, 6]), + (1720062655.44862, [], [1, 2, 3, 4, 5, 6]), + (1720082692.43711, [], [1, 2, 3, 4, 5, 6]), + (1720082771.847834, [], [1, 2, 3, 4, 5, 6]), + (1720153671.808662, [], [1, 2, 3, 4, 5, 6]), + (1720153713.489374, [], [1, 2, 3, 4, 5, 6]), + (1720153715.599402, [], [1, 2, 3, 4, 5, 6]), + (1720153716.387598, [], [1, 2, 3, 4, 5, 6]), + (1720153718.446591, [], [1, 2, 3, 4, 5, 6]), + (1720239246.152588, [], [1, 2, 3, 4, 5, 6]), + (1720239248.241024, [], [1, 2, 3, 4, 5, 6]), + (1720239250.77294, [], [1, 2, 3, 4, 5, 6]), + (1720309956.683905, [], [1, 2, 3, 4, 5, 6]), + (1720310071.602061, [], [1, 2, 3, 4, 5, 6]), + (1720325462.049867, [], [1, 2, 3, 4, 5, 6]), + (1720325503.88631, [], [1, 2, 3, 4, 5, 6]), + (1720325506.004479, [], [1, 2, 3, 4, 5, 6]), + (1720412942.492135, [], [1, 2, 3, 4, 5, 6]), + (1720458829.36376, [], [1, 2, 3, 4, 5, 6]), + (1720458949.800013, [], [1, 2, 3, 4, 5, 6]), + (1720458951.887504, [], [1, 2, 3, 4, 5, 6]), + (1720492407.820081, [], [1, 2, 3, 4, 5, 6]), + (1720492444.404348, [], [1, 2, 3, 4, 5, 6]), + (1720492446.466946, [], [1, 2, 3, 4, 5, 6]), + (1720575932.543872, [], [1, 2, 3, 4, 5, 6]), + (1720576033.410802, [], [1, 2, 3, 4, 5, 6]), + (1720576035.469127, [], [1, 2, 3, 4, 5, 6]), + (1720576036.44253, [], [1, 2, 3, 4, 5, 6]), + (1720647287.059052, [], [1, 2, 3, 4, 5, 6]), + (1720647289.160943, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720330899.088291, [], [1, 2, 3, 4, 5, 6])], + [ + (1720081793.462679, [], [1, 2, 3, 4, 5, 6]), + (1720081976.131384, [], [1, 2, 3, 4, 5, 6]), + (1720081976.187009, [], [1, 2, 3, 4, 5, 6]), + (1720081980.325716, [], [1, 2, 3, 4, 5, 6]), + (1720091170.691618, [], [1, 2, 3, 4, 5, 6]), + (1720091356.840132, [], [1, 2, 3, 4, 5, 6]), + (1720091358.928927, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720238399.047753, [], [1, 2, 3, 4, 5, 6]), (1720567368.683366, [], [1, 2, 3, 4, 5, 6])], + [(1720583646.429286, [], [1, 2, 3, 4, 5, 6])], + [(1720330049.16818, [], [1, 2, 3, 4, 5, 6])], + [(1720578076.222297, [], [1, 2, 3, 4, 5, 6])], + [(1719972331.112716, [], [1, 2, 3, 4, 5, 6]), (1720051745.533132, [], [1, 2, 3, 4, 5, 6])], + [(1720146463.601388, [], [1, 2, 3, 4, 5, 6]), (1720474541.840768, [], [1, 2, 3, 4, 5, 6])], + [ + (1720051898.891617, [], [1, 2, 3, 4, 5, 6]), + (1720173013.609275, [], [1, 2, 3, 4, 5, 6]), + (1720320493.657042, [], [1, 2, 3, 4, 5, 6]), + (1720345690.851927, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720408818.140609, [], [1, 2, 3, 4, 5, 6]), (1720486964.900766, [], [1, 2, 3, 4, 5, 6])], + [ + (1720043728.363322, [], [1, 2, 3, 4, 5, 6]), + (1720311975.271982, [], [1, 2, 3, 4, 5, 6]), + (1720571578.431424, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719972681.535491, [], [1, 2, 3, 4, 5, 6]), (1720481018.937328, [], [1, 2, 3, 4, 5, 6])], + [ + (1720026382.553301, [], [1, 2, 3, 4, 5, 6]), + (1720149100.706808, [], [1, 2, 3, 4, 5, 6]), + (1720307942.507634, [], [1, 2, 3, 4, 5, 6]), + (1720570495.6023, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720488173.923373, [], [1, 2, 3, 4, 5, 6]), (1720568447.027354, [], [1, 2, 3, 4, 5, 6])], + [(1720567270.126647, [], [1, 2, 3, 4, 5, 6])], + [(1720499324.726509, [], [1, 2, 3, 4, 5, 6])], + [(1719967975.358552, [], [1, 2, 3, 4, 5, 6]), (1720326137.056104, [], [1, 2, 3, 4, 5, 6])], + [(1720328587.433829, [], [1, 2, 3, 4, 5, 6])], + [ + (1720055336.001624, [], [1, 2, 3, 4, 5, 6]), + (1720138863.165013, [], [1, 2, 3, 4, 5, 6]), + (1720395924.519387, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720069032.516709, [], [1, 2, 3, 4, 5, 6])], + [(1720055010.518163, [], [1, 2, 3, 4, 5, 6]), (1720099339.150894, [], [1, 2, 3, 4, 5, 6])], + [(1720585549.317132, [], [1, 2, 3, 4, 5, 6])], + [ + (1720409221.504822, [], [1, 2, 3, 4, 5, 6]), + (1720519728.003909, [], [1, 2, 3, 4, 5, 6]), + (1720567616.396835, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720244626.143033, [], [1, 2, 3, 4, 5, 6]), + (1720408635.777109, [], [1, 2, 3, 4, 5, 6]), + (1720575490.310245, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720650559.825556, [], [1, 2, 3, 4, 5, 6])], + [(1720582328.399682, [], [1, 2, 3, 4, 5, 6])], + [(1720394085.218172, [], [1, 2, 3, 4, 5, 6])], + [ + (1720066065.444143, [], [1, 2, 3, 4, 5, 6]), + (1720191993.66672, [], [1, 2, 3, 4, 5, 6]), + (1720491329.586545, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720071639.073353, [], [1, 2, 3, 4, 5, 6]), + (1720147406.207381, [], [1, 2, 3, 4, 5, 6]), + (1720311129.234658, [], [1, 2, 3, 4, 5, 6]), + (1720573354.037576, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720240131.733437, [], [1, 2, 3, 4, 5, 6])], + [ + (1719984704.452873, [], [1, 2, 3, 4, 5, 6]), + (1720154844.587696, [], [1, 2, 3, 4, 5, 6]), + (1720322613.231449, [], [1, 2, 3, 4, 5, 6]), + (1720569714.825725, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720486946.256934, [], [1, 2, 3, 4, 5, 6]), (1720647691.877446, [], [1, 2, 3, 4, 5, 6])], + [ + (1719993805.960143, [], [1, 2, 3, 4, 5, 6]), + (1720143738.25635, [], [1, 2, 3, 4, 5, 6]), + (1720309437.19401, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720398437.265534, [], [1, 2, 3, 4, 5, 6]), + (1720509793.976335, [], [1, 2, 3, 4, 5, 6]), + (1720629661.586274, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720062670.596985, [], [1, 2, 3, 4, 5, 6]), (1720438472.029491, [], [1, 2, 3, 4, 5, 6])], + [(1720329032.038648, [], [1, 2, 3, 4, 5, 6])], + [(1719984110.370743, [], [1, 2, 3, 4, 5, 6])], + [(1719986035.664892, [], [1, 2, 3, 4, 5, 6]), (1720241225.374801, [], [1, 2, 3, 4, 5, 6])], + [ + (1720105075.810739, [], [1, 2, 3, 4, 5, 6]), + (1720150414.362845, [], [1, 2, 3, 4, 5, 6]), + (1720308174.216706, [], [1, 2, 3, 4, 5, 6]), + (1720412581.759663, [], [1, 2, 3, 4, 5, 6]), + (1720567554.209717, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720537016.009206, [], [1, 2, 3, 4, 5, 6]), (1720589963.468469, [], [1, 2, 3, 4, 5, 6])], + [(1720487391.820061, [], [1, 2, 3, 4, 5, 6])], + [ + (1719975756.8334, [], [1, 2, 3, 4, 5, 6]), + (1720155078.652264, [], [1, 2, 3, 4, 5, 6]), + (1720400698.199527, [], [1, 2, 3, 4, 5, 6]), + (1720496832.791723, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720018681.490249, [], [1, 2, 3, 4, 5, 6]), + (1720136925.765051, [], [1, 2, 3, 4, 5, 6]), + (1720299976.82238, [], [1, 2, 3, 4, 5, 6]), + (1720569027.317754, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720154725.361924, [], [1, 2, 3, 4, 5, 6]), + (1720243905.535885, [], [1, 2, 3, 4, 5, 6]), + (1720315512.512864, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720588095.521256, [], [1, 2, 3, 4, 5, 6])], + [(1719983442.727069, [], [1, 2, 3, 4, 5, 6]), (1720152453.391462, [], [1, 2, 3, 4, 5, 6])], + [(1720405182.158931, [], [1, 2, 3, 4, 5, 6]), (1720575807.583852, [], [1, 2, 3, 4, 5, 6])], + [(1720069878.030512, [], [1, 2, 3, 4, 5, 6]), (1720168504.534482, [], [1, 2, 3, 4, 5, 6])], + [(1720239119.238416, [], [1, 2, 3, 4, 5, 6])], + [(1720576430.211377, [], [1, 2, 3, 4, 5, 6])], + [ + (1719972965.48613, [], [1, 2, 3, 4, 5, 6]), + (1720240976.867243, [], [1, 2, 3, 4, 5, 6]), + (1720404977.394327, [], [1, 2, 3, 4, 5, 6]), + (1720537004.359466, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720487019.528315, [], [1, 2, 3, 4, 5, 6]), (1720581959.239135, [], [1, 2, 3, 4, 5, 6])], + [(1720652926.990055, [], [1, 2, 3, 4, 5, 6])], + [ + (1720052099.960777, [], [1, 2, 3, 4, 5, 6]), + (1720138855.98453, [], [1, 2, 3, 4, 5, 6]), + (1720138921.586511, [], [1, 2, 3, 4, 5, 6]), + (1720139014.744606, [], [1, 2, 3, 4, 5, 6]), + (1720139182.595009, [], [1, 2, 3, 4, 5, 6]), + (1720139192.3206, [], [1, 2, 3, 4, 5, 6]), + (1720581909.908771, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720065955.899244, [], [1, 2, 3, 4, 5, 6]), + (1720236828.579322, [], [1, 2, 3, 4, 5, 6]), + (1720308640.597753, [], [1, 2, 3, 4, 5, 6]), + (1720579634.738256, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719980159.276761, [], [1, 2, 3, 4, 5, 6]), + (1720308552.424302, [], [1, 2, 3, 4, 5, 6]), + (1720653256.063729, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719985271.443965, [], [1, 2, 3, 4, 5, 6]), + (1720220543.115385, [], [1, 2, 3, 4, 5, 6]), + (1720315297.143816, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720330015.747888, [], [1, 2, 3, 4, 5, 6]), (1720481610.656596, [], [1, 2, 3, 4, 5, 6])], + [(1720224041.283015, [], [1, 2, 3, 4, 5, 6]), (1720567371.834809, [], [1, 2, 3, 4, 5, 6])], + [ + (1720244217.827624, [], [1, 2, 3, 4, 5, 6]), + (1720402557.505715, [], [1, 2, 3, 4, 5, 6]), + (1720502124.284452, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720415547.576014, [], [1, 2, 3, 4, 5, 6]), (1720531682.711315, [], [1, 2, 3, 4, 5, 6])], + [(1720407411.272993, [], [1, 2, 3, 4, 5, 6]), (1720574508.629738, [], [1, 2, 3, 4, 5, 6])], + [(1720257290.163002, [], [1, 2, 3, 4, 5, 6]), (1720492975.717018, [], [1, 2, 3, 4, 5, 6])], + [(1720144145.711511, [], [1, 2, 3, 4, 5, 6]), (1720401163.125022, [], [1, 2, 3, 4, 5, 6])], + [(1720355601.346282, [], [1, 2, 3, 4, 5, 6]), (1720572069.286814, [], [1, 2, 3, 4, 5, 6])], + [ + (1719968339.260056, [], [1, 2, 3, 4, 5, 6]), + (1719968341.365428, [], [1, 2, 3, 4, 5, 6]), + (1719968343.993978, [], [1, 2, 3, 4, 5, 6]), + (1719968346.031381, [], [1, 2, 3, 4, 5, 6]), + (1719968349.431552, [], [1, 2, 3, 4, 5, 6]), + (1719968351.559689, [], [1, 2, 3, 4, 5, 6]), + (1719976134.941126, [], [1, 2, 3, 4, 5, 6]), + (1719976278.477066, [], [1, 2, 3, 4, 5, 6]), + (1719976280.56988, [], [1, 2, 3, 4, 5, 6]), + (1720052757.855887, [], [1, 2, 3, 4, 5, 6]), + (1720052759.915085, [], [1, 2, 3, 4, 5, 6]), + (1720110094.313929, [], [1, 2, 3, 4, 5, 6]), + (1720142517.707832, [], [1, 2, 3, 4, 5, 6]), + (1720142570.10559, [], [1, 2, 3, 4, 5, 6]), + (1720142572.151412, [], [1, 2, 3, 4, 5, 6]), + (1720142576.179553, [], [1, 2, 3, 4, 5, 6]), + (1720237055.807105, [], [1, 2, 3, 4, 5, 6]), + (1720237203.321556, [], [1, 2, 3, 4, 5, 6]), + (1720237205.419793, [], [1, 2, 3, 4, 5, 6]), + (1720316912.566247, [], [1, 2, 3, 4, 5, 6]), + (1720317055.804333, [], [1, 2, 3, 4, 5, 6]), + (1720317057.925258, [], [1, 2, 3, 4, 5, 6]), + (1720317058.399149, [], [1, 2, 3, 4, 5, 6]), + (1720317060.481448, [], [1, 2, 3, 4, 5, 6]), + (1720393849.766518, [], [1, 2, 3, 4, 5, 6]), + (1720393921.300236, [], [1, 2, 3, 4, 5, 6]), + (1720406796.853939, [], [1, 2, 3, 4, 5, 6]), + (1720406798.933918, [], [1, 2, 3, 4, 5, 6]), + (1720482599.505433, [], [1, 2, 3, 4, 5, 6]), + (1720482663.255581, [], [1, 2, 3, 4, 5, 6]), + (1720482665.27704, [], [1, 2, 3, 4, 5, 6]), + (1720492023.699542, [], [1, 2, 3, 4, 5, 6]), + (1720492025.737059, [], [1, 2, 3, 4, 5, 6]), + (1720500142.609638, [], [1, 2, 3, 4, 5, 6]), + (1720500250.895423, [], [1, 2, 3, 4, 5, 6]), + (1720525828.241699, [], [1, 2, 3, 4, 5, 6]), + (1720525830.335737, [], [1, 2, 3, 4, 5, 6]), + (1720543473.185403, [], [1, 2, 3, 4, 5, 6]), + (1720543629.193018, [], [1, 2, 3, 4, 5, 6]), + (1720543631.258205, [], [1, 2, 3, 4, 5, 6]), + (1720566115.315069, [], [1, 2, 3, 4, 5, 6]), + (1720566235.252146, [], [1, 2, 3, 4, 5, 6]), + (1720566237.371673, [], [1, 2, 3, 4, 5, 6]), + (1720566239.622085, [], [1, 2, 3, 4, 5, 6]), + (1720566241.74061, [], [1, 2, 3, 4, 5, 6]), + (1720652422.12376, [], [1, 2, 3, 4, 5, 6]), + (1720652589.161105, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720332940.235911, [], [1, 2, 3, 4, 5, 6])], + [(1720065527.859172, [], [1, 2, 3, 4, 5, 6])], + [(1720568368.543876, [], [1, 2, 3, 4, 5, 6]), (1720635472.219669, [], [1, 2, 3, 4, 5, 6])], + [ + (1719968828.538353, [], [1, 2, 3, 4, 5, 6]), + (1720051948.377763, [], [1, 2, 3, 4, 5, 6]), + (1720299205.556357, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720235830.179481, [], [1, 2, 3, 4, 5, 6]), + (1720235953.147018, [], [1, 2, 3, 4, 5, 6]), + (1720236018.20472, [], [1, 2, 3, 4, 5, 6]), + (1720236089.138704, [], [1, 2, 3, 4, 5, 6]), + (1720236119.593712, [], [1, 2, 3, 4, 5, 6]), + (1720236141.83499, [], [1, 2, 3, 4, 5, 6]), + (1720311050.201652, [], [1, 2, 3, 4, 5, 6]), + (1720311052.280309, [], [1, 2, 3, 4, 5, 6]), + (1720395484.534496, [], [1, 2, 3, 4, 5, 6]), + (1720491406.080018, [], [1, 2, 3, 4, 5, 6]), + (1720491430.598198, [], [1, 2, 3, 4, 5, 6]), + (1720491432.661821, [], [1, 2, 3, 4, 5, 6]), + (1720572678.481313, [], [1, 2, 3, 4, 5, 6]), + (1720572808.45491, [], [1, 2, 3, 4, 5, 6]), + (1720572810.563889, [], [1, 2, 3, 4, 5, 6]), + (1720603175.70942, [], [1, 2, 3, 4, 5, 6]), + (1720603202.06502, [], [1, 2, 3, 4, 5, 6]), + (1720603204.156746, [], [1, 2, 3, 4, 5, 6]), + (1720652491.405509, [], [1, 2, 3, 4, 5, 6]), + (1720652598.039059, [], [1, 2, 3, 4, 5, 6]), + (1720652600.082367, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720153161.725292, [], [1, 2, 3, 4, 5, 6])], + [(1720494662.408865, [], [1, 2, 3, 4, 5, 6]), (1720568597.855422, [], [1, 2, 3, 4, 5, 6])], + [(1720416466.753208, [], [1, 2, 3, 4, 5, 6])], + [(1719978991.390168, [], [1, 2, 3, 4, 5, 6])], + [(1720072031.976782, [], [1, 2, 3, 4, 5, 6]), (1720584690.251602, [], [1, 2, 3, 4, 5, 6])], + [(1720575076.950008, [], [1, 2, 3, 4, 5, 6])], + [(1720231712.798613, [], [1, 2, 3, 4, 5, 6]), (1720398045.987903, [], [1, 2, 3, 4, 5, 6])], + [(1720056840.047309, [], [1, 2, 3, 4, 5, 6]), (1720625851.477544, [], [1, 2, 3, 4, 5, 6])], + [ + (1720053429.359158, [], [1, 2, 3, 4, 5, 6]), + (1720053508.29626, [], [1, 2, 3, 4, 5, 6]), + (1720053570.605172, [], [1, 2, 3, 4, 5, 6]), + (1720053639.380777, [], [1, 2, 3, 4, 5, 6]), + (1720066181.00997, [], [1, 2, 3, 4, 5, 6]), + (1720066215.053405, [], [1, 2, 3, 4, 5, 6]), + (1720066217.116517, [], [1, 2, 3, 4, 5, 6]), + (1720143779.66573, [], [1, 2, 3, 4, 5, 6]), + (1720143781.713526, [], [1, 2, 3, 4, 5, 6]), + (1720222105.35254, [], [1, 2, 3, 4, 5, 6]), + (1720317654.056711, [], [1, 2, 3, 4, 5, 6]), + (1720317708.563828, [], [1, 2, 3, 4, 5, 6]), + (1720480329.549535, [], [1, 2, 3, 4, 5, 6]), + (1720480520.417693, [], [1, 2, 3, 4, 5, 6]), + (1720480522.54519, [], [1, 2, 3, 4, 5, 6]), + (1720480523.499363, [], [1, 2, 3, 4, 5, 6]), + (1720577037.242221, [], [1, 2, 3, 4, 5, 6]), + (1720577039.306434, [], [1, 2, 3, 4, 5, 6]), + (1720639329.717862, [], [1, 2, 3, 4, 5, 6]), + (1720639469.331454, [], [1, 2, 3, 4, 5, 6]), + (1720639471.36127, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720024453.629276, [], [1, 2, 3, 4, 5, 6]), (1720316176.77774, [], [1, 2, 3, 4, 5, 6])], + [ + (1720068883.919311, [], [1, 2, 3, 4, 5, 6]), + (1720319773.101818, [], [1, 2, 3, 4, 5, 6]), + (1720586957.747953, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720056927.404781, [], [1, 2, 3, 4, 5, 6])], + [ + (1720054270.638059, [], [1, 2, 3, 4, 5, 6]), + (1720153565.870327, [], [1, 2, 3, 4, 5, 6]), + (1720334693.538652, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720152641.309698, [], [1, 2, 3, 4, 5, 6]), (1720576318.23299, [], [1, 2, 3, 4, 5, 6])], + [ + (1720404934.034946, [], [1, 2, 3, 4, 5, 6]), + (1720476937.980269, [], [1, 2, 3, 4, 5, 6]), + (1720652925.317718, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720583121.659416, [], [1, 2, 3, 4, 5, 6])], + [(1719974918.036807, [], [1, 2, 3, 4, 5, 6])], + [(1720052839.789235, [], [1, 2, 3, 4, 5, 6]), (1720309756.887443, [], [1, 2, 3, 4, 5, 6])], + [(1720214816.601474, [], [1, 2, 3, 4, 5, 6]), (1720628643.350003, [], [1, 2, 3, 4, 5, 6])], + [(1719990813.089809, [], [1, 2, 3, 4, 5, 6]), (1720312746.860016, [], [1, 2, 3, 4, 5, 6])], + [(1720072040.294779, [], [1, 2, 3, 4, 5, 6]), (1720573666.820699, [], [1, 2, 3, 4, 5, 6])], + [(1720221192.01312, [], [1, 2, 3, 4, 5, 6])], + [(1720143165.437476, [], [1, 2, 3, 4, 5, 6])], + [ + (1719965593.95106, [], [1, 2, 3, 4, 5, 6]), + (1720062861.422969, [], [1, 2, 3, 4, 5, 6]), + (1720503564.270709, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720310060.645551, [], [1, 2, 3, 4, 5, 6]), + (1720482309.217878, [], [1, 2, 3, 4, 5, 6]), + (1720591036.349001, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720157768.51272, [], [1, 2, 3, 4, 5, 6])], + [(1720149445.473387, [], [1, 2, 3, 4, 5, 6]), (1720438026.869011, [], [1, 2, 3, 4, 5, 6])], + [ + (1720060489.013219, [], [1, 2, 3, 4, 5, 6]), + (1720415886.629529, [], [1, 2, 3, 4, 5, 6]), + (1720580867.871164, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720414273.276015, [], [1, 2, 3, 4, 5, 6]), (1720487097.033528, [], [1, 2, 3, 4, 5, 6])], + [(1719966569.062726, [], [1, 2, 3, 4, 5, 6])], + [ + (1719966533.368239, [], [1, 2, 3, 4, 5, 6]), + (1720318867.369239, [], [1, 2, 3, 4, 5, 6]), + (1720424434.84027, [], [1, 2, 3, 4, 5, 6]), + (1720566607.607309, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720608001.068576, [], [1, 2, 3, 4, 5, 6])], + [ + (1720062804.379267, [], [1, 2, 3, 4, 5, 6]), + (1720226534.49236, [], [1, 2, 3, 4, 5, 6]), + (1720321084.499585, [], [1, 2, 3, 4, 5, 6]), + (1720450358.303395, [], [1, 2, 3, 4, 5, 6]), + (1720577114.020932, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720138095.209939, [], [1, 2, 3, 4, 5, 6])], + [ + (1720109654.682718, [], [1, 2, 3, 4, 5, 6]), + (1720109832.815741, [], [1, 2, 3, 4, 5, 6]), + (1720109959.88633, [], [1, 2, 3, 4, 5, 6]), + (1720110033.900336, [], [1, 2, 3, 4, 5, 6]), + (1720110090.159457, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719973270.54798, [], [1, 2, 3, 4, 5, 6])], + [(1720404747.93651, [], [1, 2, 3, 4, 5, 6])], + [(1719975896.00888, [], [1, 2, 3, 4, 5, 6]), (1720412877.994145, [], [1, 2, 3, 4, 5, 6])], + [(1720488415.324703, [], [1, 2, 3, 4, 5, 6])], + [ + (1719979329.168652, [], [1, 2, 3, 4, 5, 6]), + (1719979433.834943, [], [1, 2, 3, 4, 5, 6]), + (1719979537.706541, [], [1, 2, 3, 4, 5, 6]), + (1720054525.517489, [], [1, 2, 3, 4, 5, 6]), + (1720054576.808031, [], [1, 2, 3, 4, 5, 6]), + (1720054637.310552, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720008269.86362, [], [1, 2, 3, 4, 5, 6]), (1720228186.690288, [], [1, 2, 3, 4, 5, 6])], + [(1719980906.390651, [], [1, 2, 3, 4, 5, 6])], + [(1720049804.519108, [], [1, 2, 3, 4, 5, 6])], + [(1719982824.989151, [], [1, 2, 3, 4, 5, 6])], + [ + (1720052793.231176, [], [1, 2, 3, 4, 5, 6]), + (1720416383.522419, [], [1, 2, 3, 4, 5, 6]), + (1720576203.462386, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720141956.096351, [], [1, 2, 3, 4, 5, 6]), (1720501761.653384, [], [1, 2, 3, 4, 5, 6])], + [(1719968214.670337, [], [1, 2, 3, 4, 5, 6])], + [ + (1720061582.741936, [], [1, 2, 3, 4, 5, 6]), + (1720148352.805998, [], [1, 2, 3, 4, 5, 6]), + (1720320650.836088, [], [1, 2, 3, 4, 5, 6]), + (1720480540.757287, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720066746.296404, [], [1, 2, 3, 4, 5, 6]), (1720470635.779369, [], [1, 2, 3, 4, 5, 6])], + [(1720036143.99876, [], [1, 2, 3, 4, 5, 6]), (1720235115.25383, [], [1, 2, 3, 4, 5, 6])], + [ + (1720325739.301864, [], [1, 2, 3, 4, 5, 6]), + (1720366758.48691, [], [1, 2, 3, 4, 5, 6]), + (1720579671.285769, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720406674.612278, [], [1, 2, 3, 4, 5, 6])], + [(1720569843.609239, [], [1, 2, 3, 4, 5, 6])], + [ + (1720060843.491976, [], [1, 2, 3, 4, 5, 6]), + (1720147665.305258, [], [1, 2, 3, 4, 5, 6]), + (1720501529.904655, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720046373.265399, [], [1, 2, 3, 4, 5, 6]), + (1720046375.332994, [], [1, 2, 3, 4, 5, 6]), + (1720068144.411279, [], [1, 2, 3, 4, 5, 6]), + (1720068261.195225, [], [1, 2, 3, 4, 5, 6]), + (1720131629.331825, [], [1, 2, 3, 4, 5, 6]), + (1720131717.731289, [], [1, 2, 3, 4, 5, 6]), + (1720143208.108341, [], [1, 2, 3, 4, 5, 6]), + (1720224375.336718, [], [1, 2, 3, 4, 5, 6]), + (1720224489.89131, [], [1, 2, 3, 4, 5, 6]), + (1720239983.991454, [], [1, 2, 3, 4, 5, 6]), + (1720240023.957522, [], [1, 2, 3, 4, 5, 6]), + (1720240026.023994, [], [1, 2, 3, 4, 5, 6]), + (1720288870.449116, [], [1, 2, 3, 4, 5, 6]), + (1720319014.330473, [], [1, 2, 3, 4, 5, 6]), + (1720319153.071162, [], [1, 2, 3, 4, 5, 6]), + (1720319155.11854, [], [1, 2, 3, 4, 5, 6]), + (1720356008.754634, [], [1, 2, 3, 4, 5, 6]), + (1720356170.017209, [], [1, 2, 3, 4, 5, 6]), + (1720414281.753569, [], [1, 2, 3, 4, 5, 6]), + (1720466888.126284, [], [1, 2, 3, 4, 5, 6]), + (1720466890.175399, [], [1, 2, 3, 4, 5, 6]), + (1720496852.884055, [], [1, 2, 3, 4, 5, 6]), + (1720496900.157534, [], [1, 2, 3, 4, 5, 6]), + (1720496902.257177, [], [1, 2, 3, 4, 5, 6]), + (1720517711.484252, [], [1, 2, 3, 4, 5, 6]), + (1720517785.617389, [], [1, 2, 3, 4, 5, 6]), + (1720517787.722386, [], [1, 2, 3, 4, 5, 6]), + (1720574636.301281, [], [1, 2, 3, 4, 5, 6]), + (1720574638.402501, [], [1, 2, 3, 4, 5, 6]), + (1720631962.467861, [], [1, 2, 3, 4, 5, 6]), + (1720632073.350096, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720222983.951049, [], [1, 2, 3, 4, 5, 6]), (1720416117.193584, [], [1, 2, 3, 4, 5, 6])], + [ + (1719971140.695348, [], [1, 2, 3, 4, 5, 6]), + (1720135102.372106, [], [1, 2, 3, 4, 5, 6]), + (1720241528.560118, [], [1, 2, 3, 4, 5, 6]), + (1720494221.442123, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720321074.976216, [], [1, 2, 3, 4, 5, 6]), (1720409891.326419, [], [1, 2, 3, 4, 5, 6])], + [ + (1720048681.074873, [], [1, 2, 3, 4, 5, 6]), + (1720048799.279747, [], [1, 2, 3, 4, 5, 6]), + (1720048801.388645, [], [1, 2, 3, 4, 5, 6]), + (1720078114.283264, [], [1, 2, 3, 4, 5, 6]), + (1720078331.228227, [], [1, 2, 3, 4, 5, 6]), + (1720143813.123392, [], [1, 2, 3, 4, 5, 6]), + (1720143818.771163, [], [1, 2, 3, 4, 5, 6]), + (1720235193.521271, [], [1, 2, 3, 4, 5, 6]), + (1720235195.596896, [], [1, 2, 3, 4, 5, 6]), + (1720325140.395885, [], [1, 2, 3, 4, 5, 6]), + (1720325267.478348, [], [1, 2, 3, 4, 5, 6]), + (1720411316.426439, [], [1, 2, 3, 4, 5, 6]), + (1720411410.991238, [], [1, 2, 3, 4, 5, 6]), + (1720411413.049352, [], [1, 2, 3, 4, 5, 6]), + (1720585972.027756, [], [1, 2, 3, 4, 5, 6]), + (1720586043.355429, [], [1, 2, 3, 4, 5, 6]), + (1720586045.457795, [], [1, 2, 3, 4, 5, 6]), + (1720615162.541609, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719966754.275194, [], [1, 2, 3, 4, 5, 6]), + (1720490216.464205, [], [1, 2, 3, 4, 5, 6]), + (1720553382.681907, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720002644.294528, [], [1, 2, 3, 4, 5, 6]), (1720230090.842106, [], [1, 2, 3, 4, 5, 6])], + [(1720146769.696788, [], [1, 2, 3, 4, 5, 6])], + [ + (1720165756.310512, [], [1, 2, 3, 4, 5, 6]), + (1720410912.566749, [], [1, 2, 3, 4, 5, 6]), + (1720570647.832366, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719976353.576494, [], [1, 2, 3, 4, 5, 6]), + (1720377185.297147, [], [1, 2, 3, 4, 5, 6]), + (1720377289.215042, [], [1, 2, 3, 4, 5, 6]), + (1720377308.468995, [], [1, 2, 3, 4, 5, 6]), + (1720377428.407697, [], [1, 2, 3, 4, 5, 6]), + (1720377485.735576, [], [1, 2, 3, 4, 5, 6]), + (1720377529.508166, [], [1, 2, 3, 4, 5, 6]), + (1720377719.383399, [], [1, 2, 3, 4, 5, 6]), + (1720377809.666048, [], [1, 2, 3, 4, 5, 6]), + (1720377903.918773, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719980213.693083, [], [1, 2, 3, 4, 5, 6]), (1720140384.252931, [], [1, 2, 3, 4, 5, 6])], + [(1720063871.378525, [], [1, 2, 3, 4, 5, 6]), (1720573199.935932, [], [1, 2, 3, 4, 5, 6])], + [(1719985832.719319, [], [1, 2, 3, 4, 5, 6]), (1720406386.34727, [], [1, 2, 3, 4, 5, 6])], + [(1720235695.246766, [], [1, 2, 3, 4, 5, 6]), (1720397629.747797, [], [1, 2, 3, 4, 5, 6])], + [ + (1719968874.938189, [], [1, 2, 3, 4, 5, 6]), + (1719969009.652547, [], [1, 2, 3, 4, 5, 6]), + (1719985700.913806, [], [1, 2, 3, 4, 5, 6]), + (1719985791.512554, [], [1, 2, 3, 4, 5, 6]), + (1720148300.05719, [], [1, 2, 3, 4, 5, 6]), + (1720148304.627225, [], [1, 2, 3, 4, 5, 6]), + (1720148306.685703, [], [1, 2, 3, 4, 5, 6]), + (1720227741.213642, [], [1, 2, 3, 4, 5, 6]), + (1720227808.775173, [], [1, 2, 3, 4, 5, 6]), + (1720295172.811284, [], [1, 2, 3, 4, 5, 6]), + (1720295262.745855, [], [1, 2, 3, 4, 5, 6]), + (1720295264.827116, [], [1, 2, 3, 4, 5, 6]), + (1720295269.130924, [], [1, 2, 3, 4, 5, 6]), + (1720295271.214758, [], [1, 2, 3, 4, 5, 6]), + (1720295276.000757, [], [1, 2, 3, 4, 5, 6]), + (1720295278.050173, [], [1, 2, 3, 4, 5, 6]), + (1720295281.951474, [], [1, 2, 3, 4, 5, 6]), + (1720314791.722567, [], [1, 2, 3, 4, 5, 6]), + (1720314793.809493, [], [1, 2, 3, 4, 5, 6]), + (1720314794.091414, [], [1, 2, 3, 4, 5, 6]), + (1720314796.180282, [], [1, 2, 3, 4, 5, 6]), + (1720334621.693568, [], [1, 2, 3, 4, 5, 6]), + (1720334651.208509, [], [1, 2, 3, 4, 5, 6]), + (1720334653.289286, [], [1, 2, 3, 4, 5, 6]), + (1720405990.429231, [], [1, 2, 3, 4, 5, 6]), + (1720406072.368399, [], [1, 2, 3, 4, 5, 6]), + (1720406074.479232, [], [1, 2, 3, 4, 5, 6]), + (1720502938.778116, [], [1, 2, 3, 4, 5, 6]), + (1720502940.865312, [], [1, 2, 3, 4, 5, 6]), + (1720575136.293441, [], [1, 2, 3, 4, 5, 6]), + (1720575193.500487, [], [1, 2, 3, 4, 5, 6]), + (1720575195.593287, [], [1, 2, 3, 4, 5, 6]), + (1720584066.099625, [], [1, 2, 3, 4, 5, 6]), + (1720584068.181406, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720401234.664166, [], [1, 2, 3, 4, 5, 6])], + [(1720338995.593562, [], [1, 2, 3, 4, 5, 6]), (1720569421.058122, [], [1, 2, 3, 4, 5, 6])], + [ + (1720152780.103003, [], [1, 2, 3, 4, 5, 6]), + (1720318021.21162, [], [1, 2, 3, 4, 5, 6]), + (1720568682.771219, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720153767.474128, [], [1, 2, 3, 4, 5, 6]), + (1720153989.99445, [], [1, 2, 3, 4, 5, 6]), + (1720154117.339532, [], [1, 2, 3, 4, 5, 6]), + (1720154188.47243, [], [1, 2, 3, 4, 5, 6]), + (1720227169.047901, [], [1, 2, 3, 4, 5, 6]), + (1720227171.113334, [], [1, 2, 3, 4, 5, 6]), + (1720290328.719511, [], [1, 2, 3, 4, 5, 6]), + (1720290370.18464, [], [1, 2, 3, 4, 5, 6]), + (1720308949.583306, [], [1, 2, 3, 4, 5, 6]), + (1720309021.205367, [], [1, 2, 3, 4, 5, 6]), + (1720309023.255742, [], [1, 2, 3, 4, 5, 6]), + (1720400031.238045, [], [1, 2, 3, 4, 5, 6]), + (1720400050.534361, [], [1, 2, 3, 4, 5, 6]), + (1720400052.591865, [], [1, 2, 3, 4, 5, 6]), + (1720475517.057002, [], [1, 2, 3, 4, 5, 6]), + (1720475631.221119, [], [1, 2, 3, 4, 5, 6]), + (1720489341.891834, [], [1, 2, 3, 4, 5, 6]), + (1720489520.813888, [], [1, 2, 3, 4, 5, 6]), + (1720522911.41822, [], [1, 2, 3, 4, 5, 6]), + (1720522980.415637, [], [1, 2, 3, 4, 5, 6]), + (1720522982.44762, [], [1, 2, 3, 4, 5, 6]), + (1720590435.585175, [], [1, 2, 3, 4, 5, 6]), + (1720590601.259611, [], [1, 2, 3, 4, 5, 6]), + (1720590603.315457, [], [1, 2, 3, 4, 5, 6]), + (1720590604.638539, [], [1, 2, 3, 4, 5, 6]), + (1720590606.730642, [], [1, 2, 3, 4, 5, 6]), + (1720612053.860624, [], [1, 2, 3, 4, 5, 6]), + (1720612129.921877, [], [1, 2, 3, 4, 5, 6]), + (1720612132.011818, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720426949.173587, [], [1, 2, 3, 4, 5, 6])], + [(1720569102.034496, [], [1, 2, 3, 4, 5, 6])], + [(1720034790.744638, [], [1, 2, 3, 4, 5, 6]), (1720307075.973997, [], [1, 2, 3, 4, 5, 6])], + [ + (1720226287.705985, [], [1, 2, 3, 4, 5, 6]), + (1720397684.607266, [], [1, 2, 3, 4, 5, 6]), + (1720488997.884315, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720228730.18975, [], [1, 2, 3, 4, 5, 6]), + (1720407495.769529, [], [1, 2, 3, 4, 5, 6]), + (1720486995.921451, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720489080.310875, [], [1, 2, 3, 4, 5, 6]), (1720579311.992295, [], [1, 2, 3, 4, 5, 6])], + [(1720138007.433538, [], [1, 2, 3, 4, 5, 6]), (1720243741.609597, [], [1, 2, 3, 4, 5, 6])], + [(1720528666.459324, [], [1, 2, 3, 4, 5, 6])], + [(1719970772.701878, [], [1, 2, 3, 4, 5, 6]), (1720141632.061506, [], [1, 2, 3, 4, 5, 6])], + [(1720068110.038208, [], [1, 2, 3, 4, 5, 6])], + [(1720047191.032235, [], [1, 2, 3, 4, 5, 6])], + [(1719976436.118248, [], [1, 2, 3, 4, 5, 6]), (1720307037.853977, [], [1, 2, 3, 4, 5, 6])], + [(1719972036.639217, [], [1, 2, 3, 4, 5, 6]), (1720057689.829017, [], [1, 2, 3, 4, 5, 6])], + [(1720110461.39165, [], [1, 2, 3, 4, 5, 6]), (1720507249.36072, [], [1, 2, 3, 4, 5, 6])], + [(1719973197.847086, [], [1, 2, 3, 4, 5, 6])], + [ + (1720069338.721539, [], [1, 2, 3, 4, 5, 6]), + (1720524537.017222, [], [1, 2, 3, 4, 5, 6]), + (1720603176.268707, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720142471.621654, [], [1, 2, 3, 4, 5, 6]), (1720221877.173433, [], [1, 2, 3, 4, 5, 6])], + [(1720141771.947396, [], [1, 2, 3, 4, 5, 6])], + [(1720563222.366935, [], [1, 2, 3, 4, 5, 6])], + [(1720237444.558492, [], [1, 2, 3, 4, 5, 6]), (1720586951.821255, [], [1, 2, 3, 4, 5, 6])], + [ + (1720066787.226665, [], [1, 2, 3, 4, 5, 6]), + (1720138501.376918, [], [1, 2, 3, 4, 5, 6]), + (1720332897.490345, [], [1, 2, 3, 4, 5, 6]), + (1720498267.095353, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719979972.999784, [], [1, 2, 3, 4, 5, 6]), (1720326547.318274, [], [1, 2, 3, 4, 5, 6])], + [(1720156142.458551, [], [1, 2, 3, 4, 5, 6]), (1720222674.830191, [], [1, 2, 3, 4, 5, 6])], + [ + (1719976247.399205, [], [1, 2, 3, 4, 5, 6]), + (1719976421.138728, [], [1, 2, 3, 4, 5, 6]), + (1719976457.121053, [], [1, 2, 3, 4, 5, 6]), + (1719976566.522486, [], [1, 2, 3, 4, 5, 6]), + (1720060116.807539, [], [1, 2, 3, 4, 5, 6]), + (1720142201.528128, [], [1, 2, 3, 4, 5, 6]), + (1720142320.790244, [], [1, 2, 3, 4, 5, 6]), + (1720142322.873716, [], [1, 2, 3, 4, 5, 6]), + (1720142323.209429, [], [1, 2, 3, 4, 5, 6]), + (1720142325.32365, [], [1, 2, 3, 4, 5, 6]), + (1720158309.47212, [], [1, 2, 3, 4, 5, 6]), + (1720158464.699924, [], [1, 2, 3, 4, 5, 6]), + (1720158466.803077, [], [1, 2, 3, 4, 5, 6]), + (1720235827.780639, [], [1, 2, 3, 4, 5, 6]), + (1720235829.873017, [], [1, 2, 3, 4, 5, 6]), + (1720235831.516786, [], [1, 2, 3, 4, 5, 6]), + (1720235833.64015, [], [1, 2, 3, 4, 5, 6]), + (1720308111.792929, [], [1, 2, 3, 4, 5, 6]), + (1720308113.917634, [], [1, 2, 3, 4, 5, 6]), + (1720330424.153222, [], [1, 2, 3, 4, 5, 6]), + (1720330426.274619, [], [1, 2, 3, 4, 5, 6]), + (1720397440.529792, [], [1, 2, 3, 4, 5, 6]), + (1720397517.527169, [], [1, 2, 3, 4, 5, 6]), + (1720397519.567891, [], [1, 2, 3, 4, 5, 6]), + (1720489794.692916, [], [1, 2, 3, 4, 5, 6]), + (1720489888.559008, [], [1, 2, 3, 4, 5, 6]), + (1720489890.678539, [], [1, 2, 3, 4, 5, 6]), + (1720577363.385966, [], [1, 2, 3, 4, 5, 6]), + (1720577493.034855, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720042932.668232, [], [1, 2, 3, 4, 5, 6])], + [ + (1720059740.224971, [], [1, 2, 3, 4, 5, 6]), + (1720141837.883794, [], [1, 2, 3, 4, 5, 6]), + (1720405792.751871, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720050443.838424, [], [1, 2, 3, 4, 5, 6]), (1720124719.146549, [], [1, 2, 3, 4, 5, 6])], + [(1719974887.67444, [], [1, 2, 3, 4, 5, 6]), (1720568466.68215, [], [1, 2, 3, 4, 5, 6])], + [(1720065592.314345, [], [1, 2, 3, 4, 5, 6]), (1720205463.888972, [], [1, 2, 3, 4, 5, 6])], + [ + (1720226332.701569, [], [1, 2, 3, 4, 5, 6]), + (1720396620.155135, [], [1, 2, 3, 4, 5, 6]), + (1720492327.218299, [], [1, 2, 3, 4, 5, 6]), + (1720574416.447233, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720045016.618738, [], [1, 2, 3, 4, 5, 6])], + [ + (1720041923.403398, [], [1, 2, 3, 4, 5, 6]), + (1720041925.529856, [], [1, 2, 3, 4, 5, 6]), + (1720041929.344695, [], [1, 2, 3, 4, 5, 6]), + (1720071082.001532, [], [1, 2, 3, 4, 5, 6]), + (1720071201.167727, [], [1, 2, 3, 4, 5, 6]), + (1720071203.259989, [], [1, 2, 3, 4, 5, 6]), + (1720113938.478909, [], [1, 2, 3, 4, 5, 6]), + (1720114019.141219, [], [1, 2, 3, 4, 5, 6]), + (1720147954.114345, [], [1, 2, 3, 4, 5, 6]), + (1720148058.186186, [], [1, 2, 3, 4, 5, 6]), + (1720148060.244565, [], [1, 2, 3, 4, 5, 6]), + (1720230463.28606, [], [1, 2, 3, 4, 5, 6]), + (1720230465.339869, [], [1, 2, 3, 4, 5, 6]), + (1720306384.513301, [], [1, 2, 3, 4, 5, 6]), + (1720306386.603107, [], [1, 2, 3, 4, 5, 6]), + (1720327575.975525, [], [1, 2, 3, 4, 5, 6]), + (1720327821.751969, [], [1, 2, 3, 4, 5, 6]), + (1720327823.781901, [], [1, 2, 3, 4, 5, 6]), + (1720410348.159738, [], [1, 2, 3, 4, 5, 6]), + (1720410448.341114, [], [1, 2, 3, 4, 5, 6]), + (1720457570.237639, [], [1, 2, 3, 4, 5, 6]), + (1720457731.119754, [], [1, 2, 3, 4, 5, 6]), + (1720457733.248545, [], [1, 2, 3, 4, 5, 6]), + (1720499264.385485, [], [1, 2, 3, 4, 5, 6]), + (1720499470.033411, [], [1, 2, 3, 4, 5, 6]), + (1720499472.085357, [], [1, 2, 3, 4, 5, 6]), + (1720543986.94937, [], [1, 2, 3, 4, 5, 6]), + (1720570525.581032, [], [1, 2, 3, 4, 5, 6]), + (1720570749.619565, [], [1, 2, 3, 4, 5, 6]), + (1720585164.854344, [], [1, 2, 3, 4, 5, 6]), + (1720585249.748529, [], [1, 2, 3, 4, 5, 6]), + (1720585251.810485, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720489237.597076, [], [1, 2, 3, 4, 5, 6]), + (1720489298.656835, [], [1, 2, 3, 4, 5, 6]), + (1720489340.853931, [], [1, 2, 3, 4, 5, 6]), + (1720489414.715662, [], [1, 2, 3, 4, 5, 6]), + (1720489578.362748, [], [1, 2, 3, 4, 5, 6]), + (1720489722.080922, [], [1, 2, 3, 4, 5, 6]), + (1720489846.161597, [], [1, 2, 3, 4, 5, 6]), + (1720489902.616032, [], [1, 2, 3, 4, 5, 6]), + (1720489979.179271, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720226541.700259, [], [1, 2, 3, 4, 5, 6]), (1720459357.712795, [], [1, 2, 3, 4, 5, 6])], + [ + (1720137147.179349, [], [1, 2, 3, 4, 5, 6]), + (1720241160.346244, [], [1, 2, 3, 4, 5, 6]), + (1720393844.000636, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720233961.944441, [], [1, 2, 3, 4, 5, 6]), (1720475993.227865, [], [1, 2, 3, 4, 5, 6])], + [(1720339946.523179, [], [1, 2, 3, 4, 5, 6])], + [(1720314335.142585, [], [1, 2, 3, 4, 5, 6])], + [(1720307070.122528, [], [1, 2, 3, 4, 5, 6]), (1720396806.823553, [], [1, 2, 3, 4, 5, 6])], + [(1720134885.254524, [], [1, 2, 3, 4, 5, 6]), (1720582472.172677, [], [1, 2, 3, 4, 5, 6])], + [ + (1720064989.52196, [], [1, 2, 3, 4, 5, 6]), + (1720317471.54011, [], [1, 2, 3, 4, 5, 6]), + (1720405569.646675, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720230240.375249, [], [1, 2, 3, 4, 5, 6])], + [ + (1719981989.67667, [], [1, 2, 3, 4, 5, 6]), + (1719982209.356573, [], [1, 2, 3, 4, 5, 6]), + (1719982211.412871, [], [1, 2, 3, 4, 5, 6]), + (1719990729.511533, [], [1, 2, 3, 4, 5, 6]), + (1719990731.571772, [], [1, 2, 3, 4, 5, 6]), + (1720052018.486278, [], [1, 2, 3, 4, 5, 6]), + (1720052084.895512, [], [1, 2, 3, 4, 5, 6]), + (1720052086.959136, [], [1, 2, 3, 4, 5, 6]), + (1720063752.458627, [], [1, 2, 3, 4, 5, 6]), + (1720063775.402517, [], [1, 2, 3, 4, 5, 6]), + (1720131365.952047, [], [1, 2, 3, 4, 5, 6]), + (1720131512.217778, [], [1, 2, 3, 4, 5, 6]), + (1720131514.344434, [], [1, 2, 3, 4, 5, 6]), + (1720155954.588913, [], [1, 2, 3, 4, 5, 6]), + (1720156049.221823, [], [1, 2, 3, 4, 5, 6]), + (1720326057.45718, [], [1, 2, 3, 4, 5, 6]), + (1720404760.882693, [], [1, 2, 3, 4, 5, 6]), + (1720404806.729924, [], [1, 2, 3, 4, 5, 6]), + (1720404808.834418, [], [1, 2, 3, 4, 5, 6]), + (1720416517.018963, [], [1, 2, 3, 4, 5, 6]), + (1720494367.532053, [], [1, 2, 3, 4, 5, 6]), + (1720500247.551019, [], [1, 2, 3, 4, 5, 6]), + (1720500294.606063, [], [1, 2, 3, 4, 5, 6]), + (1720500296.694825, [], [1, 2, 3, 4, 5, 6]), + (1720500299.259697, [], [1, 2, 3, 4, 5, 6]), + (1720500301.365635, [], [1, 2, 3, 4, 5, 6]), + (1720572338.244531, [], [1, 2, 3, 4, 5, 6]), + (1720572428.794186, [], [1, 2, 3, 4, 5, 6]), + (1720572430.860491, [], [1, 2, 3, 4, 5, 6]), + (1720600877.354363, [], [1, 2, 3, 4, 5, 6]), + (1720601092.109844, [], [1, 2, 3, 4, 5, 6]), + (1720601094.164843, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720230142.987461, [], [1, 2, 3, 4, 5, 6])], + [(1720040834.068992, [], [1, 2, 3, 4, 5, 6])], + [ + (1719984036.646786, [], [1, 2, 3, 4, 5, 6]), + (1720138775.775437, [], [1, 2, 3, 4, 5, 6]), + (1720337436.06649, [], [1, 2, 3, 4, 5, 6]), + (1720567415.54222, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720501680.278938, [], [1, 2, 3, 4, 5, 6]), (1720645969.459141, [], [1, 2, 3, 4, 5, 6])], + [(1719981148.135955, [], [1, 2, 3, 4, 5, 6]), (1720574648.013669, [], [1, 2, 3, 4, 5, 6])], + [ + (1719982323.222591, [], [1, 2, 3, 4, 5, 6]), + (1720101646.380659, [], [1, 2, 3, 4, 5, 6]), + (1720493833.121559, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719977634.84991, [], [1, 2, 3, 4, 5, 6])], + [(1720494761.805988, [], [1, 2, 3, 4, 5, 6]), (1720595943.849674, [], [1, 2, 3, 4, 5, 6])], + [ + (1720155432.624618, [], [1, 2, 3, 4, 5, 6]), + (1720500643.020756, [], [1, 2, 3, 4, 5, 6]), + (1720584683.624928, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720245035.196003, [], [1, 2, 3, 4, 5, 6])], + [(1720313673.855042, [], [1, 2, 3, 4, 5, 6]), (1720381149.495776, [], [1, 2, 3, 4, 5, 6])], + [(1720019520.657419, [], [1, 2, 3, 4, 5, 6])], + [(1719981920.434976, [], [1, 2, 3, 4, 5, 6]), (1720128572.036838, [], [1, 2, 3, 4, 5, 6])], + [(1720136202.220094, [], [1, 2, 3, 4, 5, 6]), (1720279940.922158, [], [1, 2, 3, 4, 5, 6])], + [(1720462395.987553, [], [1, 2, 3, 4, 5, 6])], + [ + (1720653383.244, [], [1, 2, 3, 4, 5, 6]), + (1720653383.325, [], [1, 2, 3, 4, 5, 6]), + (1720653391.627, [], [1, 2, 3, 4, 5, 6]), + (1720653392.102, [], [1, 2, 3, 4, 5, 6]), + (1720653392.298, [], [1, 2, 3, 4, 5, 6]), + (1720653394.934, [], [1, 2, 3, 4, 5, 6]), + (1720653396.411, [], [1, 2, 3, 4, 5, 6]), + (1720653433.093, [], [1, 2, 3, 4, 5, 6]), + (1720653433.236, [], [1, 2, 3, 4, 5, 6]), + (1720653434.991, [], [1, 2, 3, 4, 5, 6]), + (1720653435.037, [], [1, 2, 3, 4, 5, 6]), + (1720653501.654, [], [1, 2, 3, 4, 5, 6]), + (1720653501.71, [], [1, 2, 3, 4, 5, 6]), + (1720653504.799, [], [1, 2, 3, 4, 5, 6]), + (1720653506.446, [], [1, 2, 3, 4, 5, 6]), + (1720653507.872, [], [1, 2, 3, 4, 5, 6]), + (1720654003.023, [], [1, 2, 3, 4, 5, 6]), + (1720654003.148, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719977539.575178, [], [1, 2, 3, 4, 5, 6]), + (1720223726.13705, [], [1, 2, 3, 4, 5, 6]), + (1720396336.894644, [], [1, 2, 3, 4, 5, 6]), + (1720587683.68083, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720327049.710872, [], [1, 2, 3, 4, 5, 6])], + [(1720223003.678086, [], [1, 2, 3, 4, 5, 6]), (1720320656.874702, [], [1, 2, 3, 4, 5, 6])], + [(1720149475.628567, [], [1, 2, 3, 4, 5, 6]), (1720228859.277837, [], [1, 2, 3, 4, 5, 6])], + [(1720049864.230497, [], [1, 2, 3, 4, 5, 6])], + [(1720198432.201466, [], [1, 2, 3, 4, 5, 6])], + [ + (1719975613.439717, [], [1, 2, 3, 4, 5, 6]), + (1719975648.049123, [], [1, 2, 3, 4, 5, 6]), + (1720056914.90013, [], [1, 2, 3, 4, 5, 6]), + (1720057026.542911, [], [1, 2, 3, 4, 5, 6]), + (1720061926.526142, [], [1, 2, 3, 4, 5, 6]), + (1720062007.614611, [], [1, 2, 3, 4, 5, 6]), + (1720147419.43368, [], [1, 2, 3, 4, 5, 6]), + (1720147421.485277, [], [1, 2, 3, 4, 5, 6]), + (1720234139.651394, [], [1, 2, 3, 4, 5, 6]), + (1720234141.758276, [], [1, 2, 3, 4, 5, 6]), + (1720315191.984726, [], [1, 2, 3, 4, 5, 6]), + (1720315194.093018, [], [1, 2, 3, 4, 5, 6]), + (1720315195.836394, [], [1, 2, 3, 4, 5, 6]), + (1720395738.54726, [], [1, 2, 3, 4, 5, 6]), + (1720395740.684533, [], [1, 2, 3, 4, 5, 6]), + (1720410342.218884, [], [1, 2, 3, 4, 5, 6]), + (1720410455.568303, [], [1, 2, 3, 4, 5, 6]), + (1720496479.412713, [], [1, 2, 3, 4, 5, 6]), + (1720496636.329168, [], [1, 2, 3, 4, 5, 6]), + (1720568810.362519, [], [1, 2, 3, 4, 5, 6]), + (1720569040.475975, [], [1, 2, 3, 4, 5, 6]), + (1720652557.884167, [], [1, 2, 3, 4, 5, 6]), + (1720652630.129755, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720233899.203213, [], [1, 2, 3, 4, 5, 6]), + (1720463796.00711, [], [1, 2, 3, 4, 5, 6]), + (1720567454.878169, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720218589.331391, [], [1, 2, 3, 4, 5, 6]), + (1720572246.733219, [], [1, 2, 3, 4, 5, 6]), + (1720585861.133309, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720030179.060188, [], [1, 2, 3, 4, 5, 6]), + (1720330759.17762, [], [1, 2, 3, 4, 5, 6]), + (1720494515.69797, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719979902.797865, [], [1, 2, 3, 4, 5, 6])], + [ + (1720070638.173492, [], [1, 2, 3, 4, 5, 6]), + (1720070819.083453, [], [1, 2, 3, 4, 5, 6]), + (1720070899.802295, [], [1, 2, 3, 4, 5, 6]), + (1720318683.767078, [], [1, 2, 3, 4, 5, 6]), + (1720318886.533145, [], [1, 2, 3, 4, 5, 6]), + (1720318966.57212, [], [1, 2, 3, 4, 5, 6]), + (1720318995.968059, [], [1, 2, 3, 4, 5, 6]), + (1720319139.50433, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720146380.443011, [], [1, 2, 3, 4, 5, 6]), (1720567703.854081, [], [1, 2, 3, 4, 5, 6])], + [(1720485224.936769, [], [1, 2, 3, 4, 5, 6])], + [(1720039180.636756, [], [1, 2, 3, 4, 5, 6]), (1720320703.675688, [], [1, 2, 3, 4, 5, 6])], + [(1720572877.111346, [], [1, 2, 3, 4, 5, 6])], + [(1720149009.624794, [], [1, 2, 3, 4, 5, 6])], + [ + (1720146066.037668, [], [1, 2, 3, 4, 5, 6]), + (1720233446.585623, [], [1, 2, 3, 4, 5, 6]), + (1720397647.223612, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720071535.98588, [], [1, 2, 3, 4, 5, 6]), + (1720222696.675857, [], [1, 2, 3, 4, 5, 6]), + (1720581710.534385, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720320564.297259, [], [1, 2, 3, 4, 5, 6])], + [(1720221596.179609, [], [1, 2, 3, 4, 5, 6]), (1720502714.197196, [], [1, 2, 3, 4, 5, 6])], + [(1720553799.408143, [], [1, 2, 3, 4, 5, 6])], + [ + (1720244362.654861, [], [1, 2, 3, 4, 5, 6]), + (1720412405.21556, [], [1, 2, 3, 4, 5, 6]), + (1720566429.648086, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720225993.003411, [], [1, 2, 3, 4, 5, 6]), (1720576860.143664, [], [1, 2, 3, 4, 5, 6])], + [(1720050680.82043, [], [1, 2, 3, 4, 5, 6])], + [(1719979231.190542, [], [1, 2, 3, 4, 5, 6]), (1720395944.084001, [], [1, 2, 3, 4, 5, 6])], + [(1720483644.896944, [], [1, 2, 3, 4, 5, 6])], + [ + (1720238837.512808, [], [1, 2, 3, 4, 5, 6]), + (1720400917.965225, [], [1, 2, 3, 4, 5, 6]), + (1720499924.896186, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719978670.650293, [], [1, 2, 3, 4, 5, 6]), (1720312908.844749, [], [1, 2, 3, 4, 5, 6])], + [ + (1720064475.615309, [], [1, 2, 3, 4, 5, 6]), + (1720311005.200102, [], [1, 2, 3, 4, 5, 6]), + (1720398033.682041, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1719974842.261587, [], [1, 2, 3, 4, 5, 6]), + (1720070482.809945, [], [1, 2, 3, 4, 5, 6]), + (1720492054.306253, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719985346.86067, [], [1, 2, 3, 4, 5, 6])], + [(1720494586.311794, [], [1, 2, 3, 4, 5, 6])], + [ + (1720151598.2787, [], [1, 2, 3, 4, 5, 6]), + (1720243336.399964, [], [1, 2, 3, 4, 5, 6]), + (1720394460.006175, [], [1, 2, 3, 4, 5, 6]), + (1720584803.786632, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720044414.812182, [], [1, 2, 3, 4, 5, 6]), (1720161374.32603, [], [1, 2, 3, 4, 5, 6])], + [(1720242818.837344, [], [1, 2, 3, 4, 5, 6])], + [(1720407806.948096, [], [1, 2, 3, 4, 5, 6]), (1720511793.967125, [], [1, 2, 3, 4, 5, 6])], + [(1720177465.166679, [], [1, 2, 3, 4, 5, 6])], + [(1720152899.613121, [], [1, 2, 3, 4, 5, 6])], + [(1720144169.768087, [], [1, 2, 3, 4, 5, 6])], + [(1720050900.326256, [], [1, 2, 3, 4, 5, 6]), (1720592651.789908, [], [1, 2, 3, 4, 5, 6])], + [(1720136535.399876, [], [1, 2, 3, 4, 5, 6]), (1720345016.561725, [], [1, 2, 3, 4, 5, 6])], + [(1720148677.039505, [], [1, 2, 3, 4, 5, 6])], + [(1720103982.765975, [], [1, 2, 3, 4, 5, 6]), (1720223275.492349, [], [1, 2, 3, 4, 5, 6])], + [(1719966246.265247, [], [1, 2, 3, 4, 5, 6])], + [(1720048787.249996, [], [1, 2, 3, 4, 5, 6]), (1720588475.186395, [], [1, 2, 3, 4, 5, 6])], + [ + (1720406823.932911, [], [1, 2, 3, 4, 5, 6]), + (1720406854.864424, [], [1, 2, 3, 4, 5, 6]), + (1720406898.943281, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720106989.608336, [], [1, 2, 3, 4, 5, 6])], + [(1719965156.233365, [], [1, 2, 3, 4, 5, 6]), (1720156113.65034, [], [1, 2, 3, 4, 5, 6])], + [(1720237894.767081, [], [1, 2, 3, 4, 5, 6])], + [ + (1720236335.89358, [], [1, 2, 3, 4, 5, 6]), + (1720311377.453215, [], [1, 2, 3, 4, 5, 6]), + (1720406308.416613, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720580297.715893, [], [1, 2, 3, 4, 5, 6])], + [(1719983515.156201, [], [1, 2, 3, 4, 5, 6]), (1720243011.26844, [], [1, 2, 3, 4, 5, 6])], + [(1720412740.206646, [], [1, 2, 3, 4, 5, 6])], + [(1720573676.882026, [], [1, 2, 3, 4, 5, 6])], + [(1720069113.016836, [], [1, 2, 3, 4, 5, 6])], + [(1720065156.88711, [], [1, 2, 3, 4, 5, 6]), (1720342013.62189, [], [1, 2, 3, 4, 5, 6])], + [(1720414414.37316, [], [1, 2, 3, 4, 5, 6]), (1720576057.542994, [], [1, 2, 3, 4, 5, 6])], + [ + (1719965980.977528, [], [1, 2, 3, 4, 5, 6]), + (1720328208.291947, [], [1, 2, 3, 4, 5, 6]), + (1720586256.843288, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719993285.557781, [], [1, 2, 3, 4, 5, 6])], + [ + (1720157474.360894, [], [1, 2, 3, 4, 5, 6]), + (1720317049.692797, [], [1, 2, 3, 4, 5, 6]), + (1720418157.354486, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720492206.117992, [], [1, 2, 3, 4, 5, 6])], + [(1720566094.344648, [], [1, 2, 3, 4, 5, 6])], + [(1719974058.930323, [], [1, 2, 3, 4, 5, 6]), (1720059173.893018, [], [1, 2, 3, 4, 5, 6])], + [(1720517061.661773, [], [1, 2, 3, 4, 5, 6])], + [(1720052300.009912, [], [1, 2, 3, 4, 5, 6]), (1720447926.535749, [], [1, 2, 3, 4, 5, 6])], + [(1720060153.321408, [], [1, 2, 3, 4, 5, 6]), (1720498576.79341, [], [1, 2, 3, 4, 5, 6])], + [(1720415193.154478, [], [1, 2, 3, 4, 5, 6]), (1720494529.74019, [], [1, 2, 3, 4, 5, 6])], + [ + (1719980354.732889, [], [1, 2, 3, 4, 5, 6]), + (1719980356.852338, [], [1, 2, 3, 4, 5, 6]), + (1719980359.805901, [], [1, 2, 3, 4, 5, 6]), + (1719980361.898886, [], [1, 2, 3, 4, 5, 6]), + (1719980364.204398, [], [1, 2, 3, 4, 5, 6]), + (1720063622.210305, [], [1, 2, 3, 4, 5, 6]), + (1720063766.011158, [], [1, 2, 3, 4, 5, 6]), + (1720063768.060823, [], [1, 2, 3, 4, 5, 6]), + (1720134932.57792, [], [1, 2, 3, 4, 5, 6]), + (1720148426.91756, [], [1, 2, 3, 4, 5, 6]), + (1720148428.987966, [], [1, 2, 3, 4, 5, 6]), + (1720237634.85931, [], [1, 2, 3, 4, 5, 6]), + (1720237687.961173, [], [1, 2, 3, 4, 5, 6]), + (1720321596.679301, [], [1, 2, 3, 4, 5, 6]), + (1720394727.592533, [], [1, 2, 3, 4, 5, 6]), + (1720394743.278857, [], [1, 2, 3, 4, 5, 6]), + (1720408408.443408, [], [1, 2, 3, 4, 5, 6]), + (1720419213.527306, [], [1, 2, 3, 4, 5, 6]), + (1720419321.981, [], [1, 2, 3, 4, 5, 6]), + (1720419324.073269, [], [1, 2, 3, 4, 5, 6]), + (1720497577.385151, [], [1, 2, 3, 4, 5, 6]), + (1720497694.789568, [], [1, 2, 3, 4, 5, 6]), + (1720497696.883431, [], [1, 2, 3, 4, 5, 6]), + (1720584999.597212, [], [1, 2, 3, 4, 5, 6]), + (1720585001.687849, [], [1, 2, 3, 4, 5, 6]), + (1720585005.063862, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720134251.830614, [], [1, 2, 3, 4, 5, 6]), + (1720407054.526951, [], [1, 2, 3, 4, 5, 6]), + (1720543564.686466, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720395362.215692, [], [1, 2, 3, 4, 5, 6]), (1720500480.122778, [], [1, 2, 3, 4, 5, 6])], + [ + (1720058412.695383, [], [1, 2, 3, 4, 5, 6]), + (1720228775.865928, [], [1, 2, 3, 4, 5, 6]), + (1720503282.31697, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720614350.980502, [], [1, 2, 3, 4, 5, 6])], + [ + (1719982519.149294, [], [1, 2, 3, 4, 5, 6]), + (1719982589.903207, [], [1, 2, 3, 4, 5, 6]), + (1719982591.966235, [], [1, 2, 3, 4, 5, 6]), + (1719982594.824529, [], [1, 2, 3, 4, 5, 6]), + (1720056059.106374, [], [1, 2, 3, 4, 5, 6]), + (1720056099.353137, [], [1, 2, 3, 4, 5, 6]), + (1720056101.438857, [], [1, 2, 3, 4, 5, 6]), + (1720084141.137944, [], [1, 2, 3, 4, 5, 6]), + (1720084195.578773, [], [1, 2, 3, 4, 5, 6]), + (1720136869.202173, [], [1, 2, 3, 4, 5, 6]), + (1720223064.342828, [], [1, 2, 3, 4, 5, 6]), + (1720223120.591787, [], [1, 2, 3, 4, 5, 6]), + (1720223122.696149, [], [1, 2, 3, 4, 5, 6]), + (1720239556.237398, [], [1, 2, 3, 4, 5, 6]), + (1720239630.045363, [], [1, 2, 3, 4, 5, 6]), + (1720239632.137037, [], [1, 2, 3, 4, 5, 6]), + (1720312988.468776, [], [1, 2, 3, 4, 5, 6]), + (1720313161.594176, [], [1, 2, 3, 4, 5, 6]), + (1720313163.656358, [], [1, 2, 3, 4, 5, 6]), + (1720413652.862676, [], [1, 2, 3, 4, 5, 6]), + (1720413773.395596, [], [1, 2, 3, 4, 5, 6]), + (1720484458.010065, [], [1, 2, 3, 4, 5, 6]), + (1720484503.114542, [], [1, 2, 3, 4, 5, 6]), + (1720484505.173957, [], [1, 2, 3, 4, 5, 6]), + (1720570920.862746, [], [1, 2, 3, 4, 5, 6]), + (1720571065.994777, [], [1, 2, 3, 4, 5, 6]), + (1720571068.086575, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720138634.579801, [], [1, 2, 3, 4, 5, 6]), (1720394701.653755, [], [1, 2, 3, 4, 5, 6])], + [(1720404840.88735, [], [1, 2, 3, 4, 5, 6]), (1720570759.329975, [], [1, 2, 3, 4, 5, 6])], + [(1720474997.255842, [], [1, 2, 3, 4, 5, 6])], + [ + (1719964981.812038, [], [1, 2, 3, 4, 5, 6]), + (1719965079.656724, [], [1, 2, 3, 4, 5, 6]), + (1719965081.766625, [], [1, 2, 3, 4, 5, 6]), + (1720017945.346535, [], [1, 2, 3, 4, 5, 6]), + (1720018196.228851, [], [1, 2, 3, 4, 5, 6]), + (1720018198.332037, [], [1, 2, 3, 4, 5, 6]), + (1720071944.789981, [], [1, 2, 3, 4, 5, 6]), + (1720071989.860765, [], [1, 2, 3, 4, 5, 6]), + (1720071991.963241, [], [1, 2, 3, 4, 5, 6]), + (1720226601.357382, [], [1, 2, 3, 4, 5, 6]), + (1720226662.671017, [], [1, 2, 3, 4, 5, 6]), + (1720226664.720854, [], [1, 2, 3, 4, 5, 6]), + (1720226666.697991, [], [1, 2, 3, 4, 5, 6]), + (1720245432.525672, [], [1, 2, 3, 4, 5, 6]), + (1720245586.690365, [], [1, 2, 3, 4, 5, 6]), + (1720245588.811888, [], [1, 2, 3, 4, 5, 6]), + (1720313288.75101, [], [1, 2, 3, 4, 5, 6]), + (1720313438.935319, [], [1, 2, 3, 4, 5, 6]), + (1720313440.997298, [], [1, 2, 3, 4, 5, 6]), + (1720325185.461926, [], [1, 2, 3, 4, 5, 6]), + (1720325279.708469, [], [1, 2, 3, 4, 5, 6]), + (1720325281.823994, [], [1, 2, 3, 4, 5, 6]), + (1720325284.895173, [], [1, 2, 3, 4, 5, 6]), + (1720325286.963747, [], [1, 2, 3, 4, 5, 6]), + (1720351212.007507, [], [1, 2, 3, 4, 5, 6]), + (1720351417.722923, [], [1, 2, 3, 4, 5, 6]), + (1720351419.786979, [], [1, 2, 3, 4, 5, 6]), + (1720410234.644402, [], [1, 2, 3, 4, 5, 6]), + (1720410236.746729, [], [1, 2, 3, 4, 5, 6]), + (1720484087.598816, [], [1, 2, 3, 4, 5, 6]), + (1720484089.656452, [], [1, 2, 3, 4, 5, 6]), + (1720560975.588946, [], [1, 2, 3, 4, 5, 6]), + (1720561062.767708, [], [1, 2, 3, 4, 5, 6]), + (1720576170.001406, [], [1, 2, 3, 4, 5, 6]), + (1720576274.339938, [], [1, 2, 3, 4, 5, 6]), + (1720634969.318238, [], [1, 2, 3, 4, 5, 6]), + (1720634971.383262, [], [1, 2, 3, 4, 5, 6]), + (1720634973.669218, [], [1, 2, 3, 4, 5, 6]), + (1720634975.727614, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720047138.987663, [], [1, 2, 3, 4, 5, 6]), + (1720239116.860589, [], [1, 2, 3, 4, 5, 6]), + (1720567216.089602, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720062114.160483, [], [1, 2, 3, 4, 5, 6])], + [(1719974901.32474, [], [1, 2, 3, 4, 5, 6]), (1720224712.94567, [], [1, 2, 3, 4, 5, 6])], + [ + (1719985511.407849, [], [1, 2, 3, 4, 5, 6]), + (1720140363.584567, [], [1, 2, 3, 4, 5, 6]), + (1720573348.34834, [], [1, 2, 3, 4, 5, 6]), + (1720649971.95392, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720325668.53657, [], [1, 2, 3, 4, 5, 6]), (1720407800.484026, [], [1, 2, 3, 4, 5, 6])], + [(1720313988.784401, [], [1, 2, 3, 4, 5, 6])], + [ + (1720137608.121513, [], [1, 2, 3, 4, 5, 6]), + (1720230219.916298, [], [1, 2, 3, 4, 5, 6]), + (1720576804.122481, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720060264.40999, [], [1, 2, 3, 4, 5, 6])], + [ + (1719982324.891431, [], [1, 2, 3, 4, 5, 6]), + (1719982326.95929, [], [1, 2, 3, 4, 5, 6]), + (1720072365.964045, [], [1, 2, 3, 4, 5, 6]), + (1720072368.013382, [], [1, 2, 3, 4, 5, 6]), + (1720185779.887725, [], [1, 2, 3, 4, 5, 6]), + (1720185782.013458, [], [1, 2, 3, 4, 5, 6]), + (1720230424.054008, [], [1, 2, 3, 4, 5, 6]), + (1720329463.631365, [], [1, 2, 3, 4, 5, 6]), + (1720329503.210461, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719978020.337077, [], [1, 2, 3, 4, 5, 6]), (1720378278.012205, [], [1, 2, 3, 4, 5, 6])], + [ + (1720198700.302556, [], [1, 2, 3, 4, 5, 6]), + (1720417057.718199, [], [1, 2, 3, 4, 5, 6]), + (1720584860.786802, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720627126.675399, [], [1, 2, 3, 4, 5, 6])], + [(1720072022.286212, [], [1, 2, 3, 4, 5, 6]), (1720366423.980574, [], [1, 2, 3, 4, 5, 6])], + [(1720221042.039954, [], [1, 2, 3, 4, 5, 6])], + [ + (1720060635.731519, [], [1, 2, 3, 4, 5, 6]), + (1720210299.946067, [], [1, 2, 3, 4, 5, 6]), + (1720283154.070272, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720402469.930097, [], [1, 2, 3, 4, 5, 6])], + [ + (1719972611.185894, [], [1, 2, 3, 4, 5, 6]), + (1720227219.185837, [], [1, 2, 3, 4, 5, 6]), + (1720565623.051185, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720060770.015072, [], [1, 2, 3, 4, 5, 6])], + [ + (1719979906.872722, [], [1, 2, 3, 4, 5, 6]), + (1719980094.376717, [], [1, 2, 3, 4, 5, 6]), + (1719980096.476308, [], [1, 2, 3, 4, 5, 6]), + (1720067152.682142, [], [1, 2, 3, 4, 5, 6]), + (1720067174.598435, [], [1, 2, 3, 4, 5, 6]), + (1720137635.975558, [], [1, 2, 3, 4, 5, 6]), + (1720137733.593423, [], [1, 2, 3, 4, 5, 6]), + (1720224539.774939, [], [1, 2, 3, 4, 5, 6]), + (1720323664.982932, [], [1, 2, 3, 4, 5, 6]), + (1720400336.830381, [], [1, 2, 3, 4, 5, 6]), + (1720400497.747426, [], [1, 2, 3, 4, 5, 6]), + (1720400499.843107, [], [1, 2, 3, 4, 5, 6]), + (1720486404.88152, [], [1, 2, 3, 4, 5, 6]), + (1720486460.387837, [], [1, 2, 3, 4, 5, 6]), + (1720486462.465262, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720494960.521565, [], [1, 2, 3, 4, 5, 6])], + [(1720492283.522426, [], [1, 2, 3, 4, 5, 6])], + [(1720588131.39025, [], [1, 2, 3, 4, 5, 6])], + [(1719965172.184078, [], [1, 2, 3, 4, 5, 6])], + [(1720313653.224728, [], [1, 2, 3, 4, 5, 6])], + [(1720133961.331413, [], [1, 2, 3, 4, 5, 6])], + [(1719969914.979558, [], [1, 2, 3, 4, 5, 6])], + [ + (1720051155.959984, [], [1, 2, 3, 4, 5, 6]), + (1720318569.685111, [], [1, 2, 3, 4, 5, 6]), + (1720499729.951734, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720328273.411971, [], [1, 2, 3, 4, 5, 6])], + [ + (1719982315.965122, [], [1, 2, 3, 4, 5, 6]), + (1720423276.150804, [], [1, 2, 3, 4, 5, 6]), + (1720586911.740203, [], [1, 2, 3, 4, 5, 6]), + ], + [(1719968679.211527, [], [1, 2, 3, 4, 5, 6])], + [(1720063388.278848, [], [1, 2, 3, 4, 5, 6]), (1720416336.796001, [], [1, 2, 3, 4, 5, 6])], + [(1720398479.735494, [], [1, 2, 3, 4, 5, 6]), (1720493260.033312, [], [1, 2, 3, 4, 5, 6])], + [ + (1720489609.661573, [], [1, 2, 3, 4, 5, 6]), + (1720489700.750791, [], [1, 2, 3, 4, 5, 6]), + (1720489717.546997, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720500732.208908, [], [1, 2, 3, 4, 5, 6])], + [ + (1720153118.225066, [], [1, 2, 3, 4, 5, 6]), + (1720314031.634943, [], [1, 2, 3, 4, 5, 6]), + (1720590337.724401, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720070140.554847, [], [1, 2, 3, 4, 5, 6]), (1720137932.433554, [], [1, 2, 3, 4, 5, 6])], + [(1719992154.926275, [], [1, 2, 3, 4, 5, 6]), (1720320574.945082, [], [1, 2, 3, 4, 5, 6])], + [(1719984916.520671, [], [1, 2, 3, 4, 5, 6]), (1720569849.178614, [], [1, 2, 3, 4, 5, 6])], + [(1720140614.641046, [], [1, 2, 3, 4, 5, 6]), (1720395184.350061, [], [1, 2, 3, 4, 5, 6])], + [(1720310387.035179, [], [1, 2, 3, 4, 5, 6]), (1720473940.199193, [], [1, 2, 3, 4, 5, 6])], + [(1720062920.051834, [], [1, 2, 3, 4, 5, 6]), (1720226181.474055, [], [1, 2, 3, 4, 5, 6])], + [(1720470329.222623, [], [1, 2, 3, 4, 5, 6])], + [(1720582334.499662, [], [1, 2, 3, 4, 5, 6])], + [(1720443828.896214, [], [1, 2, 3, 4, 5, 6]), (1720580682.756419, [], [1, 2, 3, 4, 5, 6])], + [ + (1720226425.344326, [], [1, 2, 3, 4, 5, 6]), + (1720310598.961662, [], [1, 2, 3, 4, 5, 6]), + (1720589761.631011, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720584698.862455, [], [1, 2, 3, 4, 5, 6])], + [(1720164879.185564, [], [1, 2, 3, 4, 5, 6]), (1720323846.480885, [], [1, 2, 3, 4, 5, 6])], + [(1720051096.071376, [], [1, 2, 3, 4, 5, 6]), (1720157299.452758, [], [1, 2, 3, 4, 5, 6])], + [ + (1720223524.412388, [], [1, 2, 3, 4, 5, 6]), + (1720326592.782923, [], [1, 2, 3, 4, 5, 6]), + (1720578100.065601, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720313647.455076, [], [1, 2, 3, 4, 5, 6]), (1720559337.211802, [], [1, 2, 3, 4, 5, 6])], + [ + (1719981335.449573, [], [1, 2, 3, 4, 5, 6]), + (1720067595.1521, [], [1, 2, 3, 4, 5, 6]), + (1720319132.823969, [], [1, 2, 3, 4, 5, 6]), + (1720491547.165147, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720019886.753884, [], [1, 2, 3, 4, 5, 6]), + (1720153101.556554, [], [1, 2, 3, 4, 5, 6]), + (1720313536.357232, [], [1, 2, 3, 4, 5, 6]), + (1720485395.202604, [], [1, 2, 3, 4, 5, 6]), + (1720568839.562655, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720310841.194378, [], [1, 2, 3, 4, 5, 6]), + (1720310912.574061, [], [1, 2, 3, 4, 5, 6]), + (1720310914.655803, [], [1, 2, 3, 4, 5, 6]), + (1720587828.804404, [], [1, 2, 3, 4, 5, 6]), + (1720588071.078858, [], [1, 2, 3, 4, 5, 6]), + (1720588073.115074, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720055953.618503, [], [1, 2, 3, 4, 5, 6]), + (1720223652.080905, [], [1, 2, 3, 4, 5, 6]), + (1720308372.703732, [], [1, 2, 3, 4, 5, 6]), + (1720624033.359415, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720173756.125859, [], [1, 2, 3, 4, 5, 6]), + (1720315128.683231, [], [1, 2, 3, 4, 5, 6]), + (1720466410.646777, [], [1, 2, 3, 4, 5, 6]), + ], + [(1720157263.810637, [], [1, 2, 3, 4, 5, 6]), (1720235081.49838, [], [1, 2, 3, 4, 5, 6])], + [ + (1720229216.005254, [], [1, 2, 3, 4, 5, 6]), + (1720557735.625871, [], [1, 2, 3, 4, 5, 6]), + (1720627294.521232, [], [1, 2, 3, 4, 5, 6]), + ], + [ + (1720394336.326148, [], [1, 2, 3, 4, 5, 6]), + (1720394382.775033, [], [1, 2, 3, 4, 5, 6]), + (1720394404.054186, [], [1, 2, 3, 4, 5, 6]), + (1720394488.655765, [], [1, 2, 3, 4, 5, 6]), + (1720394583.815862, [], [1, 2, 3, 4, 5, 6]), + (1720394609.744123, [], [1, 2, 3, 4, 5, 6]), + (1720394643.351845, [], [1, 2, 3, 4, 5, 6]), + (1720394661.447752, [], [1, 2, 3, 4, 5, 6]), + (1720394715.354794, [], [1, 2, 3, 4, 5, 6]), + ], + ] + for b in a: + calculate_funnel_from_user_events(6, 1123200, "first_touch", "ordered", [[]], b) diff --git a/posthog/user_scripts/aggregate_funnel.py b/posthog/user_scripts/aggregate_funnel.py new file mode 100755 index 0000000000000..162918a819625 --- /dev/null +++ b/posthog/user_scripts/aggregate_funnel.py @@ -0,0 +1,144 @@ +#!/usr/bin/python3 +import json +import sys +from dataclasses import dataclass, replace +from itertools import groupby, permutations +from typing import Any, cast +from collections.abc import Sequence + + +def parse_args(line): + args = json.loads(line) + return [ + int(args["num_steps"]), + int(args["conversion_window_limit"]), + str(args["breakdown_attribution_type"]), + str(args["funnel_order_type"]), + args["prop_vals"], # Array(Array(String)) + args["value"], # Array(Tuple(Nullable(Float64), Nullable(DateTime), Array(String), Array(Int8))) + ] + + +@dataclass(frozen=True) +class EnteredTimestamp: + timestamp: Any + timings: Any + + +# each one can be multiple steps here +# it only matters when they entered the funnel - you can propagate the time from the previous step when you update +# This function is defined for Clickhouse in user_defined_functions.xml along with types +# num_steps is the total number of steps in the funnel +# conversion_window_limit is in seconds +# events is a array of tuples of (timestamp, breakdown, [steps]) +# steps is an array of integers which represent the steps that this event qualifies for. it looks like [1,3,5,6]. +# negative integers represent an exclusion on that step. each event is either all exclusions or all steps. +def calculate_funnel_from_user_events( + num_steps: int, + conversion_window_limit_seconds: int, + breakdown_attribution_type: str, + funnel_order_type: str, + prop_vals: list[Any], + events: Sequence[tuple[float, list[str] | int | str, list[int]]], +): + default_entered_timestamp = EnteredTimestamp(0, []) + max_step = [0, default_entered_timestamp] + # If the attribution mode is a breakdown step, set this to the integer that represents that step + breakdown_step = int(breakdown_attribution_type[5:]) if breakdown_attribution_type.startswith("step_") else None + + # This function returns an Array. We build up an array of strings to return here. + results: list[tuple[int, Any, list[float]]] = [] + + # Process an event. If this hits an exclusion, return False, else return True. + def process_event(timestamp, breakdown, steps, *, entered_timestamp, prop_val) -> bool: + # iterate the steps in reverse so we don't count this event multiple times + for step in reversed(steps): + exclusion = False + if step < 0: + exclusion = True + step = -step + + in_match_window = timestamp - entered_timestamp[step - 1].timestamp <= conversion_window_limit_seconds + already_reached_this_step_with_same_entered_timestamp = ( + entered_timestamp[step].timestamp == entered_timestamp[step - 1].timestamp + ) + + if in_match_window and not already_reached_this_step_with_same_entered_timestamp: + if exclusion: + results.append((-1, prop_val, [])) + return False + is_unmatched_step_attribution = ( + breakdown_step is not None and step == breakdown_step - 1 and prop_val != breakdown + ) + if not is_unmatched_step_attribution: + entered_timestamp[step] = replace( + entered_timestamp[step - 1], timings=[*entered_timestamp[step - 1].timings, timestamp] + ) + if step > max_step[0]: + max_step[:] = (step, entered_timestamp[step]) + + if funnel_order_type == "strict": + for i in range(len(entered_timestamp)): + if i not in steps: + entered_timestamp[i] = default_entered_timestamp + + return True + + # We call this for each possible breakdown value. + def loop_prop_val(prop_val): + # an array of when the user entered the funnel + # entered_timestamp = [(0, "", [])] * (num_steps + 1) + max_step[:] = [0, default_entered_timestamp] + entered_timestamp: list[EnteredTimestamp] = [default_entered_timestamp] * (num_steps + 1) + + def add_max_step(): + i = cast(int, max_step[0]) + final = cast(EnteredTimestamp, max_step[1]) + results.append((i - 1, prop_val, [final.timings[i] - final.timings[i - 1] for i in range(1, i)])) + + filtered_events = ( + ((timestamp, breakdown, steps) for (timestamp, breakdown, steps) in events if breakdown == prop_val) + if breakdown_attribution_type == "all_events" + else events + ) + for timestamp, events_with_same_timestamp_iterator in groupby(filtered_events, key=lambda x: x[0]): + events_with_same_timestamp = tuple(events_with_same_timestamp_iterator) + entered_timestamp[0] = EnteredTimestamp(timestamp, []) + if len(events_with_same_timestamp) == 1: + if not process_event( + *events_with_same_timestamp[0], entered_timestamp=entered_timestamp, prop_val=prop_val + ): + return + else: + # This is a special case for events with the same timestamp + # We play all of their permutations and most generously take the ones that advanced the furthest + # This has quite bad performance, and can probably be optimized through clever but annoying logic + # but shouldn't be hit too often + entered_timestamps = [] + for events_group_perm in permutations(events_with_same_timestamp): + entered_timestamps.append(list(entered_timestamp)) + for event in events_group_perm: + if not process_event(*event, entered_timestamp=entered_timestamps[-1], prop_val=prop_val): + # If any of the permutations hits an exclusion, we exclude this user. + # This isn't an important implementation detail and we could do something smarter here. + return + for i in range(len(entered_timestamp)): + entered_timestamp[i] = max((x[i] for x in entered_timestamps), key=lambda x: x.timestamp) + + # If we have hit the goal, we can terminate early + if entered_timestamp[num_steps].timestamp > 0: + add_max_step() + return + + # Find the furthest step we have made it to and print it + add_max_step() + return + + [loop_prop_val(prop_val) for prop_val in prop_vals] + print(json.dumps({"result": results}), end="\n") # noqa: T201 + + +if __name__ == "__main__": + for line in sys.stdin: + calculate_funnel_from_user_events(*parse_args(line)) + sys.stdout.flush() diff --git a/posthog/user_scripts/aggregate_funnel_array.py b/posthog/user_scripts/aggregate_funnel_array.py new file mode 100755 index 0000000000000..17b053bb7d448 --- /dev/null +++ b/posthog/user_scripts/aggregate_funnel_array.py @@ -0,0 +1,9 @@ +#!/usr/bin/python3 +import sys + +from aggregate_funnel import parse_args, calculate_funnel_from_user_events + +if __name__ == "__main__": + for line in sys.stdin: + calculate_funnel_from_user_events(*parse_args(line)) + sys.stdout.flush() diff --git a/posthog/user_scripts/aggregate_funnel_array_trends.py b/posthog/user_scripts/aggregate_funnel_array_trends.py new file mode 100755 index 0000000000000..15e93f5452797 --- /dev/null +++ b/posthog/user_scripts/aggregate_funnel_array_trends.py @@ -0,0 +1,9 @@ +#!/usr/bin/python3 +import sys + +from aggregate_funnel_trends import parse_args, calculate_funnel_trends_from_user_events + +if __name__ == "__main__": + for line in sys.stdin: + calculate_funnel_trends_from_user_events(*parse_args(line)) + sys.stdout.flush() diff --git a/posthog/user_scripts/aggregate_funnel_array_trends_test.py b/posthog/user_scripts/aggregate_funnel_array_trends_test.py new file mode 100755 index 0000000000000..44d3cc9b8f059 --- /dev/null +++ b/posthog/user_scripts/aggregate_funnel_array_trends_test.py @@ -0,0 +1,13 @@ +#!/usr/bin/python3 + +from aggregate_funnel_trends import calculate_funnel_trends_from_user_events, parse_args +import sys +import json + +if __name__ == "__main__": + for line in sys.stdin: + try: + calculate_funnel_trends_from_user_events(*parse_args(line)) + except Exception as e: + print(json.dumps({"result": json.dumps(str(e))}), end="\n") # noqa: T201 + sys.stdout.flush() diff --git a/posthog/user_scripts/aggregate_funnel_cohort.py b/posthog/user_scripts/aggregate_funnel_cohort.py new file mode 100755 index 0000000000000..17b053bb7d448 --- /dev/null +++ b/posthog/user_scripts/aggregate_funnel_cohort.py @@ -0,0 +1,9 @@ +#!/usr/bin/python3 +import sys + +from aggregate_funnel import parse_args, calculate_funnel_from_user_events + +if __name__ == "__main__": + for line in sys.stdin: + calculate_funnel_from_user_events(*parse_args(line)) + sys.stdout.flush() diff --git a/posthog/user_scripts/aggregate_funnel_cohort_trends.py b/posthog/user_scripts/aggregate_funnel_cohort_trends.py new file mode 100755 index 0000000000000..15e93f5452797 --- /dev/null +++ b/posthog/user_scripts/aggregate_funnel_cohort_trends.py @@ -0,0 +1,9 @@ +#!/usr/bin/python3 +import sys + +from aggregate_funnel_trends import parse_args, calculate_funnel_trends_from_user_events + +if __name__ == "__main__": + for line in sys.stdin: + calculate_funnel_trends_from_user_events(*parse_args(line)) + sys.stdout.flush() diff --git a/posthog/user_scripts/aggregate_funnel_test.py b/posthog/user_scripts/aggregate_funnel_test.py new file mode 100755 index 0000000000000..e0689b82af21c --- /dev/null +++ b/posthog/user_scripts/aggregate_funnel_test.py @@ -0,0 +1,13 @@ +#!/usr/bin/python3 +import json + +from aggregate_funnel import calculate_funnel_from_user_events, parse_args +import sys + +if __name__ == "__main__": + for line in sys.stdin: + try: + calculate_funnel_from_user_events(*parse_args(line)) + except Exception as e: + print(json.dumps({"result": json.dumps(str(e))}), end="\n") # noqa: T201 + sys.stdout.flush() diff --git a/posthog/user_scripts/aggregate_funnel_trends.py b/posthog/user_scripts/aggregate_funnel_trends.py new file mode 100755 index 0000000000000..0aa96b7a19b96 --- /dev/null +++ b/posthog/user_scripts/aggregate_funnel_trends.py @@ -0,0 +1,131 @@ +#!/usr/bin/python3 +import sys +from dataclasses import dataclass, replace +from typing import Any +from collections.abc import Sequence +import json + + +def parse_args(line): + args = json.loads(line) + return [ + int(args["from_step"]), + int(args["num_steps"]), + int(args["conversion_window_limit"]), + str(args["breakdown_attribution_type"]), + str(args["funnel_order_type"]), + args["prop_vals"], # Array(Array(String)) + args["value"], # Array(Tuple(Nullable(Float64), Nullable(DateTime), Array(String), Array(Int8))) + ] + + +@dataclass(frozen=True) +class EnteredTimestamp: + timestamp: Any + timings: Any + + +# each one can be multiple steps here +# it only matters when they entered the funnel - you can propagate the time from the previous step when you update +# This function is defined for Clickhouse in user_defined_functions.xml along with types +# num_steps is the total number of steps in the funnel +# conversion_window_limit is in seconds +# events is a array of tuples of (timestamp, breakdown, [steps]) +# steps is an array of integers which represent the steps that this event qualifies for. it looks like [1,3,5,6]. +# negative integers represent an exclusion on that step. each event is either all exclusions or all steps. +def calculate_funnel_trends_from_user_events( + from_step: int, + num_steps: int, + conversion_window_limit_seconds: int, + breakdown_attribution_type: str, + funnel_order_type: str, + prop_vals: list[Any], + events: Sequence[tuple[float, int, list[str] | int | str, list[int]]], +): + default_entered_timestamp = EnteredTimestamp(0, []) + # If the attribution mode is a breakdown step, set this to the integer that represents that step + breakdown_step = int(breakdown_attribution_type[5:]) if breakdown_attribution_type.startswith("step_") else None + + # Results is a map of start intervals to success or failure. If an interval isn't here, it means the + # user didn't enter + results = {} + + # We call this for each possible breakdown value. + def loop_prop_val(prop_val): + # we need to track every distinct entry into the funnel through to the end + filtered_events = ( + ( + (timestamp, interval_start, breakdown, steps) + for (timestamp, interval_start, breakdown, steps) in events + if breakdown == prop_val + ) + if breakdown_attribution_type == "all_events" + else events + ) + list_of_entered_timestamps = [] + + for timestamp, interval_start, breakdown, steps in filtered_events: + for step in reversed(steps): + exclusion = False + if step < 0: + exclusion = True + step = -step + # Special code to handle the first step + # Potential Optimization: we could skip tracking here if the user has already completed the funnel for this interval + if step == 1: + entered_timestamp = [default_entered_timestamp] * (num_steps + 1) + # Set the interval start at 0, which is what we want to return if this works. + # For strict funnels, we need to track if the "from_step" has been hit + # Abuse the timings field on the 0th index entered_timestamp to have the elt True if we have + entered_timestamp[0] = EnteredTimestamp(interval_start, [True] if from_step == 0 else []) + entered_timestamp[1] = EnteredTimestamp(timestamp, [timestamp]) + list_of_entered_timestamps.append(entered_timestamp) + else: + for entered_timestamp in list_of_entered_timestamps[:]: + in_match_window = ( + timestamp - entered_timestamp[step - 1].timestamp <= conversion_window_limit_seconds + ) + already_reached_this_step_with_same_entered_timestamp = ( + entered_timestamp[step].timestamp == entered_timestamp[step - 1].timestamp + ) + if in_match_window and not already_reached_this_step_with_same_entered_timestamp: + if exclusion: + # this is a complete failure, exclude this person, don't print anything, don't count + return False + is_unmatched_step_attribution = ( + breakdown_step is not None and step == breakdown_step - 1 and prop_val != breakdown + ) + if not is_unmatched_step_attribution: + entered_timestamp[step] = replace( + entered_timestamp[step - 1], + timings=[*entered_timestamp[step - 1].timings, timestamp], + ) + # check if we have hit the goal. if we have, remove it from the list and add it to the successful_timestamps + if entered_timestamp[num_steps].timestamp > 0: + results[entered_timestamp[0].timestamp] = (1, prop_val) + list_of_entered_timestamps.remove(entered_timestamp) + # If we have hit the from_step threshold, record it (abuse the timings field) + elif step == from_step + 1: + entered_timestamp[0].timings.append(True) + + # At the end of the event, clear all steps that weren't done by that event + if funnel_order_type == "strict": + for entered_timestamp in list_of_entered_timestamps[:]: + for i in range(1, len(entered_timestamp)): + if i not in steps: + entered_timestamp[i] = default_entered_timestamp + + # At this point, everything left in entered_timestamps is a failure, if it has made it to from_step + for entered_timestamp in list_of_entered_timestamps: + if entered_timestamp[0].timestamp not in results and len(entered_timestamp[0].timings) > 0: + results[entered_timestamp[0].timestamp] = (-1, prop_val) + + [loop_prop_val(prop_val) for prop_val in prop_vals] + result = [(interval_start, success_bool, prop_val) for interval_start, (success_bool, prop_val) in results.items()] + print(json.dumps({"result": result}), end="\n") # noqa: T201 + + +if __name__ == "__main__": + for line in sys.stdin: + calculate_funnel_trends_from_user_events(*parse_args(line)) + sys.stdout.flush() diff --git a/posthog/utils.py b/posthog/utils.py index 39bf6d606982f..aaf02658b42d1 100644 --- a/posthog/utils.py +++ b/posthog/utils.py @@ -58,6 +58,7 @@ from posthog.models import Team, User DATERANGE_MAP = { + "second": datetime.timedelta(seconds=1), "minute": datetime.timedelta(minutes=1), "hour": datetime.timedelta(hours=1), "day": datetime.timedelta(days=1), diff --git a/requirements.in b/requirements.in index 17c4feb2f808d..959a0b2dc75de 100644 --- a/requirements.in +++ b/requirements.in @@ -90,7 +90,7 @@ sshtunnel==0.4.0 statshog==1.0.6 structlog==23.2.0 sqlparse==0.4.4 -temporalio==1.6.0 +temporalio==1.7.0 token-bucket==0.3.0 toronado==0.1.0 webdriver_manager==4.0.1 diff --git a/requirements.txt b/requirements.txt index c8d3e50b4256c..e31cbdd5d09bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -665,7 +665,7 @@ structlog==23.2.0 # via # -r requirements.in # django-structlog -temporalio==1.6.0 +temporalio==1.7.0 # via -r requirements.in tenacity==8.2.3 # via