2024-01-05 11:15:31 +05:30
|
|
|
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
|
|
|
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
|
|
|
/* eslint-disable jsx-a11y/anchor-is-valid */
|
|
|
|
|
import './AppLayout.styles.scss';
|
|
|
|
|
|
2024-06-18 19:04:06 +05:30
|
|
|
import * as Sentry from '@sentry/react';
|
2024-01-05 11:15:31 +05:30
|
|
|
import { Flex } from 'antd';
|
2024-12-02 19:58:38 +05:30
|
|
|
import manageCreditCardApi from 'api/billing/manage';
|
2025-02-21 14:50:29 +05:30
|
|
|
import getLocalStorageApi from 'api/browser/localstorage/get';
|
|
|
|
|
import setLocalStorageApi from 'api/browser/localstorage/set';
|
|
|
|
|
import logEvent from 'api/common/logEvent';
|
2025-05-12 18:14:58 +05:30
|
|
|
import getUserLatestVersion from 'api/v1/version/getLatestVersion';
|
|
|
|
|
import getUserVersion from 'api/v1/version/getVersion';
|
2024-01-05 11:15:31 +05:30
|
|
|
import cx from 'classnames';
|
2024-08-14 20:50:35 +05:30
|
|
|
import ChatSupportGateway from 'components/ChatSupportGateway/ChatSupportGateway';
|
2024-07-16 13:16:13 +04:30
|
|
|
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
2024-12-02 19:58:38 +05:30
|
|
|
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
2025-02-21 14:50:29 +05:30
|
|
|
import { Events } from 'constants/events';
|
2024-08-14 20:50:35 +05:30
|
|
|
import { FeatureKeys } from 'constants/features';
|
2025-02-21 14:50:29 +05:30
|
|
|
import { LOCALSTORAGE } from 'constants/localStorage';
|
2023-09-12 19:20:14 +05:30
|
|
|
import ROUTES from 'constants/routes';
|
2021-10-20 09:24:55 +05:30
|
|
|
import SideNav from 'container/SideNav';
|
2022-05-03 15:27:09 +05:30
|
|
|
import TopNav from 'container/TopNav';
|
2024-12-02 19:58:38 +05:30
|
|
|
import dayjs from 'dayjs';
|
2024-01-05 11:15:31 +05:30
|
|
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
2025-03-05 21:50:29 +05:30
|
|
|
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
2023-02-12 04:23:00 +01:00
|
|
|
import { useNotifications } from 'hooks/useNotifications';
|
2024-01-05 11:15:31 +05:30
|
|
|
import history from 'lib/history';
|
2024-12-02 19:58:38 +05:30
|
|
|
import { isNull } from 'lodash-es';
|
2023-11-15 16:46:20 +05:30
|
|
|
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
2025-01-30 21:51:49 +05:30
|
|
|
import { INTEGRATION_TYPES } from 'pages/Integrations/utils';
|
2024-12-02 19:58:38 +05:30
|
|
|
import { useAppContext } from 'providers/App/App';
|
2025-02-21 14:50:29 +05:30
|
|
|
import {
|
|
|
|
|
ReactNode,
|
|
|
|
|
useCallback,
|
|
|
|
|
useEffect,
|
|
|
|
|
useMemo,
|
|
|
|
|
useRef,
|
|
|
|
|
useState,
|
|
|
|
|
} from 'react';
|
2023-08-02 15:14:15 +05:30
|
|
|
import { Helmet } from 'react-helmet-async';
|
2022-04-05 18:21:25 +05:30
|
|
|
import { useTranslation } from 'react-i18next';
|
2024-12-02 19:58:38 +05:30
|
|
|
import { useMutation, useQueries } from 'react-query';
|
2024-12-20 14:00:02 +05:30
|
|
|
import { useDispatch } from 'react-redux';
|
feat: Funnel Details Page Base Structure (#7364)
* feat: funnels list page basic UI
* feat: get funnels list data from mock API, and handle data, loading and empty states
* feat: implement funnel rename
* chore: move useFunnels to hooks/TracesFunnels
* feat: create traces funnels details basic page + funnel -> details redirection
* fix: properly display created at in funnels list item + preventDefault
* chore: add tab bar to trace funnel details page
* chore: traces funnel details page overall skeleton
* chore: traces funnel details results skeleton
* fix: hide step count for add button only
* feat: funnel details page steps and configuration (#7424)
* chore: add a new tab for traces funnels
* feat: funnels list page basic UI
* feat: get funnels list data from mock API, and handle data, loading and empty states
* feat: implement funnel rename
* refactor: overall improvements
* feat: implement sorting in traces funnels list page
* feat: add sort column key and order to url params
* chore: move useFunnels to hooks/TracesFunnels
* feat: implement traces funnels search and refactor search and sort by extracting to custom hooks
* chore: overall improvements to rename trace funnel modal
* chore: make the rename input auto-focusable
* feat: handle create funnel modal
* feat: delete funnel modal and functionality
* fix: fix the layout shift in funnel item caused by getContainer={false}
* chore: overall improvements and use live api in traces funnels
* feat: create traces funnels details basic page + funnel -> details redirection
* fix: funnels traces light mode UI
* fix: properly display created at in funnels list item + preventDefault
* refactor: extract FunnelItemPopover into a separate component
* chore: hide funnel tab from traces explorer
* chore: add check to display trace funnels tab only in dev environment
* chore: improve funnels modals light mode
* chore: overall improvements
* fix: properly pass funnel details link
* chore: address PR review changes
* chore: add tab bar to trace funnel details page
* feat: funnel step UI with service, span, and where filters
* feat: build radio button component
* refactor: use the SignozRadioButton in funnel results -> step transitions radio buttons
* feat: inter step config (i.e. latency type) UI
* chore: improve steps header styles by removing divider width
* feat: funnel steps title, description, popover UI + pass data from API
* chore: update FilterSelect component to conditionally add url params and accept on change
* fix: fix funnel step where clause and update the state variables for filters
* chore: add support for isMultiple and fix the type in FilterSelect
* feat: centralize the steps state management in StepsContent
* fix: move steps state up + pass steps count from state
* feat: implement auto save for updating the steps whenever any step changes
* feat: implement auto save for validating steps if service name or span names change
* feat: impelement funnel step removal
* feat: implement add details modal for funnel steps
* fix: fix the overflowing time range picker
* feat: funnel details empty state
* feat: add support for saving funnel description
* chore: overall improvements
* fix: fix the light mode styles
* fix: fix the failing build + broken search UI
* refactor: remove the reference of useLocation from traceFunnel item in TraceModulePage constant
* fix: fix the issue of update steps getting triggered on initial render if we have filters
* fix: fix the edge case of stale state causing filters to be re-added after removing
* feat: funnel details page results (#7451)
* feat: funnel metrics table component
* feat: funnel metrics and steps transition metrics components UI
* feat: funnel table component
* feat: slowest traces and traces with error components
* fix: overall light theme fixes
* fix: fix the warning
* chore: add empty and loading states to FunnelMetricsTable
* feat: get overall funnel metrics from the API
* fix: fix the empty state of funnel metrics table
* feat: get data for slowest traces and traces with errors
* fix: link trace id to trace details page
* fix: get data for funnel step transition metrics and refactor the existing data fetching logic
* refactor: add funnel context + overall refactoring and optimizations
* refactor: move steps states to funnel context + handle empty and run funnel disabled states
* feat: handle run funnel
* fix: improve empty state
* chore: rename isValidateStepsMutationLoading -> isValidateStepsLoading
* chore: improve query key
* fix: display loading state if funnel results are fetching
* refactor: move steps validation fetching and states to the context API
* fix: display loading state in funnel results while steps validation is fetching
* fix: call validate steps API only on changing the service name or span name of any step
* refactor: move validateStepsQuery key out of useEffect and update the dependencies
* chore: centralize hasIncompleteSteps and run validate only if steps have service and spans
* fix: handle all empty fields state + overall improvements
* fix: handle long where query tags
* feat: build the funnel result graph component
* feat: build the funnel result graph component
* feat: handle loading, error, empty states in funnel graph
* fix: don't display change percentage if % is 0
* refactor: overall improvements
* feat: get funnel steps graph data from API + move logic to custom hook
* fix: improve empty and error states
* fix: handle funnel graph legends width using css
* fix: redirect to trace funnels list page on clicking delete from funnel details
* fix: update the query cache while updating steps
* fix: implement debounced search for funnel list search
* fix: refetch steps graph data query on clicking run funnel / sync button
* fix: improve the step footer spacing
* chore: add gap between divider to inter-step-config
* fix: handle loading state while fetching
* feat: add span to funnel flow (from trace details page) (#7477)
* chore: display add to funnel icon on hovering any span in trace details page
* chore: add className to funnel item actions popover
* feat: add funnels tab to trace details v2 tab bar
* feat: add span to funnel flow
* chore: hide actions popover button from funnel item in span -> funnel flows
* chore: improve the funnel details UI in add span to funnel modal
* fix: display empty state + don't redirect to funnels list on delete success + overall improvements
* chore: add null check
* fix: display add to funnel button based on feature flag
* fix: display funnels tab in trace details based on feature flag
* fix: remove maxTagCount
* feat: change ms to ns
* chore: address review comments
* chore: remove feature flag and display trace funnels only in dev envirnoment
* fix: handle restoring steps if updating funnel steps fail
* refactor: update the get and delete funnel endpoints to adjust to the BE changes (#7697)
* refactor: address review comments
* fix: handle nested funnel response structure to fix missing funnel_id… (#7740)
* fix: handle nested funnel response structure to fix missing funnel_id in updates
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* chore: remove console.og
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* chore: revert explicitly passing funnelId to updateFunnelSteps
---------
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
Co-authored-by: ahmadshaheer <ashaheerki@gmail.com>
* chore: fix api endpoint
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* refactor: incorporate the recent funnel details API changes (#7760)
* chore: trace funnels feedback changes (#7772)
* chore: change the copy from x traces to valid traces found / not found
* chore: add open funnel button in add span to funnel modal
* feat: display buttons for adding step details and funnel description + copy to clipboard
* feat: highlight funnel graph column based on selected (total / error span) from the legend items
* chore: trace funnel changes (#7780)
* refactor: handle funnels list search on frontend
* refactor: use funnel steps update API for adding / updating step title and description
* feat: allow selecting user's typed option in trace funnel service and span name dropdowns
* chore: properly render the -> between steps in funnel results
* fix: sync funnel step name with add details modal text fields
---------
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
Co-authored-by: Yunus M <myounis.ar@live.com>
Co-authored-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
2025-05-12 09:16:26 +04:30
|
|
|
import { matchPath, useLocation } from 'react-router-dom';
|
2022-04-05 18:21:25 +05:30
|
|
|
import { Dispatch } from 'redux';
|
|
|
|
|
import AppActions from 'types/actions';
|
|
|
|
|
import {
|
|
|
|
|
UPDATE_CURRENT_ERROR,
|
|
|
|
|
UPDATE_CURRENT_VERSION,
|
|
|
|
|
UPDATE_LATEST_VERSION,
|
|
|
|
|
UPDATE_LATEST_VERSION_ERROR,
|
|
|
|
|
} from 'types/actions/app';
|
2024-12-02 19:58:38 +05:30
|
|
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
|
|
|
|
import { CheckoutSuccessPayloadProps } from 'types/api/billing/checkout';
|
2025-03-17 19:27:45 +05:30
|
|
|
import {
|
|
|
|
|
LicenseEvent,
|
|
|
|
|
LicensePlatform,
|
|
|
|
|
LicenseState,
|
|
|
|
|
} from 'types/api/licensesV3/getActive';
|
2025-02-21 14:50:29 +05:30
|
|
|
import { USER_ROLES } from 'types/roles';
|
|
|
|
|
import { eventEmitter } from 'utils/getEventEmitter';
|
2024-12-02 19:58:38 +05:30
|
|
|
import {
|
|
|
|
|
getFormattedDate,
|
|
|
|
|
getFormattedDateWithMinutes,
|
|
|
|
|
getRemainingDays,
|
|
|
|
|
} from 'utils/timeUtils';
|
2021-05-16 18:35:50 +05:30
|
|
|
|
2023-09-06 13:00:20 +05:30
|
|
|
import { ChildrenContainer, Layout, LayoutContent } from './styles';
|
2023-08-02 15:14:15 +05:30
|
|
|
import { getRouteKey } from './utils';
|
2021-05-16 18:35:50 +05:30
|
|
|
|
2024-08-14 20:50:35 +05:30
|
|
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
2022-03-24 12:06:57 +05:30
|
|
|
function AppLayout(props: AppLayoutProps): JSX.Element {
|
2024-12-20 14:00:02 +05:30
|
|
|
const {
|
|
|
|
|
isLoggedIn,
|
|
|
|
|
user,
|
2025-03-17 19:27:45 +05:30
|
|
|
trialInfo,
|
2024-12-20 14:00:02 +05:30
|
|
|
activeLicenseV3,
|
|
|
|
|
isFetchingActiveLicenseV3,
|
|
|
|
|
featureFlags,
|
|
|
|
|
isFetchingFeatureFlags,
|
|
|
|
|
featureFlagsFetchError,
|
|
|
|
|
} = useAppContext();
|
2023-09-12 19:20:14 +05:30
|
|
|
|
2024-08-14 20:50:35 +05:30
|
|
|
const { notifications } = useNotifications();
|
|
|
|
|
|
2024-12-02 19:58:38 +05:30
|
|
|
const [
|
|
|
|
|
showPaymentFailedWarning,
|
|
|
|
|
setShowPaymentFailedWarning,
|
|
|
|
|
] = useState<boolean>(false);
|
|
|
|
|
|
2025-02-21 14:50:29 +05:30
|
|
|
const [showSlowApiWarning, setShowSlowApiWarning] = useState(false);
|
|
|
|
|
const [slowApiWarningShown, setSlowApiWarningShown] = useState(false);
|
|
|
|
|
|
2024-12-02 19:58:38 +05:30
|
|
|
const handleBillingOnSuccess = (
|
|
|
|
|
data: ErrorResponse | SuccessResponse<CheckoutSuccessPayloadProps, unknown>,
|
|
|
|
|
): void => {
|
|
|
|
|
if (data?.payload?.redirectURL) {
|
|
|
|
|
const newTab = document.createElement('a');
|
|
|
|
|
newTab.href = data.payload.redirectURL;
|
|
|
|
|
newTab.target = '_blank';
|
|
|
|
|
newTab.rel = 'noopener noreferrer';
|
|
|
|
|
newTab.click();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleBillingOnError = (): void => {
|
|
|
|
|
notifications.error({
|
|
|
|
|
message: SOMETHING_WENT_WRONG,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const {
|
|
|
|
|
mutate: manageCreditCard,
|
|
|
|
|
isLoading: isLoadingManageBilling,
|
|
|
|
|
} = useMutation(manageCreditCardApi, {
|
|
|
|
|
onSuccess: (data) => {
|
|
|
|
|
handleBillingOnSuccess(data);
|
|
|
|
|
},
|
|
|
|
|
onError: handleBillingOnError,
|
|
|
|
|
});
|
|
|
|
|
|
2024-01-05 11:15:31 +05:30
|
|
|
const isDarkMode = useIsDarkMode();
|
|
|
|
|
|
2022-03-24 12:06:57 +05:30
|
|
|
const { pathname } = useLocation();
|
2023-08-02 15:14:15 +05:30
|
|
|
const { t } = useTranslation(['titles']);
|
2021-05-23 14:15:13 +05:30
|
|
|
|
2025-03-05 21:50:29 +05:30
|
|
|
const { isCloudUser: isCloudUserVal } = useGetTenantLicense();
|
|
|
|
|
|
2024-07-04 01:07:55 +05:30
|
|
|
const [getUserVersionResponse, getUserLatestVersionResponse] = useQueries([
|
2022-04-08 13:49:33 +05:30
|
|
|
{
|
|
|
|
|
queryFn: getUserVersion,
|
2023-05-19 19:04:41 +05:30
|
|
|
queryKey: ['getUserVersion', user?.accessJwt],
|
2022-04-08 13:49:33 +05:30
|
|
|
enabled: isLoggedIn,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
queryFn: getUserLatestVersion,
|
2023-05-19 19:04:41 +05:30
|
|
|
queryKey: ['getUserLatestVersion', user?.accessJwt],
|
2022-04-08 13:49:33 +05:30
|
|
|
enabled: isLoggedIn,
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (getUserLatestVersionResponse.status === 'idle' && isLoggedIn) {
|
|
|
|
|
getUserLatestVersionResponse.refetch();
|
|
|
|
|
}
|
2022-04-05 18:21:25 +05:30
|
|
|
|
2022-04-08 13:49:33 +05:30
|
|
|
if (getUserVersionResponse.status === 'idle' && isLoggedIn) {
|
|
|
|
|
getUserVersionResponse.refetch();
|
|
|
|
|
}
|
2024-07-04 01:07:55 +05:30
|
|
|
}, [getUserLatestVersionResponse, getUserVersionResponse, isLoggedIn]);
|
2022-04-05 18:21:25 +05:30
|
|
|
|
2022-03-24 12:06:57 +05:30
|
|
|
const { children } = props;
|
2021-05-23 14:15:13 +05:30
|
|
|
|
2024-02-12 00:23:19 +05:30
|
|
|
const dispatch = useDispatch<Dispatch<AppActions | any>>();
|
2022-04-05 18:21:25 +05:30
|
|
|
|
|
|
|
|
const latestCurrentCounter = useRef(0);
|
|
|
|
|
const latestVersionCounter = useRef(0);
|
|
|
|
|
|
2022-04-01 15:47:39 +05:30
|
|
|
useEffect(() => {
|
2022-04-08 13:49:33 +05:30
|
|
|
if (
|
|
|
|
|
getUserLatestVersionResponse.isFetched &&
|
|
|
|
|
getUserLatestVersionResponse.isError &&
|
|
|
|
|
latestCurrentCounter.current === 0
|
|
|
|
|
) {
|
2022-04-05 18:21:25 +05:30
|
|
|
latestCurrentCounter.current = 1;
|
|
|
|
|
|
|
|
|
|
dispatch({
|
|
|
|
|
type: UPDATE_LATEST_VERSION_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
isError: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
2023-02-02 14:08:32 +08:00
|
|
|
notifications.error({
|
2022-04-05 18:21:25 +05:30
|
|
|
message: t('oops_something_went_wrong_version'),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-08 13:49:33 +05:30
|
|
|
if (
|
|
|
|
|
getUserVersionResponse.isFetched &&
|
|
|
|
|
getUserVersionResponse.isError &&
|
|
|
|
|
latestVersionCounter.current === 0
|
|
|
|
|
) {
|
2022-04-05 18:21:25 +05:30
|
|
|
latestVersionCounter.current = 1;
|
|
|
|
|
|
|
|
|
|
dispatch({
|
|
|
|
|
type: UPDATE_CURRENT_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
isError: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
2023-02-02 14:08:32 +08:00
|
|
|
notifications.error({
|
2022-04-05 18:21:25 +05:30
|
|
|
message: t('oops_something_went_wrong_version'),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-08 13:49:33 +05:30
|
|
|
if (
|
|
|
|
|
getUserVersionResponse.isFetched &&
|
|
|
|
|
getUserLatestVersionResponse.isSuccess &&
|
|
|
|
|
getUserVersionResponse.data &&
|
|
|
|
|
getUserVersionResponse.data.payload
|
|
|
|
|
) {
|
2022-04-05 18:21:25 +05:30
|
|
|
dispatch({
|
|
|
|
|
type: UPDATE_CURRENT_VERSION,
|
|
|
|
|
payload: {
|
2022-04-08 13:49:33 +05:30
|
|
|
currentVersion: getUserVersionResponse.data.payload.version,
|
2023-02-24 14:57:07 +05:30
|
|
|
ee: getUserVersionResponse.data.payload.ee,
|
|
|
|
|
setupCompleted: getUserVersionResponse.data.payload.setupCompleted,
|
2022-04-05 18:21:25 +05:30
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-08 13:49:33 +05:30
|
|
|
if (
|
|
|
|
|
getUserLatestVersionResponse.isFetched &&
|
|
|
|
|
getUserLatestVersionResponse.isSuccess &&
|
|
|
|
|
getUserLatestVersionResponse.data &&
|
|
|
|
|
getUserLatestVersionResponse.data.payload
|
|
|
|
|
) {
|
2022-04-05 18:21:25 +05:30
|
|
|
dispatch({
|
|
|
|
|
type: UPDATE_LATEST_VERSION,
|
|
|
|
|
payload: {
|
2022-05-10 12:59:15 +05:30
|
|
|
latestVersion: getUserLatestVersionResponse.data.payload.tag_name,
|
2022-04-05 18:21:25 +05:30
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}, [
|
|
|
|
|
dispatch,
|
|
|
|
|
isLoggedIn,
|
|
|
|
|
pathname,
|
|
|
|
|
t,
|
2022-04-08 13:49:33 +05:30
|
|
|
getUserLatestVersionResponse.isLoading,
|
|
|
|
|
getUserLatestVersionResponse.isError,
|
|
|
|
|
getUserLatestVersionResponse.data,
|
|
|
|
|
getUserVersionResponse.isLoading,
|
|
|
|
|
getUserVersionResponse.isError,
|
|
|
|
|
getUserVersionResponse.data,
|
|
|
|
|
getUserLatestVersionResponse.isFetched,
|
|
|
|
|
getUserVersionResponse.isFetched,
|
|
|
|
|
getUserLatestVersionResponse.isSuccess,
|
2023-02-02 14:08:32 +08:00
|
|
|
notifications,
|
2022-04-05 18:21:25 +05:30
|
|
|
]);
|
2022-04-01 15:47:39 +05:30
|
|
|
|
2022-05-03 15:27:09 +05:30
|
|
|
const isToDisplayLayout = isLoggedIn;
|
|
|
|
|
|
2023-08-02 15:14:15 +05:30
|
|
|
const routeKey = useMemo(() => getRouteKey(pathname), [pathname]);
|
|
|
|
|
const pageTitle = t(routeKey);
|
2023-10-16 23:57:44 +05:30
|
|
|
const renderFullScreen =
|
2024-03-07 14:23:28 +05:30
|
|
|
pathname === ROUTES.GET_STARTED ||
|
2024-10-23 23:06:28 +05:30
|
|
|
pathname === ROUTES.ONBOARDING ||
|
2025-03-02 13:05:22 +05:30
|
|
|
pathname === ROUTES.GET_STARTED_WITH_CLOUD ||
|
2024-03-07 14:23:28 +05:30
|
|
|
pathname === ROUTES.GET_STARTED_APPLICATION_MONITORING ||
|
|
|
|
|
pathname === ROUTES.GET_STARTED_INFRASTRUCTURE_MONITORING ||
|
|
|
|
|
pathname === ROUTES.GET_STARTED_LOGS_MANAGEMENT ||
|
2024-06-21 15:05:37 +05:30
|
|
|
pathname === ROUTES.GET_STARTED_AWS_MONITORING ||
|
|
|
|
|
pathname === ROUTES.GET_STARTED_AZURE_MONITORING;
|
2023-08-02 15:14:15 +05:30
|
|
|
|
2024-01-05 11:15:31 +05:30
|
|
|
const [showTrialExpiryBanner, setShowTrialExpiryBanner] = useState(false);
|
|
|
|
|
|
2025-03-17 19:27:45 +05:30
|
|
|
const [showWorkspaceRestricted, setShowWorkspaceRestricted] = useState(false);
|
|
|
|
|
|
2024-01-05 11:15:31 +05:30
|
|
|
useEffect(() => {
|
|
|
|
|
if (
|
2025-03-17 19:27:45 +05:30
|
|
|
!isFetchingActiveLicenseV3 &&
|
|
|
|
|
activeLicenseV3 &&
|
|
|
|
|
trialInfo?.onTrial &&
|
|
|
|
|
!trialInfo?.trialConvertedToSubscription &&
|
|
|
|
|
!trialInfo?.workSpaceBlock &&
|
|
|
|
|
getRemainingDays(trialInfo?.trialEnd) < 7
|
2024-01-05 11:15:31 +05:30
|
|
|
) {
|
|
|
|
|
setShowTrialExpiryBanner(true);
|
|
|
|
|
}
|
2025-03-17 19:27:45 +05:30
|
|
|
}, [isFetchingActiveLicenseV3, activeLicenseV3, trialInfo]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!isFetchingActiveLicenseV3 && activeLicenseV3) {
|
|
|
|
|
const isTerminated = activeLicenseV3.state === LicenseState.TERMINATED;
|
|
|
|
|
const isExpired = activeLicenseV3.state === LicenseState.EXPIRED;
|
|
|
|
|
const isCancelled = activeLicenseV3.state === LicenseState.CANCELLED;
|
|
|
|
|
const isDefaulted = activeLicenseV3.state === LicenseState.DEFAULTED;
|
|
|
|
|
const isEvaluationExpired =
|
|
|
|
|
activeLicenseV3.state === LicenseState.EVALUATION_EXPIRED;
|
|
|
|
|
|
|
|
|
|
const isWorkspaceAccessRestricted =
|
|
|
|
|
isTerminated ||
|
|
|
|
|
isExpired ||
|
|
|
|
|
isCancelled ||
|
|
|
|
|
isDefaulted ||
|
|
|
|
|
isEvaluationExpired;
|
|
|
|
|
|
|
|
|
|
const { platform } = activeLicenseV3;
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
isWorkspaceAccessRestricted &&
|
|
|
|
|
platform === LicensePlatform.SELF_HOSTED
|
|
|
|
|
) {
|
|
|
|
|
setShowWorkspaceRestricted(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, [isFetchingActiveLicenseV3, activeLicenseV3]);
|
2024-01-05 11:15:31 +05:30
|
|
|
|
2024-12-02 19:58:38 +05:30
|
|
|
useEffect(() => {
|
|
|
|
|
if (
|
|
|
|
|
!isFetchingActiveLicenseV3 &&
|
|
|
|
|
!isNull(activeLicenseV3) &&
|
2025-02-05 23:55:36 +05:30
|
|
|
activeLicenseV3?.event_queue?.event === LicenseEvent.DEFAULT
|
2024-12-02 19:58:38 +05:30
|
|
|
) {
|
|
|
|
|
setShowPaymentFailedWarning(true);
|
|
|
|
|
}
|
|
|
|
|
}, [activeLicenseV3, isFetchingActiveLicenseV3]);
|
|
|
|
|
|
2024-10-18 18:17:17 +05:30
|
|
|
useEffect(() => {
|
|
|
|
|
// after logging out hide the trial expiry banner
|
|
|
|
|
if (!isLoggedIn) {
|
|
|
|
|
setShowTrialExpiryBanner(false);
|
2024-12-20 14:00:02 +05:30
|
|
|
setShowPaymentFailedWarning(false);
|
2025-02-21 14:50:29 +05:30
|
|
|
setShowSlowApiWarning(false);
|
2024-10-18 18:17:17 +05:30
|
|
|
}
|
|
|
|
|
}, [isLoggedIn]);
|
|
|
|
|
|
2025-02-21 14:50:29 +05:30
|
|
|
const handleUpgrade = useCallback((): void => {
|
|
|
|
|
if (user.role === USER_ROLES.ADMIN) {
|
2024-01-05 11:15:31 +05:30
|
|
|
history.push(ROUTES.BILLING);
|
|
|
|
|
}
|
2025-02-21 14:50:29 +05:30
|
|
|
}, [user.role]);
|
|
|
|
|
|
|
|
|
|
const handleFailedPayment = useCallback((): void => {
|
2025-03-17 15:22:04 +05:30
|
|
|
manageCreditCard({
|
2025-03-21 11:32:49 +05:30
|
|
|
url: window.location.origin,
|
2025-03-17 15:22:04 +05:30
|
|
|
});
|
|
|
|
|
}, [manageCreditCard]);
|
2024-12-02 19:58:38 +05:30
|
|
|
|
2025-03-16 19:41:08 +05:30
|
|
|
const isHome = (): boolean => routeKey === 'HOME';
|
|
|
|
|
|
2024-02-12 00:23:19 +05:30
|
|
|
const isLogsView = (): boolean =>
|
|
|
|
|
routeKey === 'LOGS' ||
|
|
|
|
|
routeKey === 'LOGS_EXPLORER' ||
|
|
|
|
|
routeKey === 'LOGS_PIPELINES' ||
|
|
|
|
|
routeKey === 'LOGS_SAVE_VIEWS';
|
|
|
|
|
|
2025-03-24 18:01:39 +05:30
|
|
|
const isApiMonitoringView = (): boolean => routeKey === 'API_MONITORING';
|
|
|
|
|
|
2025-04-21 11:11:05 +05:30
|
|
|
const isExceptionsView = (): boolean => routeKey === 'ALL_ERROR';
|
|
|
|
|
|
2024-02-12 00:23:19 +05:30
|
|
|
const isTracesView = (): boolean =>
|
|
|
|
|
routeKey === 'TRACES_EXPLORER' || routeKey === 'TRACES_SAVE_VIEWS';
|
|
|
|
|
|
2024-08-29 16:36:56 +05:30
|
|
|
const isMessagingQueues = (): boolean =>
|
2025-01-29 17:32:01 +05:30
|
|
|
routeKey === 'MESSAGING_QUEUES_KAFKA' ||
|
|
|
|
|
routeKey === 'MESSAGING_QUEUES_KAFKA_DETAIL' ||
|
2025-01-27 10:56:01 +05:30
|
|
|
routeKey === 'MESSAGING_QUEUES_CELERY_TASK' ||
|
2025-01-28 10:04:06 +05:30
|
|
|
routeKey === 'MESSAGING_QUEUES_OVERVIEW';
|
2024-08-29 16:36:56 +05:30
|
|
|
|
2025-01-30 21:51:49 +05:30
|
|
|
const isCloudIntegrationPage = (): boolean =>
|
|
|
|
|
routeKey === 'INTEGRATIONS' &&
|
|
|
|
|
new URLSearchParams(window.location.search).get('integration') ===
|
|
|
|
|
INTEGRATION_TYPES.AWS_INTEGRATION;
|
|
|
|
|
|
2024-05-28 19:09:04 +05:30
|
|
|
const isDashboardListView = (): boolean => routeKey === 'ALL_DASHBOARD';
|
2024-09-04 21:26:10 +05:30
|
|
|
const isAlertHistory = (): boolean => routeKey === 'ALERT_HISTORY';
|
|
|
|
|
const isAlertOverview = (): boolean => routeKey === 'ALERT_OVERVIEW';
|
2025-01-08 16:13:54 +05:30
|
|
|
const isInfraMonitoring = (): boolean =>
|
|
|
|
|
routeKey === 'INFRASTRUCTURE_MONITORING_HOSTS' ||
|
|
|
|
|
routeKey === 'INFRASTRUCTURE_MONITORING_KUBERNETES';
|
2025-03-22 13:43:18 +04:30
|
|
|
const isTracesFunnels = (): boolean => routeKey === 'TRACES_FUNNELS';
|
feat: Funnel Details Page Base Structure (#7364)
* feat: funnels list page basic UI
* feat: get funnels list data from mock API, and handle data, loading and empty states
* feat: implement funnel rename
* chore: move useFunnels to hooks/TracesFunnels
* feat: create traces funnels details basic page + funnel -> details redirection
* fix: properly display created at in funnels list item + preventDefault
* chore: add tab bar to trace funnel details page
* chore: traces funnel details page overall skeleton
* chore: traces funnel details results skeleton
* fix: hide step count for add button only
* feat: funnel details page steps and configuration (#7424)
* chore: add a new tab for traces funnels
* feat: funnels list page basic UI
* feat: get funnels list data from mock API, and handle data, loading and empty states
* feat: implement funnel rename
* refactor: overall improvements
* feat: implement sorting in traces funnels list page
* feat: add sort column key and order to url params
* chore: move useFunnels to hooks/TracesFunnels
* feat: implement traces funnels search and refactor search and sort by extracting to custom hooks
* chore: overall improvements to rename trace funnel modal
* chore: make the rename input auto-focusable
* feat: handle create funnel modal
* feat: delete funnel modal and functionality
* fix: fix the layout shift in funnel item caused by getContainer={false}
* chore: overall improvements and use live api in traces funnels
* feat: create traces funnels details basic page + funnel -> details redirection
* fix: funnels traces light mode UI
* fix: properly display created at in funnels list item + preventDefault
* refactor: extract FunnelItemPopover into a separate component
* chore: hide funnel tab from traces explorer
* chore: add check to display trace funnels tab only in dev environment
* chore: improve funnels modals light mode
* chore: overall improvements
* fix: properly pass funnel details link
* chore: address PR review changes
* chore: add tab bar to trace funnel details page
* feat: funnel step UI with service, span, and where filters
* feat: build radio button component
* refactor: use the SignozRadioButton in funnel results -> step transitions radio buttons
* feat: inter step config (i.e. latency type) UI
* chore: improve steps header styles by removing divider width
* feat: funnel steps title, description, popover UI + pass data from API
* chore: update FilterSelect component to conditionally add url params and accept on change
* fix: fix funnel step where clause and update the state variables for filters
* chore: add support for isMultiple and fix the type in FilterSelect
* feat: centralize the steps state management in StepsContent
* fix: move steps state up + pass steps count from state
* feat: implement auto save for updating the steps whenever any step changes
* feat: implement auto save for validating steps if service name or span names change
* feat: impelement funnel step removal
* feat: implement add details modal for funnel steps
* fix: fix the overflowing time range picker
* feat: funnel details empty state
* feat: add support for saving funnel description
* chore: overall improvements
* fix: fix the light mode styles
* fix: fix the failing build + broken search UI
* refactor: remove the reference of useLocation from traceFunnel item in TraceModulePage constant
* fix: fix the issue of update steps getting triggered on initial render if we have filters
* fix: fix the edge case of stale state causing filters to be re-added after removing
* feat: funnel details page results (#7451)
* feat: funnel metrics table component
* feat: funnel metrics and steps transition metrics components UI
* feat: funnel table component
* feat: slowest traces and traces with error components
* fix: overall light theme fixes
* fix: fix the warning
* chore: add empty and loading states to FunnelMetricsTable
* feat: get overall funnel metrics from the API
* fix: fix the empty state of funnel metrics table
* feat: get data for slowest traces and traces with errors
* fix: link trace id to trace details page
* fix: get data for funnel step transition metrics and refactor the existing data fetching logic
* refactor: add funnel context + overall refactoring and optimizations
* refactor: move steps states to funnel context + handle empty and run funnel disabled states
* feat: handle run funnel
* fix: improve empty state
* chore: rename isValidateStepsMutationLoading -> isValidateStepsLoading
* chore: improve query key
* fix: display loading state if funnel results are fetching
* refactor: move steps validation fetching and states to the context API
* fix: display loading state in funnel results while steps validation is fetching
* fix: call validate steps API only on changing the service name or span name of any step
* refactor: move validateStepsQuery key out of useEffect and update the dependencies
* chore: centralize hasIncompleteSteps and run validate only if steps have service and spans
* fix: handle all empty fields state + overall improvements
* fix: handle long where query tags
* feat: build the funnel result graph component
* feat: build the funnel result graph component
* feat: handle loading, error, empty states in funnel graph
* fix: don't display change percentage if % is 0
* refactor: overall improvements
* feat: get funnel steps graph data from API + move logic to custom hook
* fix: improve empty and error states
* fix: handle funnel graph legends width using css
* fix: redirect to trace funnels list page on clicking delete from funnel details
* fix: update the query cache while updating steps
* fix: implement debounced search for funnel list search
* fix: refetch steps graph data query on clicking run funnel / sync button
* fix: improve the step footer spacing
* chore: add gap between divider to inter-step-config
* fix: handle loading state while fetching
* feat: add span to funnel flow (from trace details page) (#7477)
* chore: display add to funnel icon on hovering any span in trace details page
* chore: add className to funnel item actions popover
* feat: add funnels tab to trace details v2 tab bar
* feat: add span to funnel flow
* chore: hide actions popover button from funnel item in span -> funnel flows
* chore: improve the funnel details UI in add span to funnel modal
* fix: display empty state + don't redirect to funnels list on delete success + overall improvements
* chore: add null check
* fix: display add to funnel button based on feature flag
* fix: display funnels tab in trace details based on feature flag
* fix: remove maxTagCount
* feat: change ms to ns
* chore: address review comments
* chore: remove feature flag and display trace funnels only in dev envirnoment
* fix: handle restoring steps if updating funnel steps fail
* refactor: update the get and delete funnel endpoints to adjust to the BE changes (#7697)
* refactor: address review comments
* fix: handle nested funnel response structure to fix missing funnel_id… (#7740)
* fix: handle nested funnel response structure to fix missing funnel_id in updates
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* chore: remove console.og
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* chore: revert explicitly passing funnelId to updateFunnelSteps
---------
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
Co-authored-by: ahmadshaheer <ashaheerki@gmail.com>
* chore: fix api endpoint
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* refactor: incorporate the recent funnel details API changes (#7760)
* chore: trace funnels feedback changes (#7772)
* chore: change the copy from x traces to valid traces found / not found
* chore: add open funnel button in add span to funnel modal
* feat: display buttons for adding step details and funnel description + copy to clipboard
* feat: highlight funnel graph column based on selected (total / error span) from the legend items
* chore: trace funnel changes (#7780)
* refactor: handle funnels list search on frontend
* refactor: use funnel steps update API for adding / updating step title and description
* feat: allow selecting user's typed option in trace funnel service and span name dropdowns
* chore: properly render the -> between steps in funnel results
* fix: sync funnel step name with add details modal text fields
---------
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
Co-authored-by: Yunus M <myounis.ar@live.com>
Co-authored-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
2025-05-12 09:16:26 +04:30
|
|
|
const isTracesFunnelDetails = (): boolean =>
|
|
|
|
|
!!matchPath(pathname, ROUTES.TRACES_FUNNELS_DETAIL);
|
|
|
|
|
|
2024-10-01 12:17:15 +04:30
|
|
|
const isPathMatch = (regex: RegExp): boolean => regex.test(pathname);
|
2024-05-28 19:09:04 +05:30
|
|
|
|
2024-10-01 12:17:15 +04:30
|
|
|
const isDashboardView = (): boolean =>
|
|
|
|
|
isPathMatch(/^\/dashboard\/[a-zA-Z0-9_-]+$/);
|
|
|
|
|
|
|
|
|
|
const isDashboardWidgetView = (): boolean =>
|
|
|
|
|
isPathMatch(/^\/dashboard\/[a-zA-Z0-9_-]+\/new$/);
|
|
|
|
|
|
|
|
|
|
const isTraceDetailsView = (): boolean =>
|
|
|
|
|
isPathMatch(/^\/trace\/[a-zA-Z0-9]+(\?.*)?$/);
|
2024-05-28 19:09:04 +05:30
|
|
|
|
2024-02-12 00:23:19 +05:30
|
|
|
useEffect(() => {
|
|
|
|
|
if (isDarkMode) {
|
|
|
|
|
document.body.classList.remove('lightMode');
|
2025-05-06 20:14:26 +04:30
|
|
|
document.body.classList.add('dark');
|
2024-02-12 00:23:19 +05:30
|
|
|
document.body.classList.add('darkMode');
|
|
|
|
|
} else {
|
|
|
|
|
document.body.classList.add('lightMode');
|
2025-05-06 20:14:26 +04:30
|
|
|
document.body.classList.remove('dark');
|
2024-02-12 00:23:19 +05:30
|
|
|
document.body.classList.remove('darkMode');
|
|
|
|
|
}
|
|
|
|
|
}, [isDarkMode]);
|
|
|
|
|
|
2024-12-20 14:00:02 +05:30
|
|
|
const showAddCreditCardModal = useMemo(() => {
|
|
|
|
|
if (
|
|
|
|
|
!isFetchingFeatureFlags &&
|
|
|
|
|
(featureFlags || featureFlagsFetchError) &&
|
2025-03-17 19:27:45 +05:30
|
|
|
activeLicenseV3 &&
|
|
|
|
|
trialInfo
|
2024-12-20 14:00:02 +05:30
|
|
|
) {
|
|
|
|
|
let isChatSupportEnabled = false;
|
|
|
|
|
let isPremiumSupportEnabled = false;
|
|
|
|
|
if (featureFlags && featureFlags.length > 0) {
|
|
|
|
|
isChatSupportEnabled =
|
|
|
|
|
featureFlags.find((flag) => flag.name === FeatureKeys.CHAT_SUPPORT)
|
|
|
|
|
?.active || false;
|
|
|
|
|
|
|
|
|
|
isPremiumSupportEnabled =
|
|
|
|
|
featureFlags.find((flag) => flag.name === FeatureKeys.PREMIUM_SUPPORT)
|
|
|
|
|
?.active || false;
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
isLoggedIn &&
|
|
|
|
|
!isPremiumSupportEnabled &&
|
|
|
|
|
isChatSupportEnabled &&
|
2025-03-17 19:27:45 +05:30
|
|
|
!trialInfo?.trialConvertedToSubscription &&
|
2024-12-20 14:00:02 +05:30
|
|
|
isCloudUserVal
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}, [
|
|
|
|
|
featureFlags,
|
|
|
|
|
featureFlagsFetchError,
|
2025-03-05 21:50:29 +05:30
|
|
|
isCloudUserVal,
|
2024-12-20 14:00:02 +05:30
|
|
|
isFetchingFeatureFlags,
|
|
|
|
|
isLoggedIn,
|
2025-03-17 19:27:45 +05:30
|
|
|
activeLicenseV3,
|
|
|
|
|
trialInfo,
|
2024-12-20 14:00:02 +05:30
|
|
|
]);
|
|
|
|
|
|
2025-02-21 14:50:29 +05:30
|
|
|
// Listen for API warnings
|
|
|
|
|
const handleWarning = (
|
|
|
|
|
isSlow: boolean,
|
|
|
|
|
data: { duration: number; url: string; threshold: number },
|
|
|
|
|
): void => {
|
|
|
|
|
const dontShowSlowApiWarning = getLocalStorageApi(
|
|
|
|
|
LOCALSTORAGE.DONT_SHOW_SLOW_API_WARNING,
|
|
|
|
|
);
|
|
|
|
|
|
2025-03-07 15:42:51 +05:30
|
|
|
logEvent(
|
|
|
|
|
`Slow API Warning`,
|
|
|
|
|
{
|
|
|
|
|
durationMs: data.duration,
|
|
|
|
|
url: data.url,
|
|
|
|
|
thresholdMs: data.threshold,
|
|
|
|
|
},
|
|
|
|
|
'track',
|
|
|
|
|
true, // rate limited - controlled by Backend
|
|
|
|
|
);
|
2025-02-21 14:50:29 +05:30
|
|
|
|
|
|
|
|
const isDontShowSlowApiWarning = dontShowSlowApiWarning === 'true';
|
|
|
|
|
|
|
|
|
|
if (isDontShowSlowApiWarning) {
|
|
|
|
|
setShowSlowApiWarning(false);
|
|
|
|
|
} else {
|
|
|
|
|
setShowSlowApiWarning(isSlow);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
eventEmitter.on(Events.SLOW_API_WARNING, handleWarning);
|
|
|
|
|
|
|
|
|
|
return (): void => {
|
|
|
|
|
eventEmitter.off(Events.SLOW_API_WARNING, handleWarning);
|
|
|
|
|
};
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const handleDismissSlowApiWarning = (): void => {
|
|
|
|
|
setShowSlowApiWarning(false);
|
|
|
|
|
|
|
|
|
|
setLocalStorageApi(LOCALSTORAGE.DONT_SHOW_SLOW_API_WARNING, 'true');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (
|
|
|
|
|
showSlowApiWarning &&
|
2025-03-17 19:27:45 +05:30
|
|
|
trialInfo?.onTrial &&
|
|
|
|
|
!trialInfo?.trialConvertedToSubscription &&
|
2025-02-21 14:50:29 +05:30
|
|
|
!slowApiWarningShown
|
|
|
|
|
) {
|
|
|
|
|
setSlowApiWarningShown(true);
|
|
|
|
|
|
|
|
|
|
notifications.info({
|
|
|
|
|
message: (
|
|
|
|
|
<div>
|
|
|
|
|
Our systems are taking longer than expected for your trial workspace.
|
|
|
|
|
Please{' '}
|
|
|
|
|
{user.role === USER_ROLES.ADMIN ? (
|
|
|
|
|
<span>
|
|
|
|
|
<a
|
|
|
|
|
className="upgrade-link"
|
|
|
|
|
onClick={(): void => {
|
|
|
|
|
notifications.destroy('slow-api-warning');
|
|
|
|
|
|
|
|
|
|
logEvent(`Slow API Banner: Upgrade clicked`, {});
|
|
|
|
|
|
|
|
|
|
handleUpgrade();
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
upgrade
|
|
|
|
|
</a>
|
|
|
|
|
your workspace for a smoother experience.
|
|
|
|
|
</span>
|
|
|
|
|
) : (
|
|
|
|
|
'contact your administrator for upgrading to a paid plan for a smoother experience.'
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
),
|
|
|
|
|
duration: 60000,
|
|
|
|
|
placement: 'topRight',
|
|
|
|
|
onClose: handleDismissSlowApiWarning,
|
|
|
|
|
key: 'slow-api-warning',
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}, [
|
|
|
|
|
showSlowApiWarning,
|
|
|
|
|
notifications,
|
|
|
|
|
user.role,
|
|
|
|
|
isLoadingManageBilling,
|
|
|
|
|
handleFailedPayment,
|
|
|
|
|
slowApiWarningShown,
|
|
|
|
|
handleUpgrade,
|
2025-03-17 19:27:45 +05:30
|
|
|
trialInfo?.onTrial,
|
|
|
|
|
trialInfo?.trialConvertedToSubscription,
|
2025-02-21 14:50:29 +05:30
|
|
|
]);
|
|
|
|
|
|
2025-03-17 19:27:45 +05:30
|
|
|
const renderWorkspaceRestrictedBanner = (): JSX.Element => (
|
|
|
|
|
<div className="workspace-restricted-banner">
|
|
|
|
|
{activeLicenseV3?.state === LicenseState.TERMINATED && (
|
|
|
|
|
<>
|
|
|
|
|
Your SigNoz license is terminated, enterprise features have been disabled.
|
|
|
|
|
Please contact support at{' '}
|
|
|
|
|
<a href="mailto:support@signoz.io">support@signoz.io</a> for new license
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
{activeLicenseV3?.state === LicenseState.EXPIRED && (
|
|
|
|
|
<>
|
|
|
|
|
Your SigNoz license has expired. Please contact support at{' '}
|
|
|
|
|
<a href="mailto:support@signoz.io">support@signoz.io</a> for renewal to
|
|
|
|
|
avoid termination of license as per our{' '}
|
|
|
|
|
<a
|
|
|
|
|
href="https://signoz.io/terms-of-service"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
>
|
|
|
|
|
terms of service
|
|
|
|
|
</a>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
{activeLicenseV3?.state === LicenseState.CANCELLED && (
|
|
|
|
|
<>
|
|
|
|
|
Your SigNoz license is cancelled. Please contact support at{' '}
|
|
|
|
|
<a href="mailto:support@signoz.io">support@signoz.io</a> for reactivation
|
|
|
|
|
to avoid termination of license as per our{' '}
|
|
|
|
|
<a
|
|
|
|
|
href="https://signoz.io/terms-of-service"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
>
|
|
|
|
|
terms of service
|
|
|
|
|
</a>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{activeLicenseV3?.state === LicenseState.DEFAULTED && (
|
|
|
|
|
<>
|
|
|
|
|
Your SigNoz license is defaulted. Please clear the bill to continue using
|
|
|
|
|
the enterprise features. Contact support at{' '}
|
|
|
|
|
<a href="mailto:support@signoz.io">support@signoz.io</a> to avoid
|
|
|
|
|
termination of license as per our{' '}
|
|
|
|
|
<a
|
|
|
|
|
href="https://signoz.io/terms-of-service"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
>
|
|
|
|
|
terms of service
|
|
|
|
|
</a>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{activeLicenseV3?.state === LicenseState.EVALUATION_EXPIRED && (
|
|
|
|
|
<>
|
|
|
|
|
Your SigNoz trial has ended. Please contact support at{' '}
|
|
|
|
|
<a href="mailto:support@signoz.io">support@signoz.io</a> for next steps to
|
|
|
|
|
avoid termination of license as per our{' '}
|
|
|
|
|
<a
|
|
|
|
|
href="https://signoz.io/terms-of-service"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
>
|
|
|
|
|
terms of service
|
|
|
|
|
</a>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
|
2021-05-16 18:35:50 +05:30
|
|
|
return (
|
2025-05-06 20:14:26 +04:30
|
|
|
<Layout className={cx(isDarkMode ? 'darkMode dark' : 'lightMode')}>
|
2023-08-02 15:14:15 +05:30
|
|
|
<Helmet>
|
|
|
|
|
<title>{pageTitle}</title>
|
|
|
|
|
</Helmet>
|
|
|
|
|
|
2024-12-02 19:58:38 +05:30
|
|
|
{showTrialExpiryBanner && !showPaymentFailedWarning && (
|
2024-01-05 11:15:31 +05:30
|
|
|
<div className="trial-expiry-banner">
|
|
|
|
|
You are in free trial period. Your free trial will end on{' '}
|
2025-03-17 19:27:45 +05:30
|
|
|
<span>{getFormattedDate(trialInfo?.trialEnd || Date.now())}.</span>
|
2025-02-21 14:50:29 +05:30
|
|
|
{user.role === USER_ROLES.ADMIN ? (
|
2024-01-05 11:15:31 +05:30
|
|
|
<span>
|
|
|
|
|
{' '}
|
|
|
|
|
Please{' '}
|
|
|
|
|
<a className="upgrade-link" onClick={handleUpgrade}>
|
|
|
|
|
upgrade
|
|
|
|
|
</a>
|
|
|
|
|
to continue using SigNoz features.
|
|
|
|
|
</span>
|
|
|
|
|
) : (
|
|
|
|
|
'Please contact your administrator for upgrading to a paid plan.'
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-02-21 14:50:29 +05:30
|
|
|
|
2025-03-17 19:27:45 +05:30
|
|
|
{showWorkspaceRestricted && renderWorkspaceRestrictedBanner()}
|
|
|
|
|
|
2024-12-02 19:58:38 +05:30
|
|
|
{!showTrialExpiryBanner && showPaymentFailedWarning && (
|
|
|
|
|
<div className="payment-failed-banner">
|
|
|
|
|
Your bill payment has failed. Your workspace will get suspended on{' '}
|
|
|
|
|
<span>
|
|
|
|
|
{getFormattedDateWithMinutes(
|
|
|
|
|
dayjs(activeLicenseV3?.event_queue?.scheduled_at).unix() || Date.now(),
|
|
|
|
|
)}
|
|
|
|
|
.
|
|
|
|
|
</span>
|
2025-02-21 14:50:29 +05:30
|
|
|
{user.role === USER_ROLES.ADMIN ? (
|
2024-12-02 19:58:38 +05:30
|
|
|
<span>
|
|
|
|
|
{' '}
|
|
|
|
|
Please{' '}
|
2025-02-21 14:50:29 +05:30
|
|
|
<a className="upgrade-link" onClick={handleFailedPayment}>
|
2024-12-02 19:58:38 +05:30
|
|
|
pay the bill
|
|
|
|
|
</a>
|
|
|
|
|
to continue using SigNoz features.
|
|
|
|
|
</span>
|
|
|
|
|
) : (
|
|
|
|
|
' Please contact your administrator to pay the bill.'
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2024-01-05 11:15:31 +05:30
|
|
|
|
2025-05-06 20:14:26 +04:30
|
|
|
<Flex
|
|
|
|
|
className={cx('app-layout', isDarkMode ? 'darkMode dark' : 'lightMode')}
|
|
|
|
|
>
|
2024-12-20 14:00:02 +05:30
|
|
|
{isToDisplayLayout && !renderFullScreen && <SideNav />}
|
2025-03-16 19:41:08 +05:30
|
|
|
<div
|
|
|
|
|
className={cx('app-content', {
|
|
|
|
|
'full-screen-content': renderFullScreen,
|
|
|
|
|
})}
|
|
|
|
|
data-overlayscrollbars-initialize
|
|
|
|
|
>
|
2024-06-18 19:04:06 +05:30
|
|
|
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
|
2024-07-16 13:16:13 +04:30
|
|
|
<LayoutContent data-overlayscrollbars-initialize>
|
|
|
|
|
<OverlayScrollbar>
|
|
|
|
|
<ChildrenContainer
|
|
|
|
|
style={{
|
|
|
|
|
margin:
|
2025-03-16 19:41:08 +05:30
|
|
|
isHome() ||
|
2024-07-16 13:16:13 +04:30
|
|
|
isLogsView() ||
|
|
|
|
|
isTracesView() ||
|
|
|
|
|
isDashboardView() ||
|
|
|
|
|
isDashboardWidgetView() ||
|
2024-08-29 16:36:56 +05:30
|
|
|
isDashboardListView() ||
|
2024-09-04 21:26:10 +05:30
|
|
|
isAlertHistory() ||
|
|
|
|
|
isAlertOverview() ||
|
2024-11-21 21:53:05 +05:30
|
|
|
isMessagingQueues() ||
|
2025-01-30 21:51:49 +05:30
|
|
|
isCloudIntegrationPage() ||
|
2025-03-24 18:01:39 +05:30
|
|
|
isInfraMonitoring() ||
|
2025-04-21 11:11:05 +05:30
|
|
|
isApiMonitoringView() ||
|
|
|
|
|
isExceptionsView()
|
2024-07-16 13:16:13 +04:30
|
|
|
? 0
|
|
|
|
|
: '0 1rem',
|
2024-10-01 12:17:15 +04:30
|
|
|
|
feat: Funnel Details Page Base Structure (#7364)
* feat: funnels list page basic UI
* feat: get funnels list data from mock API, and handle data, loading and empty states
* feat: implement funnel rename
* chore: move useFunnels to hooks/TracesFunnels
* feat: create traces funnels details basic page + funnel -> details redirection
* fix: properly display created at in funnels list item + preventDefault
* chore: add tab bar to trace funnel details page
* chore: traces funnel details page overall skeleton
* chore: traces funnel details results skeleton
* fix: hide step count for add button only
* feat: funnel details page steps and configuration (#7424)
* chore: add a new tab for traces funnels
* feat: funnels list page basic UI
* feat: get funnels list data from mock API, and handle data, loading and empty states
* feat: implement funnel rename
* refactor: overall improvements
* feat: implement sorting in traces funnels list page
* feat: add sort column key and order to url params
* chore: move useFunnels to hooks/TracesFunnels
* feat: implement traces funnels search and refactor search and sort by extracting to custom hooks
* chore: overall improvements to rename trace funnel modal
* chore: make the rename input auto-focusable
* feat: handle create funnel modal
* feat: delete funnel modal and functionality
* fix: fix the layout shift in funnel item caused by getContainer={false}
* chore: overall improvements and use live api in traces funnels
* feat: create traces funnels details basic page + funnel -> details redirection
* fix: funnels traces light mode UI
* fix: properly display created at in funnels list item + preventDefault
* refactor: extract FunnelItemPopover into a separate component
* chore: hide funnel tab from traces explorer
* chore: add check to display trace funnels tab only in dev environment
* chore: improve funnels modals light mode
* chore: overall improvements
* fix: properly pass funnel details link
* chore: address PR review changes
* chore: add tab bar to trace funnel details page
* feat: funnel step UI with service, span, and where filters
* feat: build radio button component
* refactor: use the SignozRadioButton in funnel results -> step transitions radio buttons
* feat: inter step config (i.e. latency type) UI
* chore: improve steps header styles by removing divider width
* feat: funnel steps title, description, popover UI + pass data from API
* chore: update FilterSelect component to conditionally add url params and accept on change
* fix: fix funnel step where clause and update the state variables for filters
* chore: add support for isMultiple and fix the type in FilterSelect
* feat: centralize the steps state management in StepsContent
* fix: move steps state up + pass steps count from state
* feat: implement auto save for updating the steps whenever any step changes
* feat: implement auto save for validating steps if service name or span names change
* feat: impelement funnel step removal
* feat: implement add details modal for funnel steps
* fix: fix the overflowing time range picker
* feat: funnel details empty state
* feat: add support for saving funnel description
* chore: overall improvements
* fix: fix the light mode styles
* fix: fix the failing build + broken search UI
* refactor: remove the reference of useLocation from traceFunnel item in TraceModulePage constant
* fix: fix the issue of update steps getting triggered on initial render if we have filters
* fix: fix the edge case of stale state causing filters to be re-added after removing
* feat: funnel details page results (#7451)
* feat: funnel metrics table component
* feat: funnel metrics and steps transition metrics components UI
* feat: funnel table component
* feat: slowest traces and traces with error components
* fix: overall light theme fixes
* fix: fix the warning
* chore: add empty and loading states to FunnelMetricsTable
* feat: get overall funnel metrics from the API
* fix: fix the empty state of funnel metrics table
* feat: get data for slowest traces and traces with errors
* fix: link trace id to trace details page
* fix: get data for funnel step transition metrics and refactor the existing data fetching logic
* refactor: add funnel context + overall refactoring and optimizations
* refactor: move steps states to funnel context + handle empty and run funnel disabled states
* feat: handle run funnel
* fix: improve empty state
* chore: rename isValidateStepsMutationLoading -> isValidateStepsLoading
* chore: improve query key
* fix: display loading state if funnel results are fetching
* refactor: move steps validation fetching and states to the context API
* fix: display loading state in funnel results while steps validation is fetching
* fix: call validate steps API only on changing the service name or span name of any step
* refactor: move validateStepsQuery key out of useEffect and update the dependencies
* chore: centralize hasIncompleteSteps and run validate only if steps have service and spans
* fix: handle all empty fields state + overall improvements
* fix: handle long where query tags
* feat: build the funnel result graph component
* feat: build the funnel result graph component
* feat: handle loading, error, empty states in funnel graph
* fix: don't display change percentage if % is 0
* refactor: overall improvements
* feat: get funnel steps graph data from API + move logic to custom hook
* fix: improve empty and error states
* fix: handle funnel graph legends width using css
* fix: redirect to trace funnels list page on clicking delete from funnel details
* fix: update the query cache while updating steps
* fix: implement debounced search for funnel list search
* fix: refetch steps graph data query on clicking run funnel / sync button
* fix: improve the step footer spacing
* chore: add gap between divider to inter-step-config
* fix: handle loading state while fetching
* feat: add span to funnel flow (from trace details page) (#7477)
* chore: display add to funnel icon on hovering any span in trace details page
* chore: add className to funnel item actions popover
* feat: add funnels tab to trace details v2 tab bar
* feat: add span to funnel flow
* chore: hide actions popover button from funnel item in span -> funnel flows
* chore: improve the funnel details UI in add span to funnel modal
* fix: display empty state + don't redirect to funnels list on delete success + overall improvements
* chore: add null check
* fix: display add to funnel button based on feature flag
* fix: display funnels tab in trace details based on feature flag
* fix: remove maxTagCount
* feat: change ms to ns
* chore: address review comments
* chore: remove feature flag and display trace funnels only in dev envirnoment
* fix: handle restoring steps if updating funnel steps fail
* refactor: update the get and delete funnel endpoints to adjust to the BE changes (#7697)
* refactor: address review comments
* fix: handle nested funnel response structure to fix missing funnel_id… (#7740)
* fix: handle nested funnel response structure to fix missing funnel_id in updates
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* chore: remove console.og
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* chore: revert explicitly passing funnelId to updateFunnelSteps
---------
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
Co-authored-by: ahmadshaheer <ashaheerki@gmail.com>
* chore: fix api endpoint
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
* refactor: incorporate the recent funnel details API changes (#7760)
* chore: trace funnels feedback changes (#7772)
* chore: change the copy from x traces to valid traces found / not found
* chore: add open funnel button in add span to funnel modal
* feat: display buttons for adding step details and funnel description + copy to clipboard
* feat: highlight funnel graph column based on selected (total / error span) from the legend items
* chore: trace funnel changes (#7780)
* refactor: handle funnels list search on frontend
* refactor: use funnel steps update API for adding / updating step title and description
* feat: allow selecting user's typed option in trace funnel service and span name dropdowns
* chore: properly render the -> between steps in funnel results
* fix: sync funnel step name with add details modal text fields
---------
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
Co-authored-by: Yunus M <myounis.ar@live.com>
Co-authored-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
2025-05-12 09:16:26 +04:30
|
|
|
...(isTraceDetailsView() ||
|
|
|
|
|
isTracesFunnels() ||
|
|
|
|
|
isTracesFunnelDetails()
|
|
|
|
|
? { margin: 0 }
|
|
|
|
|
: {}),
|
2024-07-16 13:16:13 +04:30
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{isToDisplayLayout && !renderFullScreen && <TopNav />}
|
|
|
|
|
{children}
|
|
|
|
|
</ChildrenContainer>
|
|
|
|
|
</OverlayScrollbar>
|
2024-01-05 11:15:31 +05:30
|
|
|
</LayoutContent>
|
2024-06-18 19:04:06 +05:30
|
|
|
</Sentry.ErrorBoundary>
|
2024-01-05 11:15:31 +05:30
|
|
|
</div>
|
|
|
|
|
</Flex>
|
2024-08-14 20:50:35 +05:30
|
|
|
|
|
|
|
|
{showAddCreditCardModal && <ChatSupportGateway />}
|
2021-05-16 18:35:50 +05:30
|
|
|
</Layout>
|
|
|
|
|
);
|
2022-03-24 12:06:57 +05:30
|
|
|
}
|
2021-05-16 18:35:50 +05:30
|
|
|
|
2021-10-22 17:05:10 +05:30
|
|
|
interface AppLayoutProps {
|
|
|
|
|
children: ReactNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default AppLayout;
|