diff --git a/api/chalicelib/core/errors/errors_ch.py b/api/chalicelib/core/errors/errors_ch.py index 1c67e871d..f0845110b 100644 --- a/api/chalicelib/core/errors/errors_ch.py +++ b/api/chalicelib/core/errors/errors_ch.py @@ -338,14 +338,14 @@ def search(data: schemas.SearchErrorsSchema, project: schemas.ProjectContext, us SELECT details.error_id as error_id, name, message, users, total, sessions, last_occurrence, first_occurrence, chart - FROM (SELECT JSONExtractString(toString(`$properties`), 'error_id') AS error_id, + FROM (SELECT error_id, JSONExtractString(toString(`$properties`), 'name') AS name, JSONExtractString(toString(`$properties`), 'message') AS message, COUNT(DISTINCT user_id) AS users, COUNT(DISTINCT events.session_id) AS sessions, MAX(created_at) AS max_datetime, MIN(created_at) AS min_datetime, - COUNT(DISTINCT JSONExtractString(toString(`$properties`), 'error_id')) + COUNT(DISTINCT error_id) OVER() AS total FROM {MAIN_EVENTS_TABLE} AS events INNER JOIN (SELECT session_id, coalesce(user_id,toString(user_uuid)) AS user_id @@ -357,7 +357,7 @@ def search(data: schemas.SearchErrorsSchema, project: schemas.ProjectContext, us GROUP BY error_id, name, message ORDER BY {sort} {order} LIMIT %(errors_limit)s OFFSET %(errors_offset)s) AS details - INNER JOIN (SELECT JSONExtractString(toString(`$properties`), 'error_id') AS error_id, + INNER JOIN (SELECT error_id, toUnixTimestamp(MAX(created_at))*1000 AS last_occurrence, toUnixTimestamp(MIN(created_at))*1000 AS first_occurrence FROM {MAIN_EVENTS_TABLE} @@ -366,7 +366,7 @@ def search(data: schemas.SearchErrorsSchema, project: schemas.ProjectContext, us GROUP BY error_id) AS time_details ON details.error_id=time_details.error_id INNER JOIN (SELECT error_id, groupArray([timestamp, count]) AS chart - FROM (SELECT JSONExtractString(toString(`$properties`), 'error_id') AS error_id, + FROM (SELECT error_id, gs.generate_series AS timestamp, COUNT(DISTINCT session_id) AS count FROM generate_series(%(startDate)s, %(endDate)s, %(step_size)s) AS gs diff --git a/ee/scripts/schema/db/init_dbs/clickhouse/1.22.0/1.22.0.sql b/ee/scripts/schema/db/init_dbs/clickhouse/1.22.0/1.22.0.sql index 995914e03..49b5c808f 100644 --- a/ee/scripts/schema/db/init_dbs/clickhouse/1.22.0/1.22.0.sql +++ b/ee/scripts/schema/db/init_dbs/clickhouse/1.22.0/1.22.0.sql @@ -151,8 +151,7 @@ CREATE TABLE IF NOT EXISTS product_analytics.events _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) ORDER BY (project_id, "$event_name", created_at, session_id) - TTL _timestamp + INTERVAL 1 MONTH , - _deleted_at + INTERVAL 1 DAY DELETE WHERE _deleted_at != '1970-01-01 00:00:00'; + TTL _deleted_at + INTERVAL 1 DAY DELETE WHERE _deleted_at != '1970-01-01 00:00:00'; -- The list of events that should not be ingested, -- according to a specific event_name and optional properties diff --git a/ee/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql b/ee/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql index eba6f793b..5f6a06511 100644 --- a/ee/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql +++ b/ee/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql @@ -9,8 +9,7 @@ CREATE TABLE IF NOT EXISTS experimental.autocomplete _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, type, value) - TTL _timestamp + INTERVAL 1 MONTH; + ORDER BY (project_id, type, value); CREATE TABLE IF NOT EXISTS experimental.events ( @@ -87,8 +86,7 @@ CREATE TABLE IF NOT EXISTS experimental.events _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(datetime) - ORDER BY (project_id, datetime, event_type, session_id, message_id) - TTL datetime + INTERVAL 1 MONTH; + ORDER BY (project_id, datetime, event_type, session_id, message_id); @@ -140,7 +138,6 @@ CREATE TABLE IF NOT EXISTS experimental.sessions ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMMDD(datetime) ORDER BY (project_id, datetime, session_id) - TTL datetime + INTERVAL 1 MONTH SETTINGS index_granularity = 512; CREATE TABLE IF NOT EXISTS experimental.user_favorite_sessions @@ -152,8 +149,7 @@ CREATE TABLE IF NOT EXISTS experimental.user_favorite_sessions sign Int8 ) ENGINE = CollapsingMergeTree(sign) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, user_id, session_id) - TTL _timestamp + INTERVAL 3 MONTH; + ORDER BY (project_id, user_id, session_id); CREATE TABLE IF NOT EXISTS experimental.user_viewed_sessions ( @@ -163,8 +159,7 @@ CREATE TABLE IF NOT EXISTS experimental.user_viewed_sessions _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, user_id, session_id) - TTL _timestamp + INTERVAL 3 MONTH; + ORDER BY (project_id, user_id, session_id); CREATE TABLE IF NOT EXISTS experimental.user_viewed_errors ( @@ -174,8 +169,7 @@ CREATE TABLE IF NOT EXISTS experimental.user_viewed_errors _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, user_id, error_id) - TTL _timestamp + INTERVAL 3 MONTH; + ORDER BY (project_id, user_id, error_id); CREATE TABLE IF NOT EXISTS experimental.issues ( @@ -188,8 +182,7 @@ CREATE TABLE IF NOT EXISTS experimental.issues _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, issue_id, type) - TTL _timestamp + INTERVAL 1 MONTH; + ORDER BY (project_id, issue_id, type); @@ -292,8 +285,7 @@ CREATE TABLE IF NOT EXISTS experimental.sessions_feature_flags _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(datetime) - ORDER BY (project_id, datetime, session_id, feature_flag_id, condition_id) - TTL datetime + INTERVAL 3 MONTH; + ORDER BY (project_id, datetime, session_id, feature_flag_id, condition_id); CREATE TABLE IF NOT EXISTS experimental.ios_events ( @@ -329,8 +321,7 @@ CREATE TABLE IF NOT EXISTS experimental.ios_events _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(datetime) - ORDER BY (project_id, datetime, event_type, session_id, message_id) - TTL datetime + INTERVAL 1 MONTH; + ORDER BY (project_id, datetime, event_type, session_id, message_id); SET allow_experimental_json_type = 1; @@ -540,8 +531,7 @@ message_id UInt64 _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) ORDER BY (project_id, "$event_name", created_at, session_id) - TTL _timestamp + INTERVAL 1 MONTH , - _deleted_at + INTERVAL 1 DAY DELETE WHERE _deleted_at != '1970-01-01 00:00:00'; + TTL _deleted_at + INTERVAL 1 DAY DELETE WHERE _deleted_at != '1970-01-01 00:00:00'; -- The list of events that should not be ingested, -- according to a specific event_name and optional properties diff --git a/frontend/app/components/Charts/SankeyChart.tsx b/frontend/app/components/Charts/SankeyChart.tsx index 9f2ca31c4..4142e395e 100644 --- a/frontend/app/components/Charts/SankeyChart.tsx +++ b/frontend/app/components/Charts/SankeyChart.tsx @@ -34,11 +34,12 @@ interface Props { onChartClick?: (filters: any[]) => void; isUngrouped?: boolean; inGrid?: boolean; + startPoint: 'end' | 'start' } const EChartsSankey: React.FC = (props) => { const { t } = useTranslation(); - const { data, height = 240, onChartClick, isUngrouped } = props; + const { data, height = 240, onChartClick, isUngrouped, startPoint } = props; const chartRef = React.useRef(null); const [finalNodeCount, setFinalNodeCount] = React.useState(data.nodes.length); @@ -110,8 +111,9 @@ const EChartsSankey: React.FC = (props) => { if (echartNodes.length === 0) return; + const mainNodeLink = startPoint === 'end' ? echartNodes.findIndex(n => n.id === 0) : 0; const startNodeValue = echartLinks - .filter((link) => link.source === 0) + .filter((link) => startPoint === 'start' ? link.source === mainNodeLink : link.target === mainNodeLink) .reduce((sum, link) => sum + link.value, 0); Object.keys(nodeValues).forEach((nodeId) => { diff --git a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx index 4b0313ef2..0460053a5 100644 --- a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx @@ -538,6 +538,7 @@ function WidgetChart(props: Props) { dashboardStore.drillDownFilter.merge({ filters, page: 1 }); }} isUngrouped={isUngrouped} + startPoint={metric.startType} /> ); } diff --git a/frontend/app/components/Session/Player/ClipPlayer/ClipPlayerContent.tsx b/frontend/app/components/Session/Player/ClipPlayer/ClipPlayerContent.tsx index ce4284d03..6bc61da82 100644 --- a/frontend/app/components/Session/Player/ClipPlayer/ClipPlayerContent.tsx +++ b/frontend/app/components/Session/Player/ClipPlayer/ClipPlayerContent.tsx @@ -56,9 +56,9 @@ function ClipPlayerContent(props: Props) { return (
-
+
diff --git a/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx b/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx index 643673bf7..940c257cd 100644 --- a/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx +++ b/frontend/app/components/Session_/EventsBlock/EventsBlock.tsx @@ -104,6 +104,7 @@ function EventsBlock(props: IProps) { : false : true ).filter((e: any) => !e.noteId && e.type !== 'TABCHANGE' && uiPlayerStore.showOnlySearchEvents ? e.isHighlighted : true); + } }, [ filteredLength, query, diff --git a/frontend/app/mstore/sessionStore.ts b/frontend/app/mstore/sessionStore.ts index e5ae13218..c283a465f 100644 --- a/frontend/app/mstore/sessionStore.ts +++ b/frontend/app/mstore/sessionStore.ts @@ -15,6 +15,7 @@ import { loadFile } from 'App/player/web/network/loadFiles'; import { LAST_7_DAYS } from 'Types/app/period'; import { filterMap } from 'App/mstore/searchStore'; import { getDateRangeFromValue } from 'App/dateRange'; +import { searchStore, searchStoreLive } from './index'; import { checkEventWithFilters } from '@/components/Session_/Player/Controls/checkEventWithFilters'; const range = getDateRangeFromValue(LAST_7_DAYS); diff --git a/scripts/schema/db/init_dbs/clickhouse/1.22.0/1.22.0.sql b/scripts/schema/db/init_dbs/clickhouse/1.22.0/1.22.0.sql index 97eb1216d..279c9517e 100644 --- a/scripts/schema/db/init_dbs/clickhouse/1.22.0/1.22.0.sql +++ b/scripts/schema/db/init_dbs/clickhouse/1.22.0/1.22.0.sql @@ -9,8 +9,7 @@ CREATE TABLE IF NOT EXISTS experimental.autocomplete _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, type, value) - TTL _timestamp + INTERVAL 1 MONTH; + ORDER BY (project_id, type, value); CREATE TABLE IF NOT EXISTS experimental.events ( @@ -87,8 +86,7 @@ CREATE TABLE IF NOT EXISTS experimental.events _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(datetime) - ORDER BY (project_id, datetime, event_type, session_id, message_id) - TTL datetime + INTERVAL 1 MONTH; + ORDER BY (project_id, datetime, event_type, session_id, message_id); @@ -140,7 +138,6 @@ CREATE TABLE IF NOT EXISTS experimental.sessions ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMMDD(datetime) ORDER BY (project_id, datetime, session_id) - TTL datetime + INTERVAL 1 MONTH SETTINGS index_granularity = 512; CREATE TABLE IF NOT EXISTS experimental.issues @@ -154,8 +151,7 @@ CREATE TABLE IF NOT EXISTS experimental.issues _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, issue_id, type) - TTL _timestamp + INTERVAL 1 MONTH; + ORDER BY (project_id, issue_id, type); CREATE TABLE IF NOT EXISTS experimental.ios_events ( @@ -191,8 +187,7 @@ CREATE TABLE IF NOT EXISTS experimental.ios_events _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(datetime) - ORDER BY (project_id, datetime, event_type, session_id, message_id) - TTL datetime + INTERVAL 1 MONTH; + ORDER BY (project_id, datetime, event_type, session_id, message_id); SET allow_experimental_json_type = 1; @@ -345,8 +340,7 @@ CREATE TABLE IF NOT EXISTS product_analytics.events _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) ORDER BY (project_id, "$event_name", created_at, session_id) - TTL _timestamp + INTERVAL 1 MONTH , - _deleted_at + INTERVAL 1 DAY DELETE WHERE _deleted_at != '1970-01-01 00:00:00'; + TTL _deleted_at + INTERVAL 1 DAY DELETE WHERE _deleted_at != '1970-01-01 00:00:00'; -- The list of events that should not be ingested, -- according to a specific event_name and optional properties diff --git a/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql b/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql index 272ffd782..1283dc4e9 100644 --- a/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql +++ b/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql @@ -9,8 +9,7 @@ CREATE TABLE IF NOT EXISTS experimental.autocomplete _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, type, value) - TTL _timestamp + INTERVAL 1 MONTH; + ORDER BY (project_id, type, value); CREATE TABLE IF NOT EXISTS experimental.events ( @@ -87,8 +86,7 @@ CREATE TABLE IF NOT EXISTS experimental.events _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(datetime) - ORDER BY (project_id, datetime, event_type, session_id, message_id) - TTL datetime + INTERVAL 1 MONTH; + ORDER BY (project_id, datetime, event_type, session_id, message_id); @@ -140,7 +138,6 @@ CREATE TABLE IF NOT EXISTS experimental.sessions ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMMDD(datetime) ORDER BY (project_id, datetime, session_id) - TTL datetime + INTERVAL 1 MONTH SETTINGS index_granularity = 512; CREATE TABLE IF NOT EXISTS experimental.user_favorite_sessions @@ -188,8 +185,7 @@ CREATE TABLE IF NOT EXISTS experimental.issues _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(_timestamp) - ORDER BY (project_id, issue_id, type) - TTL _timestamp + INTERVAL 1 MONTH; + ORDER BY (project_id, issue_id, type); CREATE TABLE IF NOT EXISTS experimental.ios_events ( @@ -225,8 +221,7 @@ CREATE TABLE IF NOT EXISTS experimental.ios_events _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(datetime) - ORDER BY (project_id, datetime, event_type, session_id, message_id) - TTL datetime + INTERVAL 1 MONTH; + ORDER BY (project_id, datetime, event_type, session_id, message_id); SET allow_experimental_json_type = 1; @@ -435,8 +430,7 @@ message_id UInt64 _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) ORDER BY (project_id, "$event_name", created_at, session_id) - TTL _timestamp + INTERVAL 1 MONTH , - _deleted_at + INTERVAL 1 DAY DELETE WHERE _deleted_at != '1970-01-01 00:00:00'; + TTL _deleted_at + INTERVAL 1 DAY DELETE WHERE _deleted_at != '1970-01-01 00:00:00'; -- The list of events that should not be ingested, -- according to a specific event_name and optional properties