From 9949928335d470deccc33371a16ecf8393397e9c Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Fri, 14 Feb 2025 16:14:17 +0100 Subject: [PATCH 01/47] ui: support auto opening for AutocompleteModal --- .../Dashboard/components/FilterSeries/FilterSeries.tsx | 1 + .../Filters/FilterAutoComplete/AutocompleteModal.tsx | 10 ++++++++++ .../Filters/FilterAutoComplete/FilterAutoComplete.tsx | 1 + .../FilterAutoCompleteLocal.tsx | 1 + .../shared/Filters/FilterValue/FilterValue.tsx | 5 +++++ .../shared/LiveSessionSearch/LiveSessionSearch.tsx | 1 + .../shared/SessionFilters/SessionFilters.tsx | 1 + frontend/app/mstore/types/filter.ts | 2 ++ 8 files changed, 22 insertions(+) diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index f73546ebc..0844e6259 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -168,6 +168,7 @@ function FilterSeries(props: Props) { }; const onAddFilter = (filter: any) => { + filter.autoOpen = true; series.filter.addFilter(filter); observeChanges(); } diff --git a/frontend/app/components/shared/Filters/FilterAutoComplete/AutocompleteModal.tsx b/frontend/app/components/shared/Filters/FilterAutoComplete/AutocompleteModal.tsx index 4014ffb1b..409caeb81 100644 --- a/frontend/app/components/shared/Filters/FilterAutoComplete/AutocompleteModal.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoComplete/AutocompleteModal.tsx @@ -234,6 +234,7 @@ interface Props { placeholder?: string; modalProps?: any; mapValues?: (value: string) => string; + isAutoOpen?: boolean; } export function AutoCompleteContainer(props: Props) { @@ -241,6 +242,15 @@ export function AutoCompleteContainer(props: Props) { const [showValueModal, setShowValueModal] = useState(false); const [hovered, setHovered] = useState(false); const isEmpty = props.value.length === 0 || !props.value[0]; + + React.useEffect(() => { + if (props.isAutoOpen) { + setTimeout(() => { + setShowValueModal(true); + }, 1) + } + }, [props.isAutoOpen]) + const onClose = () => setShowValueModal(false); const onApply = (values: string[]) => { setTimeout(() => { diff --git a/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx b/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx index c64a10d7e..f1ac440d3 100644 --- a/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx @@ -44,6 +44,7 @@ interface Props { hideOrText?: boolean; onApplyValues: (values: string[]) => void; modalProps?: Record + isAutoOpen?: boolean; } const FilterAutoComplete = observer( diff --git a/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx b/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx index 48e6617d3..b29a51be1 100644 --- a/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx @@ -18,6 +18,7 @@ interface Props { allowDecimals?: boolean; modalProps?: Record; onApplyValues: (values: string[]) => void; + isAutoOpen?: boolean; } function FilterAutoCompleteLocal(props: { params: any, values: string[], onClose: () => void, onApply: (values: string[]) => void, placeholder?: string }) { diff --git a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx index e8b965623..5d4c60ca1 100644 --- a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx +++ b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx @@ -18,6 +18,8 @@ interface Props { } function FilterValue(props: Props) { const { filter } = props; + const isAutoOpen = filter.autoOpen; + const [durationValues, setDurationValues] = useState({ minDuration: filter.value?.[0], maxDuration: filter.value.length > 1 ? filter.value[1] : filter.value[0], @@ -99,6 +101,7 @@ function FilterValue(props: Props) { onSelect={(e, item, index) => debounceOnSelect(e, item, index)} icon={filter.icon} placeholder={filter.placeholder} + isAutoOpen={isAutoOpen} modalProps={{ placeholder: '' }} {...props} /> @@ -106,6 +109,7 @@ function FilterValue(props: Props) { const BaseDropDown = (props) => ( { + filter.autoOpen = true; searchStoreLive.addFilter(filter); }; diff --git a/frontend/app/components/shared/SessionFilters/SessionFilters.tsx b/frontend/app/components/shared/SessionFilters/SessionFilters.tsx index ab18384c5..4e40105ff 100644 --- a/frontend/app/components/shared/SessionFilters/SessionFilters.tsx +++ b/frontend/app/components/shared/SessionFilters/SessionFilters.tsx @@ -57,6 +57,7 @@ function SessionFilters() { }, [appliedFilter.filters]); const onAddFilter = (filter: any) => { + filter.autoOpen = true; searchStore.addFilter(filter); }; diff --git a/frontend/app/mstore/types/filter.ts b/frontend/app/mstore/types/filter.ts index ccde4e386..9bb135b2d 100644 --- a/frontend/app/mstore/types/filter.ts +++ b/frontend/app/mstore/types/filter.ts @@ -19,6 +19,7 @@ export interface IFilter { eventsHeader: string; page: number; limit: number; + autoOpen: boolean; merge(filter: any): void; @@ -62,6 +63,7 @@ export default class Filter implements IFilter { filterId: string = ''; name: string = ''; + autoOpen = false; filters: FilterItem[] = []; excludes: FilterItem[] = []; eventsOrder: string = 'then'; From adb359b3bf62bc68d03c9aeaa1416c90f3e4f905 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Mon, 17 Feb 2025 14:47:56 +0100 Subject: [PATCH 02/47] ui: reset autocomplete values with project change --- .../Filters/FilterAutoComplete/FilterAutoComplete.tsx | 7 ++++++- frontend/app/mstore/filterStore.ts | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx b/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx index f1ac440d3..8e00bcfea 100644 --- a/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx @@ -60,11 +60,16 @@ const FilterAutoComplete = observer( ); const [initialFocus, setInitialFocus] = useState(false); const [loading, setLoading] = useState(false); - const { filterStore } = useStore(); + const { filterStore, projectsStore } = useStore(); const _params = processKey(params); const filterKey = `${_params.type}${_params.key || ''}`; const topValues = filterStore.topValues[filterKey] || []; + React.useEffect(() => { + filterStore.resetValues() + setOptions([]) + }, [projectsStore.siteId]) + const loadTopValues = async () => { setLoading(true) await filterStore.fetchTopValues(_params.type, _params.key); diff --git a/frontend/app/mstore/filterStore.ts b/frontend/app/mstore/filterStore.ts index 0af2be151..eca477c79 100644 --- a/frontend/app/mstore/filterStore.ts +++ b/frontend/app/mstore/filterStore.ts @@ -23,6 +23,10 @@ export default class FilterStore { this.topValues[key] = vals?.filter((value) => value !== null && value.value !== ''); }; + resetValues = () => { + this.topValues = {}; + } + fetchTopValues = async (key: string, source?: string) => { if (this.topValues.hasOwnProperty(key)) { return Promise.resolve(this.topValues[key]); From f1614b6626d26e722b5567f50887dd6e5f2592e4 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 17 Feb 2025 15:21:37 +0100 Subject: [PATCH 03/47] feat(canvas): removed unnecessary log --- backend/cmd/canvas-handler/main.go | 5 ++++- backend/internal/canvas-handler/service.go | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/cmd/canvas-handler/main.go b/backend/cmd/canvas-handler/main.go index 568ff42e5..92666ebc7 100644 --- a/backend/cmd/canvas-handler/main.go +++ b/backend/cmd/canvas-handler/main.go @@ -4,6 +4,7 @@ import ( "context" "os" "os/signal" + "strings" "syscall" "time" @@ -58,7 +59,9 @@ func main() { if isSessionEnd(data) { if err := srv.PackSessionCanvases(sessCtx, sessID); err != nil { - log.Error(sessCtx, "can't pack session's canvases: %s", err) + if !strings.Contains(err.Error(), "no such file or directory") { + log.Error(sessCtx, "can't pack session's canvases: %s", err) + } } } else { if err := srv.SaveCanvasToDisk(sessCtx, sessID, data); err != nil { diff --git a/backend/internal/canvas-handler/service.go b/backend/internal/canvas-handler/service.go index d7e42a965..13ee46f68 100644 --- a/backend/internal/canvas-handler/service.go +++ b/backend/internal/canvas-handler/service.go @@ -80,7 +80,7 @@ func (v *ImageStorage) SaveCanvasToDisk(ctx context.Context, sessID uint64, data func (v *ImageStorage) writeToDisk(payload interface{}) { task := payload.(*saveTask) - path := fmt.Sprintf("%s/%d/", v.basePath, task.sessionID) + path := fmt.Sprintf("%s%d/", v.basePath, task.sessionID) // Ensure the directory exists if err := os.MkdirAll(path, 0755); err != nil { @@ -102,7 +102,7 @@ func (v *ImageStorage) writeToDisk(payload interface{}) { } func (v *ImageStorage) PackSessionCanvases(ctx context.Context, sessID uint64) error { - path := fmt.Sprintf("%s/%d/", v.basePath, sessID) + path := fmt.Sprintf("%s%d/", v.basePath, sessID) // Check that the directory exists files, err := os.ReadDir(path) From f8a1c9447b82b06123ecf4afec23945767d69f8c Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Mon, 17 Feb 2025 16:39:17 +0100 Subject: [PATCH 04/47] fix(frontend): fixed LAST_7_DAYS/LAST_30_DAYS/PREV_7_DAYS/PREV_30_DAYS time periods (#3036) --- frontend/app/types/app/period.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/app/types/app/period.js b/frontend/app/types/app/period.js index 50119c27d..768bca7de 100644 --- a/frontend/app/types/app/period.js +++ b/frontend/app/types/app/period.js @@ -36,12 +36,12 @@ function getRange(rangeName, offset) { ); case LAST_7_DAYS: return Interval.fromDateTimes( - now.minus({ days: 7 }).endOf("day"), + now.minus({ days: 6 }).startOf("day"), now.endOf("day") ); case LAST_30_DAYS: return Interval.fromDateTimes( - now.minus({ days: 30 }).startOf("day"), + now.minus({ days: 29 }).startOf("day"), now.endOf("day") ); case THIS_MONTH: @@ -55,12 +55,12 @@ function getRange(rangeName, offset) { return Interval.fromDateTimes(now.minus({ hours: 48 }), now.minus({ hours: 24 })); case PREV_7_DAYS: return Interval.fromDateTimes( - now.minus({ days: 14 }).startOf("day"), + now.minus({ days: 13 }).startOf("day"), now.minus({ days: 7 }).endOf("day") ); case PREV_30_DAYS: return Interval.fromDateTimes( - now.minus({ days: 60 }).startOf("day"), + now.minus({ days: 59 }).startOf("day"), now.minus({ days: 30 }).endOf("day") ); default: From 8d0c9d5a1fffb2a2f9c7298877fdf4ab593150a4 Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Mon, 17 Feb 2025 17:55:32 +0100 Subject: [PATCH 05/47] Dev (#3037) * refactor(chalice): refactored code * fix(frontend): changed LAST_7_DAYS/LAST_30_DAYS/PREV_7_DAYS/PREV_30_DAYS to return rounded boundaries --- api/chalicelib/core/sessions/sessions_ch.py | 6 ++++-- api/chalicelib/utils/helper.py | 16 ---------------- api/chalicelib/utils/metrics_helper.py | 20 ++++++++++++++++++++ frontend/app/types/app/period.js | 15 +++++++-------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/api/chalicelib/core/sessions/sessions_ch.py b/api/chalicelib/core/sessions/sessions_ch.py index 6a987a2d3..63c1c9401 100644 --- a/api/chalicelib/core/sessions/sessions_ch.py +++ b/api/chalicelib/core/sessions/sessions_ch.py @@ -121,8 +121,10 @@ def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, d s.pop("main_count") sessions = {"count": count, "values": helper.list_to_camel_case(sessions)} - return helper.complete_missing_steps(rows=sessions, start_timestamp=data.startTimestamp, - end_timestamp=data.endTimestamp, step=step_size, neutral={"count": 0}) + return metrics_helper.complete_missing_steps(rows=sessions, + start_timestamp=data.startTimestamp, + end_timestamp=data.endTimestamp, step=step_size, + neutral={"count": 0}) def search2_table(data: schemas.SessionsSearchPayloadSchema, project_id: int, density: int, diff --git a/api/chalicelib/utils/helper.py b/api/chalicelib/utils/helper.py index 6710100ba..4d0d09427 100644 --- a/api/chalicelib/utils/helper.py +++ b/api/chalicelib/utils/helper.py @@ -336,19 +336,3 @@ def cast_session_id_to_string(data): return data -from typing import List - - -def complete_missing_steps(rows: List[dict], start_timestamp: int, end_timestamp: int, step: int, neutral: dict, - time_key: str = "timestamp") -> List[dict]: - result = [] - i = 0 - for t in range(start_timestamp, end_timestamp, step): - if i >= len(rows) or rows[i][time_key] > t: - neutral[time_key] = t - result.append(neutral.copy()) - elif i < len(rows) and rows[i][time_key] == t: - result.append(rows[i]) - i += 1 - - return result diff --git a/api/chalicelib/utils/metrics_helper.py b/api/chalicelib/utils/metrics_helper.py index fa9bca6a6..a6ee927bc 100644 --- a/api/chalicelib/utils/metrics_helper.py +++ b/api/chalicelib/utils/metrics_helper.py @@ -1,7 +1,27 @@ +from typing import List + + def get_step_size(startTimestamp, endTimestamp, density, decimal=False, factor=1000): + print("-------density:") + print(density) step_size = (endTimestamp // factor - startTimestamp // factor) if density <= 1: return step_size if decimal: return step_size / density return step_size // density + + +def complete_missing_steps(rows: List[dict], start_timestamp: int, end_timestamp: int, step: int, neutral: dict, + time_key: str = "timestamp") -> List[dict]: + result = [] + i = 0 + for t in range(start_timestamp, end_timestamp, step): + print(t) + if i >= len(rows) or rows[i][time_key] > t: + neutral[time_key] = t + result.append(neutral.copy()) + elif i < len(rows) and rows[i][time_key] == t: + result.append(rows[i]) + i += 1 + return result diff --git a/frontend/app/types/app/period.js b/frontend/app/types/app/period.js index 768bca7de..e614f2dd2 100644 --- a/frontend/app/types/app/period.js +++ b/frontend/app/types/app/period.js @@ -20,12 +20,11 @@ function getRange(rangeName, offset) { const now = DateTime.now().setZone(offset); switch (rangeName) { case TODAY: - return Interval.fromDateTimes(now.startOf("day"), now.endOf("day")); + return Interval.fromDateTimes(now.startOf("day"), now.plus({ days:1 }).startOf("day")); case YESTERDAY: - const yesterday = now.minus({ days: 1 }); return Interval.fromDateTimes( - yesterday.startOf("day"), - yesterday.endOf("day") + now.minus({ days: 1 }).startOf("day"), + now.startOf("day") ); case LAST_24_HOURS: return Interval.fromDateTimes(now.minus({ hours: 24 }), now); @@ -37,12 +36,12 @@ function getRange(rangeName, offset) { case LAST_7_DAYS: return Interval.fromDateTimes( now.minus({ days: 6 }).startOf("day"), - now.endOf("day") + now.plus({ days: 1 }).startOf("day") ); case LAST_30_DAYS: return Interval.fromDateTimes( now.minus({ days: 29 }).startOf("day"), - now.endOf("day") + now.plus({ days: 1 }).startOf("day") ); case THIS_MONTH: return Interval.fromDateTimes(now.startOf("month"), now.endOf("month")); @@ -56,12 +55,12 @@ function getRange(rangeName, offset) { case PREV_7_DAYS: return Interval.fromDateTimes( now.minus({ days: 13 }).startOf("day"), - now.minus({ days: 7 }).endOf("day") + now.minus({ days: 6 }).startOf("day") ); case PREV_30_DAYS: return Interval.fromDateTimes( now.minus({ days: 59 }).startOf("day"), - now.minus({ days: 30 }).endOf("day") + now.minus({ days: 29 }).startOf("day") ); default: return Interval.fromDateTimes(now, now); From ecdb98b057f2e3fc44ce73ed161d82008a68cc68 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 17 Feb 2025 17:56:16 +0100 Subject: [PATCH 06/47] change(ui): spot menu item handle collapse --- frontend/app/layout/Layout.tsx | 2 +- frontend/app/layout/SideMenu.tsx | 57 ++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/frontend/app/layout/Layout.tsx b/frontend/app/layout/Layout.tsx index f2e753f9a..a914884a1 100644 --- a/frontend/app/layout/Layout.tsx +++ b/frontend/app/layout/Layout.tsx @@ -55,7 +55,7 @@ function Layout(props: Props) { collapsed={settingsStore.menuCollapsed || collapsed} width={250} > - + ) : null} diff --git a/frontend/app/layout/SideMenu.tsx b/frontend/app/layout/SideMenu.tsx index 7c3345b26..eed6ce9b0 100644 --- a/frontend/app/layout/SideMenu.tsx +++ b/frontend/app/layout/SideMenu.tsx @@ -1,4 +1,4 @@ -import { Divider, Menu, Tag, Typography } from 'antd'; +import { Divider, Menu, Tag, Typography, Popover, Button } from 'antd'; import cn from 'classnames'; import React from 'react'; import { RouteComponentProps, withRouter } from 'react-router-dom'; @@ -26,6 +26,7 @@ import { spotOnlyCats } from './data'; import { useStore } from 'App/mstore'; +import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; const { Text } = Typography; @@ -36,13 +37,14 @@ interface Props extends RouteComponentProps { function SideMenu(props: Props) { const { - location + location, + isCollapsed } = props; const isPreferencesActive = location.pathname.includes('/client/'); const [supportOpen, setSupportOpen] = React.useState(false); const { searchStore, projectsStore, userStore } = useStore(); - const spotOnly = userStore.scopeState === 1; + const spotOnly = true; //userStore.scopeState === 1; const account = userStore.account; const modules = account.settings?.modules ?? []; const isAdmin = account.admin || account.superAdmin; @@ -50,16 +52,6 @@ function SideMenu(props: Props) { const siteId = projectsStore.siteId; const isMobile = projectsStore.isMobile; - const [isModalVisible, setIsModalVisible] = React.useState(false); - - const handleModalOpen = () => { - setIsModalVisible(true); - }; - - const handleModalClose = () => { - setIsModalVisible(false); - }; - let menu: any[] = React.useMemo(() => { const sourceMenu = isPreferencesActive ? preferences : main_menu; @@ -151,7 +143,7 @@ function SideMenu(props: Props) { [PREFERENCES_MENU.NOTIFICATIONS]: () => client(CLIENT_TABS.NOTIFICATIONS), [PREFERENCES_MENU.BILLING]: () => client(CLIENT_TABS.BILLING), [PREFERENCES_MENU.MODULES]: () => client(CLIENT_TABS.MODULES), - [MENU.HIGHLIGHTS]: () => withSiteId(routes.highlights(''), siteId), + [MENU.HIGHLIGHTS]: () => withSiteId(routes.highlights(''), siteId) }; const handleClick = (item: any) => { @@ -326,13 +318,7 @@ function SideMenu(props: Props) { ))} {spotOnly && !isPreferencesActive ? ( - <> - - - + ) : null} setSupportOpen(false)} open={supportOpen} /> @@ -340,3 +326,32 @@ function SideMenu(props: Props) { } export default withRouter(observer(SideMenu)); + + +const SpotMenuItem = ({ isCollapsed }: any) => { + const [isModalVisible, setIsModalVisible] = React.useState(false); + + return ( + <> + setIsModalVisible(false)} + /> + {isCollapsed ? ( + setIsModalVisible(true)} />} + trigger="hover" + placement="right" + > + + + ) : ( + <> + setIsModalVisible(true)} /> + + )} + + ); +}; From 2144a90ea7ecf7cb7f93f3eb04aaab3903ebb5e0 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 17 Feb 2025 17:59:23 +0100 Subject: [PATCH 07/47] change(ui): spot menu item handle collapse --- frontend/app/layout/SideMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/layout/SideMenu.tsx b/frontend/app/layout/SideMenu.tsx index eed6ce9b0..2ce564627 100644 --- a/frontend/app/layout/SideMenu.tsx +++ b/frontend/app/layout/SideMenu.tsx @@ -44,7 +44,7 @@ function SideMenu(props: Props) { const isPreferencesActive = location.pathname.includes('/client/'); const [supportOpen, setSupportOpen] = React.useState(false); const { searchStore, projectsStore, userStore } = useStore(); - const spotOnly = true; //userStore.scopeState === 1; + const spotOnly = userStore.scopeState === 1; const account = userStore.account; const modules = account.settings?.modules ?? []; const isAdmin = account.admin || account.superAdmin; From cd5d6e861da5e28b66ea4bd68b3efb5a7232cf0b Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Tue, 18 Feb 2025 10:02:09 +0100 Subject: [PATCH 08/47] ui: fix undef component in AssistSessionsModal --- .../Player/Controls/AssistSessionsModal/AssistSessionsModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Session_/Player/Controls/AssistSessionsModal/AssistSessionsModal.tsx b/frontend/app/components/Session_/Player/Controls/AssistSessionsModal/AssistSessionsModal.tsx index 027867ed8..bd85fb1ab 100644 --- a/frontend/app/components/Session_/Player/Controls/AssistSessionsModal/AssistSessionsModal.tsx +++ b/frontend/app/components/Session_/Player/Controls/AssistSessionsModal/AssistSessionsModal.tsx @@ -7,7 +7,7 @@ import { KEYS } from 'Types/filter/customFilter'; import { capitalize } from 'App/utils'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; -import AssistSearchField from 'App/components/Assist/AssistSearchActions'; +import AssistSearchActions from 'App/components/Assist/AssistSearchActions'; import LiveSessionSearch from 'Shared/LiveSessionSearch'; import cn from 'classnames'; import Session from 'App/mstore/types/session'; From 63b6b39d757ef0bbd1fb7b052b30632719b69b61 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Tue, 18 Feb 2025 13:05:48 +0100 Subject: [PATCH 09/47] ui: fix weird dateRange interaction with time picker --- .../shared/DateRangeDropdown/DateRangePopup.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.tsx b/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.tsx index 1c73e4c3f..25f382d88 100644 --- a/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.tsx +++ b/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.tsx @@ -44,7 +44,8 @@ function DateRangePopup(props: any) { if (!range.end || value > range.end) { return; } - setRange(Interval.fromDateTimes(value, range.end)); + const newRange = range.start.set({ hour: value.hour, minute: value.minute }); + setRange(Interval.fromDateTimes(newRange, range.end)); setValue(CUSTOM_RANGE); }; @@ -52,7 +53,8 @@ function DateRangePopup(props: any) { if (!range.start || (value && value < range.start)) { return; } - setRange(Interval.fromDateTimes(range.start, value)); + const newRange = range.end.set({ hour: value.hour, minute: value.minute }); + setRange(Interval.fromDateTimes(range.start, newRange)); setValue(CUSTOM_RANGE); }; @@ -92,11 +94,6 @@ function DateRangePopup(props: any) {
onChange - // numberOfCalendars={2} - // selectionType="range" - // maximumDate={new Date()} - // singleDateRange={true} onChange={selectCustomRange} shouldCloseCalendar={() => false} isOpen From b70effa9041d37289cab01528a05f45a1496ec82 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Fri, 7 Feb 2025 11:57:31 +0100 Subject: [PATCH 10/47] chore(helm): remove clickhouse resource requests Signed-off-by: rjshrjndrn --- scripts/helmcharts/databases/charts/clickhouse/values.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/helmcharts/databases/charts/clickhouse/values.yaml b/scripts/helmcharts/databases/charts/clickhouse/values.yaml index 2e37f0d80..0d5c3daad 100644 --- a/scripts/helmcharts/databases/charts/clickhouse/values.yaml +++ b/scripts/helmcharts/databases/charts/clickhouse/values.yaml @@ -72,9 +72,9 @@ service: dataPort: 8123 resources: - requests: - cpu: 1 - memory: 4Gi + requests: {} + # cpu: 1 + # memory: 4Gi limits: {} nodeSelector: {} From 231a3ac33096321f3cc763c3123c45cdd7704f7b Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Fri, 7 Feb 2025 15:33:04 +0100 Subject: [PATCH 11/47] docs(vars): keep the ep empty for iam auth. Signed-off-by: rjshrjndrn --- scripts/helmcharts/vars.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/helmcharts/vars.yaml b/scripts/helmcharts/vars.yaml index 870325d13..43c1375dd 100644 --- a/scripts/helmcharts/vars.yaml +++ b/scripts/helmcharts/vars.yaml @@ -130,6 +130,8 @@ global: pvcRWXName: "hostPath" s3: region: "us-east-1" + # if you're using iam roles for authentication, keep the value empty. + # endpoint: "" endpoint: "http://minio.db.svc.cluster.local:9000" assetsBucket: "sessions-assets" recordingsBucket: "mobs" From b4497edb059bb608798312eb998342037cddcd33 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Tue, 18 Feb 2025 14:36:17 +0100 Subject: [PATCH 12/47] ui: preset default chart view for heatmap --- .../components/DashboardList/NewDashModal/ExampleCards.tsx | 3 ++- .../Dashboard/components/WidgetView/WidgetView.tsx | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index 70c494d29..cdc907a9f 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -87,7 +87,8 @@ export const CARD_LIST: CardType[] = [ cardType: HEATMAP, metricOf: 'heatMapUrl', category: CARD_CATEGORIES[0].key, - example: HeatmapsExample + example: HeatmapsExample, + viewType: 'chart', }, { title: 'Untitled Journey', diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx index e23abc804..480b59c52 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx @@ -68,7 +68,10 @@ function WidgetView({ match: { params: { siteId, dashboardId, metricId } } }: Pr name: selectedCard.title, metricOf: selectedCard.metricOf, category: mk, - viewType: selectedCard.viewType ? selectedCard.viewType : selectedCard.cardType === FUNNEL ? 'chart' : 'lineChart', + viewType: + selectedCard.viewType + ? selectedCard.viewType + : selectedCard.cardType === FUNNEL ? 'chart' : 'lineChart', }; if (selectedCard.filters) { cardData.series = [ From 00a834b143b1d05d26141c27b1e6c66a905b907d Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Tue, 18 Feb 2025 14:38:48 +0100 Subject: [PATCH 13/47] ui: preset default chart view for few tablelike charts --- .../components/DashboardList/NewDashModal/ExampleCards.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index cdc907a9f..17945fbfb 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -136,7 +136,8 @@ export const CARD_LIST: CardType[] = [ cardType: TABLE, metricOf: FilterKey.USERID, category: CARD_CATEGORIES[1].key, - example: ByUser + example: ByUser, + viewType: 'table', }, { @@ -145,7 +146,8 @@ export const CARD_LIST: CardType[] = [ cardType: TABLE, metricOf: FilterKey.USER_BROWSER, category: CARD_CATEGORIES[1].key, - example: ByBrowser + example: ByBrowser, + viewType: 'table', }, // { // title: 'Sessions by System', From e996600dc8160039d1b0c3845030e4edcfed08ad Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Tue, 18 Feb 2025 15:19:41 +0100 Subject: [PATCH 14/47] ui: fix data parser for heatmap --- .../Widgets/CustomMetricsWidgets/ClickMapCard/ClickMapCard.tsx | 1 - frontend/app/mstore/types/widget.ts | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/ClickMapCard/ClickMapCard.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/ClickMapCard/ClickMapCard.tsx index 1b0e35d35..3eed642e6 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/ClickMapCard/ClickMapCard.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/ClickMapCard/ClickMapCard.tsx @@ -18,7 +18,6 @@ function ClickMapCard() { const url = metricStore.instance.data.path; const operator = metricStore.instance.series[0]?.filter.filters[0]?.operator ? metricStore.instance.series[0].filter.filters[0].operator : 'startsWith' - React.useEffect(() => { return () => setCustomSession(null); }, []); diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index fef672469..abdbf400b 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -314,6 +314,7 @@ export default class Widget { } if (this.metricType === HEATMAP) { + Object.assign(this.data, data); return; } From 3ed8b3c27d00d21ae27372097a01124de6fb4504 Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Tue, 18 Feb 2025 16:37:37 +0100 Subject: [PATCH 15/47] Dev (#3041) * refactor(chalice): refactored code * refactor(DB): changed delta * refactor(chalice): product analytics log refactoring --- .../core/metrics/product_analytics_ch.py | 17 +++++++++++------ api/chalicelib/utils/metrics_helper.py | 3 --- .../db/init_dbs/postgresql/1.22.0/1.22.0.sql | 8 ++++---- .../db/init_dbs/postgresql/1.22.0/1.22.0.sql | 8 ++++---- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/api/chalicelib/core/metrics/product_analytics_ch.py b/api/chalicelib/core/metrics/product_analytics_ch.py index 3bc997525..afd3e52d3 100644 --- a/api/chalicelib/core/metrics/product_analytics_ch.py +++ b/api/chalicelib/core/metrics/product_analytics_ch.py @@ -487,10 +487,12 @@ WITH {initial_sessions_cte} SELECT * FROM pre_ranked_events;""" logger.debug("---------Q1-----------") - ch.execute(query=ch_query1, parameters=params) + ch_query1 = ch.format(query=ch_query1, parameters=params) + logger.debug(ch_query1) + ch.execute(query=ch_query1) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch.format(query=ch_query1, parameters=params)) + logger.warning(ch_query1) logger.warning("----------------------") _now = time() @@ -512,10 +514,11 @@ SELECT * FROM ranked_events {q2_extra_condition if q2_extra_condition else ""};""" logger.debug("---------Q2-----------") - ch.execute(query=ch_query2, parameters=params) + ch_query2 = ch.format(query=ch_query2, parameters=params) + ch.execute(query=ch_query2) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch.format(query=ch_query2, parameters=params)) + logger.warning(ch_query2) logger.warning("----------------------") _now = time() @@ -625,10 +628,12 @@ FROM ranked_events ) AS chart_steps ORDER BY event_number_in_session, sessions_count DESC;""" logger.debug("---------Q3-----------") - rows = ch.execute(query=ch_query3, parameters=params) + ch_query3 = ch.format(query=ch_query3, parameters=params) + logger.debug(ch_query3) + rows = ch.execute(query=ch_query3) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch.format(query=ch_query3, parameters=params)) + logger.warning(ch_query3) logger.warning("----------------------") return __transform_journey(rows=rows, reverse_path=reverse) diff --git a/api/chalicelib/utils/metrics_helper.py b/api/chalicelib/utils/metrics_helper.py index a6ee927bc..7bf9c94f8 100644 --- a/api/chalicelib/utils/metrics_helper.py +++ b/api/chalicelib/utils/metrics_helper.py @@ -2,8 +2,6 @@ from typing import List def get_step_size(startTimestamp, endTimestamp, density, decimal=False, factor=1000): - print("-------density:") - print(density) step_size = (endTimestamp // factor - startTimestamp // factor) if density <= 1: return step_size @@ -17,7 +15,6 @@ def complete_missing_steps(rows: List[dict], start_timestamp: int, end_timestamp result = [] i = 0 for t in range(start_timestamp, end_timestamp, step): - print(t) if i >= len(rows) or rows[i][time_key] > t: neutral[time_key] = t result.append(neutral.copy()) diff --git a/ee/scripts/schema/db/init_dbs/postgresql/1.22.0/1.22.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.22.0/1.22.0.sql index d7ed6c5ba..fbedb48a0 100644 --- a/ee/scripts/schema/db/init_dbs/postgresql/1.22.0/1.22.0.sql +++ b/ee/scripts/schema/db/init_dbs/postgresql/1.22.0/1.22.0.sql @@ -27,10 +27,10 @@ DROP TABLE IF EXISTS public.user_favorite_errors; DROP TABLE IF EXISTS public.user_viewed_errors; ALTER TABLE IF EXISTS public.sessions_notes - ADD COLUMN start_at integer, - ADD COLUMN end_at integer, - ADD COLUMN thumbnail text, - ADD COLUMN updated_at timestamp DEFAULT NULL, + ADD COLUMN IF NOT EXISTS start_at integer, + ADD COLUMN IF NOT EXISTS end_at integer, + ADD COLUMN IF NOT EXISTS thumbnail text, + ADD COLUMN IF NOT EXISTS updated_at timestamp DEFAULT NULL, ALTER COLUMN message DROP NOT NULL; DELETE diff --git a/scripts/schema/db/init_dbs/postgresql/1.22.0/1.22.0.sql b/scripts/schema/db/init_dbs/postgresql/1.22.0/1.22.0.sql index 340929e68..a08ba5048 100644 --- a/scripts/schema/db/init_dbs/postgresql/1.22.0/1.22.0.sql +++ b/scripts/schema/db/init_dbs/postgresql/1.22.0/1.22.0.sql @@ -27,10 +27,10 @@ DROP TABLE IF EXISTS public.user_favorite_errors; DROP TABLE IF EXISTS public.user_viewed_errors; ALTER TABLE IF EXISTS public.sessions_notes - ADD COLUMN start_at integer, - ADD COLUMN end_at integer, - ADD COLUMN thumbnail text, - ADD COLUMN updated_at timestamp DEFAULT NULL, + ADD COLUMN IF NOT EXISTS start_at integer, + ADD COLUMN IF NOT EXISTS end_at integer, + ADD COLUMN IF NOT EXISTS thumbnail text, + ADD COLUMN IF NOT EXISTS updated_at timestamp DEFAULT NULL, ALTER COLUMN message DROP NOT NULL; DELETE From e046bcbe0a6aa2e0ed8ca300823511d3526cbac6 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 18 Feb 2025 17:32:12 +0100 Subject: [PATCH 16/47] feat(go.mod): upgraded CH library version --- backend/go.mod | 12 ++++++------ backend/go.sum | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/backend/go.mod b/backend/go.mod index 4046f8136..995f0ae2b 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -5,7 +5,7 @@ go 1.23 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 - github.com/ClickHouse/clickhouse-go/v2 v2.30.1 + github.com/ClickHouse/clickhouse-go/v2 v2.32.1 github.com/DataDog/datadog-api-client-go/v2 v2.34.0 github.com/Masterminds/semver v1.5.0 github.com/andybalholm/brotli v1.1.1 @@ -36,12 +36,12 @@ require ( github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce github.com/ua-parser/uap-go v0.0.0-20250126222208-a52596c19dff go.uber.org/zap v1.27.0 - golang.org/x/net v0.34.0 + golang.org/x/net v0.35.0 ) require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect - github.com/ClickHouse/ch-go v0.63.1 // indirect + github.com/ClickHouse/ch-go v0.65.0 // indirect github.com/DataDog/zstd v1.5.6 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -77,10 +77,10 @@ require ( go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.32.0 // indirect + golang.org/x/crypto v0.33.0 // indirect golang.org/x/oauth2 v0.25.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287 // indirect google.golang.org/protobuf v1.36.4 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/backend/go.sum b/backend/go.sum index d4180aaf2..f31efe937 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -24,8 +24,10 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5g github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/ClickHouse/ch-go v0.63.1 h1:s2JyZvWLTCSAGdtjMBBmAgQQHMco6pawLJMOXi0FODM= github.com/ClickHouse/ch-go v0.63.1/go.mod h1:I1kJJCL3WJcBMGe1m+HVK0+nREaG+JOYYBWjrDrF3R0= +github.com/ClickHouse/ch-go v0.65.0/go.mod h1:tCM0XEH5oWngoi9Iu/8+tjPBo04I/FxNIffpdjtwx3k= github.com/ClickHouse/clickhouse-go/v2 v2.30.1 h1:Dy0n0l+cMbPXs8hFkeeWGaPKrB+MDByUNQBSmRO3W6k= github.com/ClickHouse/clickhouse-go/v2 v2.30.1/go.mod h1:szk8BMoQV/NgHXZ20ZbwDyvPWmpfhRKjFkc6wzASGxM= +github.com/ClickHouse/clickhouse-go/v2 v2.32.1/go.mod h1:YtaiIFlHCGNPbOpAvFGYobtcVnmgYvD/WmzitixxWYc= github.com/DataDog/datadog-api-client-go/v2 v2.34.0 h1:0VVmv8uZg8vdBuEpiF2nBGUezl2QITrxdEsLgh38j8M= github.com/DataDog/datadog-api-client-go/v2 v2.34.0/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= @@ -618,6 +620,7 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -642,6 +645,7 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -676,6 +680,7 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -695,6 +700,7 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From f752876675281481dea6e92f7118d4d6dc03cccc Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Tue, 18 Feb 2025 18:00:49 +0100 Subject: [PATCH 17/47] refactor(chalice): product analytics log refactoring (#3043) --- api/chalicelib/core/metrics/product_analytics_ch.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/api/chalicelib/core/metrics/product_analytics_ch.py b/api/chalicelib/core/metrics/product_analytics_ch.py index afd3e52d3..8425e7a77 100644 --- a/api/chalicelib/core/metrics/product_analytics_ch.py +++ b/api/chalicelib/core/metrics/product_analytics_ch.py @@ -488,11 +488,11 @@ SELECT * FROM pre_ranked_events;""" logger.debug("---------Q1-----------") ch_query1 = ch.format(query=ch_query1, parameters=params) - logger.debug(ch_query1) + logger.debug(ch_query1.encode('utf-8')) ch.execute(query=ch_query1) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch_query1) + logger.warning(ch_query1.encode('utf-8')) logger.warning("----------------------") _now = time() @@ -515,10 +515,11 @@ FROM ranked_events {q2_extra_condition if q2_extra_condition else ""};""" logger.debug("---------Q2-----------") ch_query2 = ch.format(query=ch_query2, parameters=params) + logger.debug(ch_query2.encode('utf-8')) ch.execute(query=ch_query2) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch_query2) + logger.warning(ch_query2.encode('utf-8')) logger.warning("----------------------") _now = time() @@ -629,11 +630,11 @@ FROM ranked_events ORDER BY event_number_in_session, sessions_count DESC;""" logger.debug("---------Q3-----------") ch_query3 = ch.format(query=ch_query3, parameters=params) - logger.debug(ch_query3) + logger.debug(ch_query3.encode('utf-8')) rows = ch.execute(query=ch_query3) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch_query3) + logger.warning(ch_query3.encode('utf-8')) logger.warning("----------------------") return __transform_journey(rows=rows, reverse_path=reverse) From def33daa6ccf7f3b901b63933876b0301aac6247 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Tue, 18 Feb 2025 18:18:34 +0100 Subject: [PATCH 18/47] fix(backend): go sum --- backend/go.sum | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/backend/go.sum b/backend/go.sum index f31efe937..46e8a1bbc 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -12,21 +12,20 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xP github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 h1:mlmW46Q0B79I+Aj4azKC6xDMFN9a9SyZWESlGWYXbFs= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0/go.mod h1:PXe2h+LKcWTX9afWdZoHyODqR4fBa5boUM/8uJfZ0Jo= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 h1:UXT0o77lXQrikd1kgwIPQOUect7EoR/+sbP4wQKdzxM= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0/go.mod h1:cTvi54pg19DoT07ekoeMgE/taAwNtCShVeZqA+Iv2xI= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/ClickHouse/ch-go v0.63.1 h1:s2JyZvWLTCSAGdtjMBBmAgQQHMco6pawLJMOXi0FODM= github.com/ClickHouse/ch-go v0.63.1/go.mod h1:I1kJJCL3WJcBMGe1m+HVK0+nREaG+JOYYBWjrDrF3R0= +github.com/ClickHouse/ch-go v0.65.0 h1:vZAXfTQliuNNefqkPDewX3kgRxN6Q4vUENnnY+ynTRY= github.com/ClickHouse/ch-go v0.65.0/go.mod h1:tCM0XEH5oWngoi9Iu/8+tjPBo04I/FxNIffpdjtwx3k= github.com/ClickHouse/clickhouse-go/v2 v2.30.1 h1:Dy0n0l+cMbPXs8hFkeeWGaPKrB+MDByUNQBSmRO3W6k= github.com/ClickHouse/clickhouse-go/v2 v2.30.1/go.mod h1:szk8BMoQV/NgHXZ20ZbwDyvPWmpfhRKjFkc6wzASGxM= +github.com/ClickHouse/clickhouse-go/v2 v2.32.1 h1:RLhkxA6iH/bLTXeDtEj/u4yUx9Q03Y95P+cjHScQK78= github.com/ClickHouse/clickhouse-go/v2 v2.32.1/go.mod h1:YtaiIFlHCGNPbOpAvFGYobtcVnmgYvD/WmzitixxWYc= github.com/DataDog/datadog-api-client-go/v2 v2.34.0 h1:0VVmv8uZg8vdBuEpiF2nBGUezl2QITrxdEsLgh38j8M= github.com/DataDog/datadog-api-client-go/v2 v2.34.0/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= @@ -200,8 +199,6 @@ github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= -github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= @@ -529,8 +526,6 @@ github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/ github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Qb2z5hI1UHxSQt4JMyxebFR15KnApw= github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= -github.com/ua-parser/uap-go v0.0.0-20241012191800-bbb40edc15aa h1:VzPR4xFM7HARqNocjdHg75ZL9SAgFtaF3P57ZdDcG6I= -github.com/ua-parser/uap-go v0.0.0-20241012191800-bbb40edc15aa/go.mod h1:BUbeWZiieNxAuuADTBNb3/aeje6on3DhU3rpWsQSB1E= github.com/ua-parser/uap-go v0.0.0-20250126222208-a52596c19dff h1:NwMEGwb7JJ8wPjT8OPKP5hO1Xz6AQ7Z00+GLSJfW21s= github.com/ua-parser/uap-go v0.0.0-20250126222208-a52596c19dff/go.mod h1:BUbeWZiieNxAuuADTBNb3/aeje6on3DhU3rpWsQSB1E= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -620,6 +615,7 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= @@ -680,6 +676,7 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -700,6 +697,7 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= @@ -726,16 +724,12 @@ google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa h1:ePqxpG3LVx+feAU google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:CnZenrTdRJb7jc+jOm0Rkywq+9wh0QC4U8tyiRbEPPM= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287 h1:J1H9f+LEdWAfHcez/4cvaVBox7cOYT+IU6rgqj5x++8= google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk= google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= From 4970bc365bbf7a37fde0aabdf514df236c6c1a5f Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Tue, 18 Feb 2025 18:28:30 +0100 Subject: [PATCH 19/47] fix(chalice): fixed product analytics query issue for old CH version (#3044) --- api/chalicelib/core/metrics/product_analytics_ch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/chalicelib/core/metrics/product_analytics_ch.py b/api/chalicelib/core/metrics/product_analytics_ch.py index 8425e7a77..c19542ede 100644 --- a/api/chalicelib/core/metrics/product_analytics_ch.py +++ b/api/chalicelib/core/metrics/product_analytics_ch.py @@ -428,7 +428,7 @@ def path_analysis(project_id: int, data: schemas.CardPathAnalysis): SELECT event_number_in_session, `$event_name`, e_value, - SUM(sessions_count) AS sessions_count + SUM(n{i}.sessions_count) AS sessions_count FROM n{i} GROUP BY event_number_in_session, `$event_name`, e_value ORDER BY sessions_count DESC @@ -594,7 +594,7 @@ FROM ranked_events NULL AS e_value, 'OTHER' AS next_type, NULL AS next_value, - SUM(sessions_count) AS sessions_count + SUM(others_n.sessions_count) AS sessions_count FROM others_n WHERE isNotNull(others_n.next_type) AND others_n.event_number_in_session < %(density)s From 963c8354c6c47b74475d49840339df2c4eda227d Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Wed, 19 Feb 2025 09:27:00 +0100 Subject: [PATCH 20/47] ui: fix playlink hover state --- .../shared/SessionItem/PlayLink/PlayLink.tsx | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx b/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx index deab8d8a4..f9d322606 100644 --- a/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx +++ b/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx @@ -12,10 +12,9 @@ import { useStore } from 'App/mstore'; const PLAY_ICON_NAMES = { notPlayed: 'play-fill', played: 'play-circle-light', - hovered: 'play-hover', } as const -const getDefaultIconName = (isViewed: any) => +const getIconName = (isViewed: any) => !isViewed ? PLAY_ICON_NAMES.notPlayed : PLAY_ICON_NAMES.played; interface Props { @@ -33,15 +32,13 @@ function PlayLink(props: Props) { const { projectsStore } = useStore(); const { isAssist, viewed, sessionId, onClick = null, queryParams } = props; const history = useHistory(); - const defaultIconName = getDefaultIconName(viewed); + const defaultIconName = getIconName(viewed); - const [isHovered, toggleHover] = useState(false); const [iconName, setIconName] = useState(defaultIconName); useEffect(() => { - if (isHovered) setIconName(PLAY_ICON_NAMES.hovered); - else setIconName(getDefaultIconName(viewed)); - }, [isHovered, viewed]); + setIconName(getIconName(viewed)); + }, [viewed]); const link = isAssist ? liveSessionRoute(sessionId, queryParams) @@ -68,22 +65,20 @@ function PlayLink(props: Props) { const onLinkClick = props.beforeOpen ? handleBeforeOpen : onClick; - const onLeave = () => { - toggleHover(false); - }; - const onOver = () => { - toggleHover(true); - }; return ( - +
+ +
+
+ +
); } From 346fd76ea88b8ecd07bb3c39786a9ca4e4535d25 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Wed, 19 Feb 2025 10:48:29 +0100 Subject: [PATCH 21/47] chore(db): Update min CH version --- scripts/helmcharts/databases/values.yaml | 2 +- scripts/helmcharts/openreplay/templates/job.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/helmcharts/databases/values.yaml b/scripts/helmcharts/databases/values.yaml index f1df0ece2..16ef521bf 100644 --- a/scripts/helmcharts/databases/values.yaml +++ b/scripts/helmcharts/databases/values.yaml @@ -166,7 +166,7 @@ kafka: # Enterprise dbs clickhouse: image: - tag: "24.12-alpine" + tag: "25.1-alpine" enabled: false postgreql: diff --git a/scripts/helmcharts/openreplay/templates/job.yaml b/scripts/helmcharts/openreplay/templates/job.yaml index a094f8951..0aa71f332 100644 --- a/scripts/helmcharts/openreplay/templates/job.yaml +++ b/scripts/helmcharts/openreplay/templates/job.yaml @@ -227,8 +227,8 @@ spec: - -c args: - | - lowVersion=24.9 - highVersion=24 + lowVersion=25.1 + highVersion=25 [[ "${CH_PASSWORD}" == "" ]] || { CH_PASSWORD="--password $CH_PASSWORD" } From af5d7300281b2362e00fafb211870b24bbdf675a Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Wed, 19 Feb 2025 11:37:06 +0100 Subject: [PATCH 22/47] fix(backend): go sum --- backend/go.sum | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/go.sum b/backend/go.sum index 46e8a1bbc..4ecc6225b 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -641,6 +641,7 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= From 659aa7495ff352403f7394341dce81b27921aeb7 Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Wed, 19 Feb 2025 13:48:44 +0100 Subject: [PATCH 23/47] fix(chalice): fixed assist record (#3045) --- ee/api/routers/ee.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ee/api/routers/ee.py b/ee/api/routers/ee.py index 2b8ba0f37..2b7f51ead 100644 --- a/ee/api/routers/ee.py +++ b/ee/api/routers/ee.py @@ -1,6 +1,7 @@ from typing import Optional -from chalicelib.core import roles, traces, assist_records, sessions +from chalicelib.core import roles, traces, assist_records +from chalicelib.core.sessions import sessions from chalicelib.core import assist_stats from chalicelib.core import unlock, signals from chalicelib.utils import assist_helper From 0a4379be6b73d3e064d1201de7884b49ad3971fe Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 11:30:47 +0100 Subject: [PATCH 24/47] ui: fix heatmap expand state --- .../Dashboard/components/FilterSeries/FilterSeries.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index 0844e6259..fa9249183 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -143,7 +143,7 @@ function FilterSeries(props: Props) { onToggleCollapse, excludeCategory } = props; - const expanded = !collapseState + const expanded = isHeatmap || !collapseState const setExpanded = onToggleCollapse const { series, seriesIndex } = props; From 11824d2993a71e07ef9492e5eafc6d29e0c40870 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 11:40:35 +0100 Subject: [PATCH 25/47] ui: set empty defaults for clickmap --- frontend/app/mstore/types/widget.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index abdbf400b..abe3552f3 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -314,6 +314,19 @@ export default class Widget { } if (this.metricType === HEATMAP) { + const defaults = { + domURL: undefined, + duration: 0, + events: [], + mobsUrl: [], + path: '', + projectId: 0, + sessionId: null, + startTs: 0 + }; + if (!data || !data.domURL) { + this.data = defaults; + } Object.assign(this.data, data); return; } From 2465029a6cdab29f43c5efd7f985870dc08e784f Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 12:01:06 +0100 Subject: [PATCH 26/47] ui: remove broken sank tooltip row --- frontend/app/components/Charts/SankeyChart.tsx | 2 +- frontend/app/components/Charts/sankeyUtils.ts | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/frontend/app/components/Charts/SankeyChart.tsx b/frontend/app/components/Charts/SankeyChart.tsx index 48c508e88..f26131981 100644 --- a/frontend/app/components/Charts/SankeyChart.tsx +++ b/frontend/app/components/Charts/SankeyChart.tsx @@ -172,7 +172,7 @@ const EChartsSankey: React.FC = (props) => { params.name.slice(-(maxLen / 2 - 2)) : params.name; const nodeType = params.data.type; - + const icon = getIcon(nodeType) return ( `${icon}{header|${safeName}}\n` + diff --git a/frontend/app/components/Charts/sankeyUtils.ts b/frontend/app/components/Charts/sankeyUtils.ts index 78f044d58..92997f223 100644 --- a/frontend/app/components/Charts/sankeyUtils.ts +++ b/frontend/app/components/Charts/sankeyUtils.ts @@ -4,19 +4,12 @@ export function sankeyTooltip(echartNodes: any[], nodeValues: number[]) { if ('source' in params.data && 'target' in params.data) { const sourceName = echartNodes[params.data.source].name; const targetName = echartNodes[params.data.target].name; - const sourceValue = nodeValues[params.data.source]; return `
- ${sourceName} -
-
- ${sourceValue} Sessions -
-
- ${targetName} + ${sourceName} ${targetName}
${params.data.value} ( ${params.data.percentage.toFixed(2)}% ) From 6c7880efbc1858b911e2779476c294f03da63c53 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 12:05:29 +0100 Subject: [PATCH 27/47] ui: dissallow taint for clickmap thumbnails --- .../app/components/Dashboard/components/WidgetForm/renderMap.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/app/components/Dashboard/components/WidgetForm/renderMap.ts b/frontend/app/components/Dashboard/components/WidgetForm/renderMap.ts index c2cc128ac..cdc10d353 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/renderMap.ts +++ b/frontend/app/components/Dashboard/components/WidgetForm/renderMap.ts @@ -9,6 +9,8 @@ export const renderClickmapThumbnail = () => { return html2canvas( element, { + allowTaint: false, + logging: true, scale: 1, // allowTaint: true, useCORS: true, From f8a40fd87578d7748826203fe527b07874f372fe Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 12:18:03 +0100 Subject: [PATCH 28/47] ui: dissallow taint for clickmap thumbnails --- .../components/Dashboard/components/WidgetView/CardViewMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx b/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx index 5d3911320..05502ebcd 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx @@ -36,7 +36,7 @@ const CardViewMenu = () => { key: 'alert', label: 'Set Alerts', icon: , - disabled: !widget.exists() || widget.metricType === 'predefined', + disabled: !widget.exists() || widget.metricType !== 'timeseries', onClick: showAlertModal, }, { From 724d5a28972bf83c1ae815b3a066488b702607ec Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Thu, 20 Feb 2025 13:30:36 +0100 Subject: [PATCH 29/47] Dev (#3046) * refactor(chalice): upgraded dependencies * refactor(chalice): changed logging * fix(chalice): fixed CH pagination --- api/chalicelib/core/metrics/product_analytics_ch.py | 9 +++------ api/chalicelib/core/sessions/sessions_ch.py | 6 +++--- api/chalicelib/utils/ch_client_exp.py | 2 +- ee/api/Pipfile | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/api/chalicelib/core/metrics/product_analytics_ch.py b/api/chalicelib/core/metrics/product_analytics_ch.py index c19542ede..44c94952e 100644 --- a/api/chalicelib/core/metrics/product_analytics_ch.py +++ b/api/chalicelib/core/metrics/product_analytics_ch.py @@ -488,11 +488,10 @@ SELECT * FROM pre_ranked_events;""" logger.debug("---------Q1-----------") ch_query1 = ch.format(query=ch_query1, parameters=params) - logger.debug(ch_query1.encode('utf-8')) ch.execute(query=ch_query1) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch_query1.encode('utf-8')) + logger.warning(str.encode(ch_query1)) logger.warning("----------------------") _now = time() @@ -515,11 +514,10 @@ FROM ranked_events {q2_extra_condition if q2_extra_condition else ""};""" logger.debug("---------Q2-----------") ch_query2 = ch.format(query=ch_query2, parameters=params) - logger.debug(ch_query2.encode('utf-8')) ch.execute(query=ch_query2) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch_query2.encode('utf-8')) + logger.warning(str.encode(ch_query2)) logger.warning("----------------------") _now = time() @@ -630,11 +628,10 @@ FROM ranked_events ORDER BY event_number_in_session, sessions_count DESC;""" logger.debug("---------Q3-----------") ch_query3 = ch.format(query=ch_query3, parameters=params) - logger.debug(ch_query3.encode('utf-8')) rows = ch.execute(query=ch_query3) if time() - _now > 2: logger.warning(f">>>>>>>>>PathAnalysis long query EE ({int(time() - _now)}s)<<<<<<<<<") - logger.warning(ch_query3.encode('utf-8')) + logger.warning(str.encode(ch_query3)) logger.warning("----------------------") return __transform_journey(rows=rows, reverse_path=reverse) diff --git a/api/chalicelib/core/sessions/sessions_ch.py b/api/chalicelib/core/sessions/sessions_ch.py index 63c1c9401..91fe824c7 100644 --- a/api/chalicelib/core/sessions/sessions_ch.py +++ b/api/chalicelib/core/sessions/sessions_ch.py @@ -244,7 +244,7 @@ def search2_table(data: schemas.SessionsSearchPayloadSchema, project_id: int, de {extra_where} GROUP BY {main_col} ORDER BY total DESC - LIMIT %(limit_e)s OFFSET %(limit_s)s;""" + LIMIT %(limit)s OFFSET %(limit_s)s;""" else: main_query = f"""SELECT COUNT(DISTINCT {main_col}) OVER () AS main_count, {main_col} AS name, @@ -257,13 +257,13 @@ def search2_table(data: schemas.SessionsSearchPayloadSchema, project_id: int, de {extra_where} GROUP BY {main_col} ORDER BY total DESC - LIMIT %(limit_e)s OFFSET %(limit_s)s;""" + LIMIT %(limit)s OFFSET %(limit_s)s;""" main_query = cur.format(query=main_query, parameters=full_args) logging.debug("--------------------") logging.debug(main_query) logging.debug("--------------------") - sessions = cur.execute(main_query) + sessions = cur.execute(query=main_query) count = 0 total = 0 if len(sessions) > 0: diff --git a/api/chalicelib/utils/ch_client_exp.py b/api/chalicelib/utils/ch_client_exp.py index f91b0361e..f0d631420 100644 --- a/api/chalicelib/utils/ch_client_exp.py +++ b/api/chalicelib/utils/ch_client_exp.py @@ -34,7 +34,7 @@ if config("CH_COMPRESSION", cast=bool, default=True): def transform_result(self, original_function): @wraps(original_function) def wrapper(*args, **kwargs): - logger.debug(self.format(query=kwargs.get("query"), parameters=kwargs.get("parameters"))) + logger.debug(str.encode(self.format(query=kwargs.get("query", ""), parameters=kwargs.get("parameters")))) result = original_function(*args, **kwargs) if isinstance(result, clickhouse_connect.driver.query.QueryResult): column_names = result.column_names diff --git a/ee/api/Pipfile b/ee/api/Pipfile index 2b640c877..46f4da33e 100644 --- a/ee/api/Pipfile +++ b/ee/api/Pipfile @@ -9,7 +9,7 @@ requests = "==2.32.3" boto3 = "==1.36.12" pyjwt = "==2.10.1" psycopg2-binary = "==2.9.10" -psycopg = {extras = ["binary", "pool"], version = "==3.2.4"} +psycopg = {extras = ["pool", "binary"], version = "==3.2.4"} clickhouse-driver = {extras = ["lz4"], version = "==0.2.9"} clickhouse-connect = "==0.8.15" elasticsearch = "==8.17.1" From 305c7ae06483c40870e7238f962de91ecc743b82 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 14:21:51 +0100 Subject: [PATCH 30/47] ui: fix hasChanged flag, fix auto height for sankey --- frontend/app/components/Charts/SankeyChart.tsx | 4 ++-- frontend/app/mstore/types/widget.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/Charts/SankeyChart.tsx b/frontend/app/components/Charts/SankeyChart.tsx index f26131981..9a31916d9 100644 --- a/frontend/app/components/Charts/SankeyChart.tsx +++ b/frontend/app/components/Charts/SankeyChart.tsx @@ -415,7 +415,7 @@ const EChartsSankey: React.FC = (props) => { const dynamicMinHeight = finalNodeCount * 15; containerStyle = { width: '100%', - minHeight: dynamicMinHeight, + minHeight: Math.max(550, dynamicMinHeight), height: '100%', overflowY: 'auto', }; @@ -427,7 +427,7 @@ const EChartsSankey: React.FC = (props) => { } return ( -
+
{ this.startPoint = new FilterItem(startPoint); + this.hasChanged = true; }); } From aa07d41bb57ff686a86ce7f4d53fdd51ea23ecd3 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 14:47:58 +0100 Subject: [PATCH 31/47] ui: merge startpoint with widgetsessions mapper --- .../components/WidgetSessions/WidgetSessions.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx index 2e5e20ba1..08282bc67 100644 --- a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx +++ b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx @@ -11,7 +11,7 @@ import { debounce } from 'App/utils'; import useIsMounted from 'App/hooks/useIsMounted'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import { numberWithCommas } from 'App/utils'; -import { HEATMAP } from 'App/constants/card'; +import { HEATMAP, USER_PATH } from "App/constants/card"; interface Props { className?: string; @@ -107,10 +107,15 @@ function WidgetSessions(props: Props) { }; debounceClickMapSearch(customFilter); } else { - const usedSeries = focusedSeries ? widget.series.filter((s) => s.name === focusedSeries) : widget.series; + const hasStartPoint = !!widget.startPoint && widget.metricType === USER_PATH + const activeSeries = focusedSeries ? widget.series.filter((s) => s.name === focusedSeries) : widget.series + const seriesJson = activeSeries.map((s) => s.toJson()); + if (hasStartPoint) { + seriesJson[0].filter.filters.push(widget.startPoint.toJson()); + } debounceRequest(widget.metricId, { ...filter, - series: usedSeries.map((s) => s.toJson()), + series: seriesJson, page: metricStore.sessionsPage, limit: metricStore.sessionsPageSize }); @@ -125,7 +130,8 @@ function WidgetSessions(props: Props) { filter.filters, depsString, metricStore.clickMapSearch, - focusedSeries + focusedSeries, + widget.startPoint, ]); useEffect(loadData, [metricStore.sessionsPage]); useEffect(() => { From 7cfe29adf3900ef1b6cdc5b9e07ed7f9ce581b53 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 20 Feb 2025 15:31:19 +0100 Subject: [PATCH 32/47] change(ui): remove segments for mobile since it has only one category --- .../components/AddCardSection/AddCardSection.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx b/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx index 751d7505d..6781aeedb 100644 --- a/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx +++ b/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx @@ -289,11 +289,13 @@ const AddCardSection = observer( ) : null}
- setTab(value)} - /> + {options.length > 1 ? ( + setTab(value)} + /> + ) : null}
From 3e1f073e077caf9fac24b5718d74a89b896b0874 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 15:39:37 +0100 Subject: [PATCH 33/47] ui: fix subcat for heatmap --- frontend/app/mstore/types/filterItem.ts | 3 +++ frontend/app/types/filter/newFilter.js | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/app/mstore/types/filterItem.ts b/frontend/app/mstore/types/filterItem.ts index 18716fb55..31f7ff94f 100644 --- a/frontend/app/mstore/types/filterItem.ts +++ b/frontend/app/mstore/types/filterItem.ts @@ -11,6 +11,7 @@ import { pageUrlOperators } from '../../constants/filterOptions'; export default class FilterItem { type: string = ''; category: FilterCategory = FilterCategory.METADATA; + subCategory: string = ''; key: string = ''; label: string = ''; value: any = ['']; @@ -63,6 +64,7 @@ export default class FilterItem { this.operatorOptions = data.operatorOptions; this.hasSource = data.hasSource; this.category = data.category; + this.subCategory = data.subCategory; this.sourceOperatorOptions = data.sourceOperatorOptions; this.value = data.value; this.isEvent = Boolean(data.isEvent); @@ -109,6 +111,7 @@ export default class FilterItem { this.operatorOptions = _filter.operatorOptions; this.hasSource = _filter.hasSource; this.category = _filter.category; + this.subCategory = _filter.subCategory; this.sourceOperatorOptions = _filter.sourceOperatorOptions; if (isHeatmap && this.key === FilterKey.LOCATION) { this.operatorOptions = pageUrlOperators; diff --git a/frontend/app/types/filter/newFilter.js b/frontend/app/types/filter/newFilter.js index 8ae2b0019..345bbeaa9 100644 --- a/frontend/app/types/filter/newFilter.js +++ b/frontend/app/types/filter/newFilter.js @@ -902,7 +902,8 @@ export const clickmapFilter = { type: FilterType.MULTIPLE, category: FilterCategory.EVENTS, subCategory: FilterCategory.AUTOCAPTURE, - label: 'Visited URL', placeholder: 'Enter URL or path', + label: 'Visited URL', + placeholder: 'Enter URL or path', operator: filterOptions.pageUrlOperators[0].value, operatorOptions: filterOptions.pageUrlOperators, icon: 'filters/location', From 1293cbde7df3425c84b0acfd945aea7c65f511d4 Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Thu, 20 Feb 2025 16:21:08 +0100 Subject: [PATCH 34/47] fix(chalice): fixed cards different viewTypes (#3047) --- api/schemas/schemas.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/api/schemas/schemas.py b/api/schemas/schemas.py index 51d8660e1..0065836c5 100644 --- a/api/schemas/schemas.py +++ b/api/schemas/schemas.py @@ -851,18 +851,21 @@ class MetricTimeseriesViewType(str, Enum): LINE_CHART = "lineChart" AREA_CHART = "areaChart" BAR_CHART = "barChart" - PIE_CHART = "pieChart" PROGRESS_CHART = "progressChart" - TABLE_CHART = "table" + PIE_CHART = "pieChart" METRIC_CHART = "metric" + TABLE_CHART = "table" class MetricTableViewType(str, Enum): - TABLE = "table" + TABLE_CHART = "table" class MetricOtherViewType(str, Enum): OTHER_CHART = "chart" + COLUMN_CHART = "columnChart" + METRIC_CHART = "metric" + TABLE_CHART = "table" LIST_CHART = "list" @@ -876,8 +879,6 @@ class MetricType(str, Enum): HEAT_MAP = "heatMap" - - class MetricOfTable(str, Enum): USER_BROWSER = FilterType.USER_BROWSER.value USER_DEVICE = FilterType.USER_DEVICE.value @@ -1086,7 +1087,7 @@ class CardFunnel(__CardSchema): def __enforce_default(cls, values): if values.get("metricOf") and not MetricOfFunnels.has_value(values["metricOf"]): values["metricOf"] = MetricOfFunnels.SESSION_COUNT - values["viewType"] = MetricOtherViewType.OTHER_CHART + # values["viewType"] = MetricOtherViewType.OTHER_CHART if values.get("series") is not None and len(values["series"]) > 0: values["series"] = [values["series"][0]] return values From b86e6fdadcc7a665363120780bd021ce80dd7c07 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 17:07:48 +0100 Subject: [PATCH 35/47] ui: add sankey link sourceValue to chart tooltip --- .../app/components/Charts/SankeyChart.tsx | 22 ++++++++-- frontend/app/components/Charts/sankeyUtils.ts | 44 ++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/frontend/app/components/Charts/SankeyChart.tsx b/frontend/app/components/Charts/SankeyChart.tsx index 9a31916d9..0fdb38592 100644 --- a/frontend/app/components/Charts/SankeyChart.tsx +++ b/frontend/app/components/Charts/SankeyChart.tsx @@ -77,13 +77,18 @@ const EChartsSankey: React.FC = (props) => { }); setFinalNodeCount(filteredNodes.length); - + const nodeValues: Record = {}; const echartNodes = filteredNodes - .map((n) => { + .map((n, i) => { let computedName = getNodeName(n.eventType || 'Minor Paths', n.name); if (computedName === 'Other') { computedName = 'Others'; } + if (n.id) { + nodeValues[n.id] = 0; + } else { + nodeValues[i] = 0; + } const itemColor = computedName === 'Others' ? 'rgba(34,44,154,.9)' @@ -124,6 +129,17 @@ const EChartsSankey: React.FC = (props) => { .filter((link) => link.source === 0) .reduce((sum, link) => sum + link.value, 0); + Object.keys(nodeValues).forEach((nodeId) => { + const intId = parseInt(nodeId as string); + const outgoingValues = echartLinks + .filter((l) => l.source === intId) + .reduce((p, c) => p + c.value, 0); + const incomingValues = echartLinks + .filter((l) => l.target === intId) + .reduce((p, c) => p + c.value, 0); + nodeValues[nodeId] = Math.max(outgoingValues, incomingValues); + }); + const option = { ...defaultOptions, tooltip: { @@ -237,7 +253,7 @@ const EChartsSankey: React.FC = (props) => { }, }, tooltip: { - formatter: sankeyTooltip(echartNodes, []), + formatter: sankeyTooltip(echartNodes, nodeValues), }, nodeAlign: 'left', nodeWidth: 40, diff --git a/frontend/app/components/Charts/sankeyUtils.ts b/frontend/app/components/Charts/sankeyUtils.ts index 92997f223..a4e0826af 100644 --- a/frontend/app/components/Charts/sankeyUtils.ts +++ b/frontend/app/components/Charts/sankeyUtils.ts @@ -1,18 +1,32 @@ -// sankeyUtils.ts -export function sankeyTooltip(echartNodes: any[], nodeValues: number[]) { +export function sankeyTooltip( + echartNodes: any[], + nodeValues: Record +) { return (params: any) => { if ('source' in params.data && 'target' in params.data) { const sourceName = echartNodes[params.data.source].name; const targetName = echartNodes[params.data.target].name; + const sourceValue = nodeValues[params.data.source]; + + const safeSourceName = shortenString(sourceName); + const safeTargetName = shortenString(targetName); return `
- ${sourceName} ${targetName} + ${safeSourceName} +
+
+ ${sourceValue} Sessions +
+
+ ${safeTargetName}
- ${params.data.value} ( ${params.data.percentage.toFixed(2)}% ) + ${params.data.value} ( ${params.data.percentage.toFixed( + 2 + )}% ) Sessions
@@ -31,6 +45,21 @@ export function sankeyTooltip(echartNodes: any[], nodeValues: number[]) { }; } +const shortenString = (str: string) => { + const limit = 60; + const leftPart = 25; + const rightPart = 20; + const safeStr = + str.length > limit + ? `${str.slice(0, leftPart)}...${str.slice( + str.length - rightPart, + str.length + )}` + : str; + + return safeStr; +}; + export const getEventPriority = (type: string): number => { switch (type) { case 'DROP': @@ -42,9 +71,12 @@ export const getEventPriority = (type: string): number => { } }; -export const getNodeName = (eventType: string, nodeName: string | null): string => { +export const getNodeName = ( + eventType: string, + nodeName: string | null +): string => { if (!nodeName) { return eventType.charAt(0) + eventType.slice(1).toLowerCase(); } return nodeName; -}; \ No newline at end of file +}; From ef3ed8b6900c958806e3088265c146232bbd8524 Mon Sep 17 00:00:00 2001 From: Kraiem Taha Yassine Date: Thu, 20 Feb 2025 17:39:13 +0100 Subject: [PATCH 36/47] fix(chalice): fixed int value check (#3049) --- api/chalicelib/core/alerts/alerts_processor_ch.py | 2 +- api/chalicelib/core/errors/errors_ch.py | 2 +- api/chalicelib/core/metrics/heatmaps_ch.py | 12 ++++++------ .../metrics/modules/significance/significance_ch.py | 2 +- api/chalicelib/core/sessions/sessions_ch.py | 6 +++--- api/schemas/schemas.py | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/api/chalicelib/core/alerts/alerts_processor_ch.py b/api/chalicelib/core/alerts/alerts_processor_ch.py index 982518be1..316c0f166 100644 --- a/api/chalicelib/core/alerts/alerts_processor_ch.py +++ b/api/chalicelib/core/alerts/alerts_processor_ch.py @@ -173,7 +173,7 @@ def process(): logger.debug(alert) logger.debug(query) try: - result = ch_cur.execute(query) + result = ch_cur.execute(query=query) if len(result) > 0: result = result[0] diff --git a/api/chalicelib/core/errors/errors_ch.py b/api/chalicelib/core/errors/errors_ch.py index 83954fc16..ba728769f 100644 --- a/api/chalicelib/core/errors/errors_ch.py +++ b/api/chalicelib/core/errors/errors_ch.py @@ -400,7 +400,7 @@ def search(data: schemas.SearchErrorsSchema, project: schemas.ProjectContext, us # print("------------") query = ch.format(query=main_ch_query, parameters=params) - rows = ch.execute(query) + rows = ch.execute(query=query) total = rows[0]["total"] if len(rows) > 0 else 0 for r in rows: diff --git a/api/chalicelib/core/metrics/heatmaps_ch.py b/api/chalicelib/core/metrics/heatmaps_ch.py index cfbd1b89c..3b78ef551 100644 --- a/api/chalicelib/core/metrics/heatmaps_ch.py +++ b/api/chalicelib/core/metrics/heatmaps_ch.py @@ -84,7 +84,7 @@ def get_by_url(project_id, data: schemas.GetHeatMapPayloadSchema): logger.debug(query) logger.debug("---------") try: - rows = cur.execute(query) + rows = cur.execute(query=query) except Exception as err: logger.warning("--------- HEATMAP 2 SEARCH QUERY EXCEPTION CH -----------") logger.warning(query) @@ -122,7 +122,7 @@ def get_x_y_by_url_and_session_id(project_id, session_id, data: schemas.GetHeatM logger.debug(query) logger.debug("---------") try: - rows = cur.execute(query) + rows = cur.execute(query=query) except Exception as err: logger.warning("--------- HEATMAP-session_id SEARCH QUERY EXCEPTION CH -----------") logger.warning(query) @@ -160,7 +160,7 @@ def get_selectors_by_url_and_session_id(project_id, session_id, data: schemas.Ge logger.debug(query) logger.debug("---------") try: - rows = cur.execute(query) + rows = cur.execute(query=query) except Exception as err: logger.warning("--------- HEATMAP-session_id SEARCH QUERY EXCEPTION CH -----------") logger.warning(query) @@ -221,7 +221,7 @@ def __get_1_url(location_condition: schemas.SessionSearchEventSchema2 | None, se logger.debug(main_query) logger.debug("--------------------") try: - url = cur.execute(main_query) + url = cur.execute(query=main_query) except Exception as err: logger.warning("--------- CLICK MAP BEST URL SEARCH QUERY EXCEPTION CH-----------") logger.warning(main_query.decode('UTF-8')) @@ -295,7 +295,7 @@ def search_short_session(data: schemas.HeatMapSessionsSearch, project_id, user_i logger.debug(main_query) logger.debug("--------------------") try: - session = cur.execute(main_query) + session = cur.execute(query=main_query) except Exception as err: logger.warning("--------- CLICK MAP SHORT SESSION SEARCH QUERY EXCEPTION CH -----------") logger.warning(main_query) @@ -342,7 +342,7 @@ def get_selected_session(project_id, session_id): logger.debug(main_query) logger.debug("--------------------") try: - session = cur.execute(main_query) + session = cur.execute(query=main_query) except Exception as err: logger.warning("--------- CLICK MAP GET SELECTED SESSION QUERY EXCEPTION -----------") logger.warning(main_query.decode('UTF-8')) diff --git a/api/chalicelib/core/metrics/modules/significance/significance_ch.py b/api/chalicelib/core/metrics/modules/significance/significance_ch.py index 6d920ce59..f309841c0 100644 --- a/api/chalicelib/core/metrics/modules/significance/significance_ch.py +++ b/api/chalicelib/core/metrics/modules/significance/significance_ch.py @@ -243,7 +243,7 @@ def get_simple_funnel(filter_d: schemas.CardSeriesFilterSchema, project: schemas logger.debug(query) logger.debug("---------------------------------------------------") try: - row = cur.execute(query) + row = cur.execute(query=query) except Exception as err: logger.warning("--------- SIMPLE FUNNEL SEARCH QUERY EXCEPTION CH-----------") logger.warning(query) diff --git a/api/chalicelib/core/sessions/sessions_ch.py b/api/chalicelib/core/sessions/sessions_ch.py index 91fe824c7..4ebc8723d 100644 --- a/api/chalicelib/core/sessions/sessions_ch.py +++ b/api/chalicelib/core/sessions/sessions_ch.py @@ -64,7 +64,7 @@ def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, d logging.debug("--------------------") logging.debug(main_query) logging.debug("--------------------") - sessions = cur.execute(main_query) + sessions = cur.execute(query=main_query) elif metric_type == schemas.MetricType.TABLE: full_args["limit_s"] = 0 @@ -112,7 +112,7 @@ def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, d logging.debug("--------------------") logging.debug(main_query) logging.debug("--------------------") - sessions = cur.execute(main_query) + sessions = cur.execute(query=main_query) # cur.fetchone() count = 0 if len(sessions) > 0: @@ -1505,7 +1505,7 @@ def session_exists(project_id, session_id): AND project_id=%(project_id)s LIMIT 1""", parameters={"project_id": project_id, "session_id": session_id}) - row = cur.execute(query) + row = cur.execute(query=query) return row is not None diff --git a/api/schemas/schemas.py b/api/schemas/schemas.py index 0065836c5..ceee5df7c 100644 --- a/api/schemas/schemas.py +++ b/api/schemas/schemas.py @@ -541,7 +541,7 @@ class RequestGraphqlFilterSchema(BaseModel): @classmethod def _transform_data(cls, values): if values.get("type") in [FetchFilterType.FETCH_DURATION, FetchFilterType.FETCH_STATUS_CODE]: - values["value"] = [int(v) for v in values["value"] if v is not None and v.isnumeric()] + values["value"] = [int(v) for v in values["value"] if v is not None and str(v).isnumeric()] return values From da9b926b25888ba2eeee823f4eae950ec226a8c5 Mon Sep 17 00:00:00 2001 From: Aspyryan <52763578+Aspyryan@users.noreply.github.com> Date: Thu, 20 Feb 2025 17:14:13 +0100 Subject: [PATCH 37/47] Fixed tracker uploadOfflineRecording (#3048) Co-authored-by: Jasper Baetsle --- tracker/tracker/src/main/app/index.ts | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index 24c40b5c5..91a18ae39 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -918,7 +918,7 @@ export default class App { private postToWorker(messages: Array) { this.worker?.postMessage(messages) this.commitCallbacks.forEach((cb) => cb(messages)) - messages.length = 0 + //messages.length = 0 } private delay = 0 @@ -1638,18 +1638,21 @@ export default class App { flushBuffer = async (buffer: Message[]) => { return new Promise((res) => { - let ended = false - const messagesBatch: Message[] = [buffer.shift() as unknown as Message] - while (!ended) { - const nextMsg = buffer[0] - if (!nextMsg || nextMsg[0] === MType.Timestamp) { - ended = true - } else { - messagesBatch.push(buffer.shift() as unknown as Message) - } + if (buffer.length === 0) { + res(null); + return; } - this.postToWorker(messagesBatch) - res(null) + + // Since the first element is always a Timestamp, include it by default. + let endIndex = 1; + // Continue until you hit another Timestamp or run out of messages. + while (endIndex < buffer.length && buffer[endIndex][0] !== MType.Timestamp) { + endIndex++; + } + + const messagesBatch = buffer.splice(0, endIndex); + this.postToWorker(messagesBatch); + res(null); }) } From bf56cc53a7e23f50ecc48485b24db07f21836163 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 17:58:06 +0100 Subject: [PATCH 38/47] tracker: release 15.0.5-beta.1 --- tracker/tracker/CHANGELOG.md | 1 + tracker/tracker/package.json | 2 +- tracker/tracker/src/main/app/index.ts | 16 +++++++--------- tracker/tracker/src/main/index.ts | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/tracker/tracker/CHANGELOG.md b/tracker/tracker/CHANGELOG.md index 54d8f73dc..1502e32b6 100644 --- a/tracker/tracker/CHANGELOG.md +++ b/tracker/tracker/CHANGELOG.md @@ -3,6 +3,7 @@ - update medv/finder to 4.0.2 for better support of css-in-js libs - fixes for single tab recording - add option to disable network completely `{ network: { disabled: true } }` +- fix for batching during offline recording syncs ## 15.0.4 diff --git a/tracker/tracker/package.json b/tracker/tracker/package.json index 96232cb65..325d9a576 100644 --- a/tracker/tracker/package.json +++ b/tracker/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker", "description": "The OpenReplay tracker main package", - "version": "15.0.5", + "version": "15.0.5-beta.1", "keywords": [ "logging", "replay" diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index 91a18ae39..086c64f00 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -918,7 +918,6 @@ export default class App { private postToWorker(messages: Array) { this.worker?.postMessage(messages) this.commitCallbacks.forEach((cb) => cb(messages)) - //messages.length = 0 } private delay = 0 @@ -1639,20 +1638,19 @@ export default class App { flushBuffer = async (buffer: Message[]) => { return new Promise((res) => { if (buffer.length === 0) { - res(null); - return; + res(null) + return } // Since the first element is always a Timestamp, include it by default. - let endIndex = 1; - // Continue until you hit another Timestamp or run out of messages. + let endIndex = 1 while (endIndex < buffer.length && buffer[endIndex][0] !== MType.Timestamp) { - endIndex++; + endIndex++ } - const messagesBatch = buffer.splice(0, endIndex); - this.postToWorker(messagesBatch); - res(null); + const messagesBatch = buffer.splice(0, endIndex) + this.postToWorker(messagesBatch) + res(null) }) } diff --git a/tracker/tracker/src/main/index.ts b/tracker/tracker/src/main/index.ts index 8c5807035..27aaa242f 100644 --- a/tracker/tracker/src/main/index.ts +++ b/tracker/tracker/src/main/index.ts @@ -1,4 +1,4 @@ -import App, { DEFAULT_INGEST_POINT } from './app/index.js' +import App from './app/index.js' export { default as App } from './app/index.js' From 5dd1256cd320ea6eb5602be58c214f67ebfee315 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Thu, 20 Feb 2025 17:58:19 +0100 Subject: [PATCH 39/47] ui: fix card modal from staying open --- .../components/DashboardHeader/DashboardHeader.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index 66937d564..033fe55da 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -22,6 +22,10 @@ type Props = IProps & RouteComponentProps; function DashboardHeader(props: Props) { const { siteId } = props; + const [popoverOpen, setPopoverOpen] = React.useState(false); + const handleOpenChange = (open: boolean) => { + setPopoverOpen(open); + }; const { dashboardStore } = useStore(); const [focusTitle, setFocusedInput] = React.useState(true); const [showEditModal, setShowEditModal] = React.useState(false); @@ -82,7 +86,9 @@ function DashboardHeader(props: Props) { } + open={popoverOpen} + onOpenChange={handleOpenChange} + content={} overlayInnerStyle={{ padding: 0, borderRadius: '0.75rem' }} >