Skip to content

Commit

Permalink
[RHOAIENG-4226] Add additional tracking.
Browse files Browse the repository at this point in the history
  • Loading branch information
pilhuhn committed Apr 8, 2024
1 parent fee2688 commit ff5afef
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 11 deletions.
2 changes: 1 addition & 1 deletion docs/dev-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ npm run start

> If you'd like to run "backend" and "frontend" separately for development, cd into each directory in two different terminals and run `npm run start:dev` from each.
For in-depth local run guidance review the [contribution guidelines](../CONTRIBUTING.md#Serving%20Content).
For in-depth local run guidance review the [contribution guidelines](../CONTRIBUTING.md).
### Testing
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/components/ExternalLink.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { Button } from '@patternfly/react-core';
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
import { fireTrackingEventRaw } from '~/utilities/segmentIOUtils';

type ExternalLinkProps = {
text: string;
Expand All @@ -11,7 +12,10 @@ const ExternalLink: React.FC<ExternalLinkProps> = ({ text, to }) => (
<Button
variant="link"
isInline
onClick={() => window.open(to)}
onClick={() => {
window.open(to);
fireTrackingEventRaw('ExternalLink Clicked', { href: to, from: window.location.pathname });
}}
icon={<ExternalLinkAltIcon />}
iconPosition="right"
>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/pages/projects/notebook/NotebookRouteLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Button, ButtonVariant, Flex, FlexItem, Icon, Tooltip } from '@patternfl
import { ExclamationCircleIcon, ExternalLinkAltIcon } from '@patternfly/react-icons';
import { NotebookKind } from '~/k8sTypes';
import { getNotebookDisplayName } from '~/pages/projects/utils';
import { fireTrackingEventRaw } from '~/utilities/segmentIOUtils';
import useRouteForNotebook from './useRouteForNotebook';
import { hasStopAnnotation } from './utils';

Expand Down Expand Up @@ -49,6 +50,9 @@ const NotebookRouteLink: React.FC<NotebookRouteLinkProps> = ({
? 'var(--pf-v5-global--FontSize--md)'
: 'var(--pf-v5-global--FontSize--sm)',
}}
onClick={() =>
fireTrackingEventRaw('Workbench Opened', { wbName: getNotebookDisplayName(notebook) })
}
>
{label ?? getNotebookDisplayName(notebook)}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const NotebookStatusToggle: React.FC<NotebookStatusToggleProps> = ({

const fireNotebookTrackingEvent = React.useCallback(
(action: 'started' | 'stopped') => {
fireTrackingEvent(`Workbench ${action}`, {
fireTrackingEvent(`Workbench ${action === 'started' ? 'Started' : 'Stopped'}`, {
acceleratorCount: acceleratorProfile.useExisting ? undefined : acceleratorProfile.count,
accelerator: acceleratorProfile.acceleratorProfile
? `${acceleratorProfile.acceleratorProfile.spec.displayName} (${acceleratorProfile.acceleratorProfile.metadata.name}): ${acceleratorProfile.acceleratorProfile.spec.identifier}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,28 @@ import { ProjectKind } from '~/k8sTypes';
import { getProjectDisplayName } from '~/pages/projects/utils';
import { deleteProject } from '~/api';
import DeleteModal from '~/pages/projects/components/DeleteModal';
import { fireTrackingEvent } from '~/utilities/segmentIOUtils';
import { TrackingOutcome } from '~/types';

type DeleteProjectModalProps = {
onClose: (deleted: boolean) => void;
deleteData?: ProjectKind;
};

const deleteProjectEventType = 'Project Deleted';
const DeleteProjectModal: React.FC<DeleteProjectModalProps> = ({ deleteData, onClose }) => {
const [deleting, setDeleting] = React.useState(false);
const [error, setError] = React.useState<Error | undefined>();

const onBeforeClose = (deleted: boolean) => {
if (!deleted) {
fireTrackingEvent(deleteProjectEventType, { outcome: TrackingOutcome.cancel });
} else {
fireTrackingEvent(deleteProjectEventType, {
outcome: TrackingOutcome.submit,
success: true,
});
}
onClose(deleted);
setDeleting(false);
setError(undefined);
Expand All @@ -34,6 +45,11 @@ const DeleteProjectModal: React.FC<DeleteProjectModalProps> = ({ deleteData, onC
deleteProject(deleteData.metadata.name)
.then(() => onBeforeClose(true))
.catch((e) => {
fireTrackingEvent(deleteProjectEventType, {
outcome: TrackingOutcome.submit,
success: false,
error: e,
});
setError(e);
setDeleting(false);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as React from 'react';
import { Button } from '@patternfly/react-core';
import { fireTrackingEvent } from '~/utilities/segmentIOUtils';
import { TrackingOutcome } from '~/types';
import ManageProjectModal from './ManageProjectModal';

type NewProjectButtonProps = {
Expand All @@ -22,6 +24,11 @@ const NewProjectButton: React.FC<NewProjectButtonProps> = ({ closeOnCreate, onPr
<ManageProjectModal
open={open}
onClose={(newProjectName) => {
fireTrackingEvent('NewProject Created', {
outcome: newProjectName ? TrackingOutcome.submit : TrackingOutcome.cancel,
success: onProjectCreated != null,
projectName: newProjectName || '',
});
if (newProjectName) {
if (onProjectCreated) {
onProjectCreated(newProjectName);
Expand Down
33 changes: 25 additions & 8 deletions frontend/src/pages/projects/screens/spawner/SpawnerFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@ import {
} from '@patternfly/react-core';
import { assembleSecret, createNotebook, createSecret, updateNotebook } from '~/api';
import {
DataConnectionData,
EnvVariable,
StartNotebookData,
StorageData,
EnvVariable,
DataConnectionData,
} from '~/pages/projects/types';
import { useUser } from '~/redux/selectors';
import { ProjectDetailsContext } from '~/pages/projects/ProjectDetailsContext';
import { AppContext } from '~/app/AppContext';
import { fireTrackingEvent } from '~/utilities/segmentIOUtils';
import usePreferredStorageClass from '~/pages/projects/screens/spawner/storage/usePreferredStorageClass';
import { ProjectSectionID } from '~/pages/projects/screens/detail/types';
import { fireTrackingEvent, fireTrackingEventRaw } from '~/utilities/segmentIOUtils';
import { TrackingOutcome } from '~/types';
import {
createPvcDataForNotebook,
createConfigMapsAndSecretsForNotebook,
createPvcDataForNotebook,
replaceRootVolumesForNotebook,
updateConfigMapsAndSecretsForNotebook,
} from './service';
Expand Down Expand Up @@ -83,7 +84,7 @@ const SpawnerFooter: React.FC<SpawnerFooterProps> = ({

const afterStart = (name: string, type: 'created' | 'updated') => {
const { acceleratorProfile, notebookSize, image } = startNotebookData;
fireTrackingEvent(`Workbench ${type}`, {
fireTrackingEventRaw(`Workbench ${type === 'created' ? 'Created' : 'Updated'}`, {
acceleratorCount: acceleratorProfile.useExisting ? undefined : acceleratorProfile.count,
accelerator: acceleratorProfile.acceleratorProfile
? `${acceleratorProfile.acceleratorProfile.spec.displayName} (${acceleratorProfile.acceleratorProfile.metadata.name}): ${acceleratorProfile.acceleratorProfile.spec.identifier}`
Expand All @@ -96,13 +97,26 @@ const SpawnerFooter: React.FC<SpawnerFooterProps> = ({
: `${image.imageStream?.metadata.name || 'unknown image'} - ${
image.imageVersion?.name || 'unknown version'
}`,
imageName: image.imageStream?.metadata.name,
projectName,
notebookName: name,
storageType: storageData.storageType,
storageDataSize: storageData.creating.size,
dataConnectionType: dataConnection.creating?.type,
dataConnectionCategory: dataConnection.creating?.values?.category,
dataConnectionEnabled: dataConnection.enabled,
outcome: TrackingOutcome.submit,
success: true,
});
refreshAllProjectData();
navigate(`/projects/${projectName}?section=${ProjectSectionID.WORKBENCHES}`);
};
const handleError = (e: Error) => {
fireTrackingEvent('Workbench Created', {
outcome: TrackingOutcome.submit,
success: false,
error: e.message,
});
setErrorMessage(e.message || 'Error creating workbench');
setCreateInProgress(false);
};
Expand Down Expand Up @@ -267,9 +281,12 @@ const SpawnerFooter: React.FC<SpawnerFooterProps> = ({
<Button
variant="link"
id="cancel-button"
onClick={() =>
navigate(`/projects/${projectName}?section=${ProjectSectionID.WORKBENCHES}`)
}
onClick={() => {
fireTrackingEvent(`Workbench ${editNotebook ? 'Updated' : 'Created'}`, {
outcome: TrackingOutcome.cancel,
});
navigate(`/projects/${projectName}?section=${ProjectSectionID.WORKBENCHES}`);
}}
>
Cancel
</Button>
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ export type Section = {
actions: ApplicationAction[];
};

export enum TrackingOutcome {
submit = 'submit',
cancel = 'cancel',
}

export type TrackingEventProperties = {
name?: string;
anonymousID?: string;
Expand All @@ -278,6 +283,9 @@ export type TrackingEventProperties = {
projectName?: string;
notebookName?: string;
lastActivity?: string;
outcome?: TrackingOutcome;
success?: boolean;
error?: string;
};

export type NotebookPort = {
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/utilities/segmentIOUtils.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
import { TrackingEventProperties } from '~/types';
import { DEV_MODE } from './const';

// The following is like the original method below, but allows for more 'free form' properties.
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types
export const fireTrackingEventRaw = (eventType: string, properties?: any): void => {
const clusterID = window.clusterID ?? '';
if (DEV_MODE) {
/* eslint-disable-next-line no-console */
console.log(
`Telemetry event triggered: ${eventType}${
properties ? ` - ${JSON.stringify(properties)}` : ''
}`,
);
} else if (window.analytics) {
window.analytics.track(eventType, { ...properties, clusterID });
}
};

export const fireTrackingEvent = (
eventType: string,
properties?: TrackingEventProperties,
Expand Down

0 comments on commit ff5afef

Please sign in to comment.