feat: add analytics group call (#3757)

* feat: add analytics group call

* feat: add safety check for billing breakdown variable
This commit is contained in:
Yunus M 2023-10-17 16:54:37 +05:30 committed by GitHub
parent 377dbd8aec
commit f7fe64a8df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 101 additions and 48 deletions

View File

@ -22,7 +22,8 @@ import { Dispatch } from 'redux';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { UPDATE_FEATURE_FLAG_RESPONSE } from 'types/actions/app';
import AppReducer from 'types/reducer/app';
import AppReducer, { User } from 'types/reducer/app';
import { extractDomain, isCloudUser } from 'utils/app';
import { trackPageView } from 'utils/segmentAnalytics';
import PrivateRoute from './Private';
@ -32,7 +33,7 @@ function App(): JSX.Element {
const themeConfig = useThemeConfig();
const { data } = useLicense();
const [routes, setRoutes] = useState(defaultRoutes);
const { role, isLoggedIn: isLoggedInState, user } = useSelector<
const { role, isLoggedIn: isLoggedInState, user, org } = useSelector<
AppState,
AppReducer
>((state) => state.app);
@ -41,6 +42,8 @@ function App(): JSX.Element {
const { hostname, pathname } = window.location;
const isCloudUserVal = isCloudUser();
const featureResponse = useGetFeatureFlag((allFlags) => {
const isOnboardingEnabled =
allFlags.find((flag) => flag.name === FeatureKeys.ONBOARDING)?.active ||
@ -58,10 +61,7 @@ function App(): JSX.Element {
},
});
if (
!isOnboardingEnabled ||
!(hostname && hostname.endsWith('signoz.cloud'))
) {
if (!isOnboardingEnabled || !isCloudUserVal) {
const newRoutes = routes.filter(
(route) => route?.path !== ROUTES.GET_STARTED,
);
@ -86,6 +86,35 @@ function App(): JSX.Element {
license.isCurrent && license.planKey === LICENSE_PLAN_KEY.BASIC_PLAN,
) || data?.payload?.licenses === null;
const enableAnalytics = (user: User): void => {
const orgName =
org && Array.isArray(org) && org.length > 0 ? org[0].name : '';
const identifyPayload = {
email: user?.email,
name: user?.name,
company_name: orgName,
role,
};
const domain = extractDomain(user?.email);
const hostNameParts = hostname.split('.');
const groupTraits = {
name: orgName,
tenant_id: hostNameParts[0],
data_region: hostNameParts[1],
tenant_url: hostname,
company_domain: domain,
};
window.analytics.identify(user?.email, identifyPayload);
window.analytics.group(domain, groupTraits);
window.clarity('identify', user.email, user.name);
};
useEffect(() => {
const isIdentifiedUser = getLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER);
@ -98,12 +127,9 @@ function App(): JSX.Element {
) {
setLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER, 'true');
window.analytics.identify(user?.email, {
email: user?.email,
name: user?.name,
});
window.clarity('identify', user.email, user.name);
if (isCloudUserVal) {
enableAnalytics(user);
}
}
if (isOnBasicPlan || (isLoggedInState && role && role !== 'ADMIN')) {

View File

@ -176,24 +176,26 @@ export default function BillingContainer(): JSX.Element {
} = data?.payload || {};
const formattedUsageData: any[] = [];
for (let index = 0; index < breakdown.length; index += 1) {
const element = breakdown[index];
if (breakdown && Array.isArray(breakdown)) {
for (let index = 0; index < breakdown.length; index += 1) {
const element = breakdown[index];
element?.tiers.forEach(
(
tier: { quantity: number; unitPrice: number; tierCost: number },
i: number,
) => {
formattedUsageData.push({
key: `${index}${i}`,
name: i === 0 ? element?.type : '',
unit: element?.unit,
dataIngested: tier.quantity,
pricePerUnit: tier.unitPrice,
cost: `$ ${tier.tierCost}`,
});
},
);
element?.tiers.forEach(
(
tier: { quantity: number; unitPrice: number; tierCost: number },
i: number,
) => {
formattedUsageData.push({
key: `${index}${i}`,
name: i === 0 ? element?.type : '',
unit: element?.unit,
dataIngested: tier.quantity,
pricePerUnit: tier.unitPrice,
cost: `$ ${tier.tierCost}`,
});
},
);
}
}
setData(formattedUsageData);

View File

@ -1,6 +1,6 @@
import './IngestionSettings.styles.scss';
import { Table, Typography } from 'antd';
import { Skeleton, Table, Typography } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import getIngestionData from 'api/settings/getIngestionData';
import { useQuery } from 'react-query';
@ -12,7 +12,7 @@ import AppReducer from 'types/reducer/app';
export default function IngestionSettings(): JSX.Element {
const { user } = useSelector<AppState, AppReducer>((state) => state.app);
const { data: ingestionData } = useQuery({
const { data: ingestionData, isFetching } = useQuery({
queryFn: getIngestionData,
queryKey: ['getIngestionData', user?.userId],
});
@ -25,11 +25,19 @@ export default function IngestionSettings(): JSX.Element {
render: (text): JSX.Element => <Typography.Text> {text} </Typography.Text>,
},
{
title: 'Value',
title: '',
dataIndex: 'value',
key: 'value',
render: (text): JSX.Element => (
<Typography.Text copyable>{text}</Typography.Text>
<div>
{isFetching ? (
<Skeleton.Input active style={{ height: 20 }} />
) : (
<Typography.Text copyable={!isFetching && text !== ''}>
{text}
</Typography.Text>
)}
</div>
),
},
];

View File

@ -13,6 +13,7 @@ import { useLocation } from 'react-router-dom';
import { sideBarCollapse } from 'store/actions/app';
import { AppState } from 'store/reducers';
import AppReducer from 'types/reducer/app';
import { isCloudUser } from 'utils/app';
import { routeConfig, styles } from './config';
import { getQueryString } from './helper';
@ -50,8 +51,6 @@ function SideNav(): JSX.Element {
license.isCurrent && license.planKey === LICENSE_PLAN_KEY.BASIC_PLAN,
) || data?.payload?.licenses === null;
const { hostname } = window.location;
const menuItems = useMemo(
() =>
defaultMenuItems.filter((item) => {
@ -64,16 +63,13 @@ function SideNav(): JSX.Element {
return item.key !== ROUTES.BILLING;
}
if (
!isOnboardingEnabled ||
!(hostname && hostname.endsWith('signoz.cloud'))
) {
if (!isOnboardingEnabled || !isCloudUser()) {
return item.key !== ROUTES.GET_STARTED;
}
return true;
}),
[featureResponse.data, isOnBasicPlan, hostname, role],
[featureResponse.data, isOnBasicPlan, role],
);
const { pathname, search } = useLocation();

View File

@ -19,6 +19,9 @@ export const commonRoutes = (t: TFunction): RouteTabProps['routes'] => [
route: ROUTES.ALL_CHANNELS,
key: ROUTES.ALL_CHANNELS,
},
];
export const ingestionSettings = (t: TFunction): RouteTabProps['routes'] => [
{
Component: IngestionSettings,
name: t('routes:ingestion_settings').toString(),

View File

@ -1,7 +1,12 @@
import { RouteTabProps } from 'components/RouteTab/types';
import { TFunction } from 'i18next';
import { isCloudUser } from 'utils/app';
import { commonRoutes, organizationSettings } from './config';
import {
commonRoutes,
ingestionSettings,
organizationSettings,
} from './config';
export const getRoutes = (
isCurrentOrgSettings: boolean,
@ -13,5 +18,9 @@ export const getRoutes = (
common = [...common, ...organizationSettings(t)];
}
if (isCloudUser()) {
common = [...common, ...ingestionSettings(t)];
}
return common;
};

View File

@ -17,6 +17,7 @@ import { useLocation } from 'react-router-dom';
import { SuccessResponse } from 'types/api';
import { PayloadProps } from 'types/api/user/getUser';
import { PayloadProps as LoginPrecheckPayloadProps } from 'types/api/user/loginPrecheck';
import { isCloudUser } from 'utils/app';
import { trackEvent } from 'utils/segmentAnalytics';
import {
@ -233,8 +234,6 @@ function SignUp({ version }: SignUpProps): JSX.Element {
const handleSubmit = (): void => {
(async (): Promise<void> => {
const { hostname } = window.location;
try {
const values = form.getFieldsValue();
setLoading(true);
@ -260,11 +259,7 @@ function SignUp({ version }: SignUpProps): JSX.Element {
await commonHandler(
values,
async (): Promise<void> => {
if (
isOnboardingEnabled &&
hostname &&
hostname.endsWith('signoz.cloud')
) {
if (isOnboardingEnabled && isCloudUser()) {
history.push(ROUTES.GET_STARTED);
} else {
history.push(ROUTES.APPLICATION);

View File

@ -3,3 +3,17 @@ import { SKIP_ONBOARDING } from 'constants/onboarding';
export const isOnboardingSkipped = (): boolean =>
getLocalStorage(SKIP_ONBOARDING) === 'true';
export function extractDomain(email: string): string {
const emailParts = email.split('@');
if (emailParts.length !== 2) {
return email;
}
return emailParts[1];
}
export const isCloudUser = (): boolean => {
const { hostname } = window.location;
return hostname?.endsWith('signoz.cloud');
};