mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-13 04:39:06 +08:00
feat: onboarding flow - add analytics (#3594)
This commit is contained in:
parent
04acc49154
commit
4b0a7cc4d3
@ -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
|
||||
|
@ -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':
|
||||
|
@ -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':
|
||||
|
@ -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':
|
||||
|
@ -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':
|
||||
|
@ -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);
|
||||
|
@ -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':
|
||||
|
@ -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 => {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 => {
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user