feat: onboarding flow - add analytics (#3594)

This commit is contained in:
Yunus M 2023-09-20 16:00:51 +05:30 committed by GitHub
parent 04acc49154
commit 4b0a7cc4d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 150 additions and 29 deletions

View File

@ -76,9 +76,9 @@ function App(): JSX.Element {
useEffect(() => {
if (isLoggedInState && user && user.userId && user.email) {
window.analytics.identify(user?.userId, {
email: user?.email || '',
name: user?.name || '',
window.analytics.identify(user?.email, {
email: user?.email,
name: user?.name,
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps

View File

@ -3,7 +3,8 @@
import './APM.styles.scss';
import cx from 'classnames';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { trackEvent } from 'utils/segmentAnalytics';
import GoLang from './GoLang/GoLang';
import Java from './Java/Java';
@ -36,6 +37,15 @@ export default function APM({
}): JSX.Element {
const [selectedLanguage, setSelectedLanguage] = useState('java');
useEffect(() => {
// on language select
trackEvent('Onboarding: APM', {
selectedLanguage,
activeStep,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedLanguage]);
const renderSelectedLanguageSetupInstructions = (): JSX.Element => {
switch (selectedLanguage) {
case 'java':

View File

@ -3,7 +3,8 @@ import './Java.styles.scss';
import { MDXProvider } from '@mdx-js/react';
import { Form, Input, Select } from 'antd';
import Header from 'container/OnboardingContainer/common/Header/Header';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { trackEvent } from 'utils/segmentAnalytics';
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
import JavaDocs from './md-docs/java.md';
@ -27,6 +28,14 @@ export default function Java({
const [form] = Form.useForm();
useEffect(() => {
// on language select
trackEvent('Onboarding: APM : Java', {
selectedFrameWork,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedFrameWork]);
const renderDocs = (): JSX.Element => {
switch (selectedFrameWork) {
case 'tomcat':

View File

@ -3,7 +3,8 @@ import './Javascript.styles.scss';
import { MDXProvider } from '@mdx-js/react';
import { Form, Input, Select } from 'antd';
import Header from 'container/OnboardingContainer/common/Header/Header';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { trackEvent } from 'utils/segmentAnalytics';
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
import ExpressDocs from './md-docs/express.md';
@ -25,6 +26,14 @@ export default function Javascript({
const [form] = Form.useForm();
useEffect(() => {
// on language select
trackEvent('Onboarding: APM : Javascript', {
selectedFrameWork,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedFrameWork]);
const renderDocs = (): JSX.Element => {
switch (selectedFrameWork) {
case 'nodejs':

View File

@ -3,7 +3,8 @@ import './Python.styles.scss';
import { MDXProvider } from '@mdx-js/react';
import { Form, Input, Select } from 'antd';
import Header from 'container/OnboardingContainer/common/Header/Header';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { trackEvent } from 'utils/segmentAnalytics';
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
import DjangoDocs from './md-docs/django.md';
@ -29,6 +30,14 @@ export default function Python({
const [form] = Form.useForm();
useEffect(() => {
// on language select
trackEvent('Onboarding: APM : Python', {
selectedFrameWork,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedFrameWork]);
const renderDocs = (): JSX.Element => {
switch (selectedFrameWork) {
case 'django':

View File

@ -16,6 +16,7 @@ import { UPDATE_TIME_INTERVAL } from 'types/actions/globalTime';
import { PayloadProps as QueryServicePayloadProps } from 'types/api/metrics/getService';
import { GlobalReducer } from 'types/reducer/globalTime';
import { Tags } from 'types/reducer/trace';
import { trackEvent } from 'utils/segmentAnalytics';
interface ConnectionStatusProps {
serviceName: string;
@ -112,6 +113,10 @@ export default function ConnectionStatus({
if (data || isError) {
setRetryCount(retryCount - 1);
if (retryCount < 0) {
trackEvent('❌ Onboarding: APM: Connection Status', {
serviceName,
status: 'Failed',
});
setLoading(false);
}
}
@ -122,6 +127,11 @@ export default function ConnectionStatus({
setLoading(false);
setIsReceivingData(true);
trackEvent('✅ Onboarding: APM: Connection Status', {
serviceName,
status: 'Successful',
});
break;
}
}
@ -130,31 +140,35 @@ export default function ConnectionStatus({
// Use useEffect to update query parameters when the polling interval lapses
useEffect(() => {
const pollingTimer = setInterval(() => {
// Trigger a refetch with the updated parameters
const updatedMinTime = (Date.now() - 15 * 60 * 1000) * 1000000;
const updatedMaxTime = Date.now() * 1000000;
let pollingTimer: string | number | NodeJS.Timer | undefined;
const payload = {
maxTime: updatedMaxTime,
minTime: updatedMinTime,
selectedTime,
};
if (loading) {
pollingTimer = setInterval(() => {
// Trigger a refetch with the updated parameters
const updatedMinTime = (Date.now() - 15 * 60 * 1000) * 1000000;
const updatedMaxTime = Date.now() * 1000000;
dispatch({
type: UPDATE_TIME_INTERVAL,
payload,
});
const payload = {
maxTime: updatedMaxTime,
minTime: updatedMinTime,
selectedTime,
};
// refetch(updatedParams);
}, pollingInterval); // Same interval as pollingInterval
dispatch({
type: UPDATE_TIME_INTERVAL,
payload,
});
}, pollingInterval); // Same interval as pollingInterval
} else if (!loading && pollingTimer) {
clearInterval(pollingTimer);
}
// Clean up the interval when the component unmounts
return (): void => {
clearInterval(pollingTimer);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [refetch, selectedTags, selectedTime]);
}, [refetch, selectedTags, selectedTime, loading]);
useEffect(() => {
verifyApplicationData(data);

View File

@ -1,7 +1,8 @@
import { MDXProvider } from '@mdx-js/react';
import { Select } from 'antd';
import Header from 'container/OnboardingContainer/common/Header/Header';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { trackEvent } from 'utils/segmentAnalytics';
import FluentBit from './md-docs/fluentBit.md';
import FluentD from './md-docs/fluentD.md';
@ -16,6 +17,14 @@ enum FrameworksMap {
export default function ExistingCollectors(): JSX.Element {
const [selectedFrameWork, setSelectedFrameWork] = useState('fluent_d');
useEffect(() => {
// on language select
trackEvent('Onboarding: Logs Management: Existing Collectors', {
selectedFrameWork,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedFrameWork]);
const renderDocs = (): JSX.Element => {
switch (selectedFrameWork) {
case 'fluent_d':

View File

@ -4,7 +4,8 @@
import './LogsManagement.styles.scss';
import cx from 'classnames';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { trackEvent } from 'utils/segmentAnalytics';
import ApplicationLogs from './ApplicationLogs/ApplicationLogs';
import Docker from './Docker/Docker';
@ -60,6 +61,15 @@ export default function LogsManagement({
}): JSX.Element {
const [selectedLogsType, setSelectedLogsType] = useState('kubernetes');
useEffect(() => {
// on language select
trackEvent('Onboarding: Logs Management', {
selectedLogsType,
activeStep,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedLogsType]);
const renderSelectedLanguageSetupInstructions = ():
| JSX.Element
| undefined => {

View File

@ -16,6 +16,7 @@ import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import { DataSource } from 'types/common/queryBuilder';
import { trackEvent } from 'utils/segmentAnalytics';
interface ConnectionStatusProps {
logType: string;
@ -95,6 +96,10 @@ export default function LogsConnectionStatus({
setRetryCount(retryCount - 1);
if (retryCount < 0) {
trackEvent('❌ Onboarding: Logs Management: Connection Status', {
status: 'Failed',
});
setLoading(false);
setPollingInterval(false);
}
@ -123,6 +128,11 @@ export default function LogsConnectionStatus({
setIsReceivingData(true);
setRetryCount(-1);
setPollingInterval(false);
trackEvent('✅ Onboarding: Logs Management: Connection Status', {
status: 'Successful',
});
break;
}
}

View File

@ -9,6 +9,8 @@ import ROUTES from 'constants/routes';
import { useIsDarkMode } from 'hooks/useDarkMode';
import history from 'lib/history';
import { useEffect, useState } from 'react';
import { useEffectOnce } from 'react-use';
import { trackEvent } from 'utils/segmentAnalytics';
import APM from './APM/APM';
import InfrastructureMonitoring from './InfrastructureMonitoring/InfrastructureMonitoring';
@ -98,6 +100,10 @@ export default function Onboarding(): JSX.Element {
},
];
useEffectOnce(() => {
trackEvent('Onboarding Started');
});
useEffect(() => {
if (selectedModule?.id === ModulesMap.InfrastructureMonitoring) {
setsteps([...baseSteps]);
@ -123,27 +129,55 @@ export default function Onboarding(): JSX.Element {
},
]);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedModule, selectedLogsType]);
useEffect(() => {
// on select
trackEvent('Onboarding: Module Selected', {
selectedModule: selectedModule.id,
});
}, [selectedModule]);
const handleNext = (): void => {
// Need to add logic to validate service name and then allow next step transition in APM module
const isFormValid = true;
if (isFormValid && activeStep <= 3) {
setActiveStep(activeStep + 1);
const nextStep = activeStep + 1;
// on next
trackEvent('Onboarding: Next', {
selectedModule: selectedModule.id,
nextStepId: nextStep,
});
setActiveStep(nextStep);
setCurrent(current + 1);
}
};
const handlePrev = (): void => {
if (activeStep >= 1) {
const prevStep = activeStep - 1;
// on prev
trackEvent('Onboarding: Back', {
module: selectedModule.id,
prevStepId: prevStep,
});
setCurrent(current - 1);
setActiveStep(activeStep - 1);
setActiveStep(prevStep);
}
};
const handleOnboardingComplete = (): void => {
trackEvent('Onboarding Complete', {
module: selectedModule.id,
});
switch (selectedModule.id) {
case ModulesMap.APM:
history.push(ROUTES.APPLICATION);
@ -160,8 +194,15 @@ export default function Onboarding(): JSX.Element {
};
const handleStepChange = (value: number): void => {
const stepId = value + 1;
trackEvent('Onboarding: Step Change', {
module: selectedModule.id,
step: stepId,
});
setCurrent(value);
setActiveStep(value + 1);
setActiveStep(stepId);
};
const handleModuleSelect = (module: ModuleProps): void => {

View File

@ -4,7 +4,7 @@ function trackPageView(pageName: string): void {
function trackEvent(
eventName: string,
properties: Record<string, string>,
properties?: Record<string, unknown>,
): void {
window.analytics.track(eventName, properties);
}