Skip to content

Commit

Permalink
Fix new source / destination test connection success / failure tracki…
Browse files Browse the repository at this point in the history
…ng events (#12526)

* Consolidate track new action analytics calls into hook

* Move new source and destination test tracking to where the actual connection is being tested and remove from creation

* Use consistent properties across all track new source actions

* Make track action hook more generic and support new destination actions
Update new destination actions with useTrackAction hook

* Use connector_source_definition_id over connector_source_id for track new source actions
  • Loading branch information
edmundito authored May 3, 2022
1 parent 17892e8 commit 7e79cac
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 73 deletions.
2 changes: 1 addition & 1 deletion airbyte-webapp/src/core/analytics/AnalyticsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class AnalyticsService {

reset = (): void => this.getSegmentAnalytics()?.reset?.();

track = (name: string, properties: Record<string, unknown>): void =>
track = <P = Record<string, unknown>>(name: string, properties: P): void =>
this.getSegmentAnalytics()?.track?.(name, {
...properties,
...this.context,
Expand Down
16 changes: 1 addition & 15 deletions airbyte-webapp/src/hooks/services/useDestinationHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ const useCreateDestination = () => {
const queryClient = useQueryClient();
const workspace = useCurrentWorkspace();

const analyticsService = useAnalyticsService();

return useMutation(
async (createDestinationPayload: { values: ValuesProps; destinationConnector?: ConnectorProps }) => {
const { values, destinationConnector } = createDestinationPayload;
Expand All @@ -78,23 +76,11 @@ const useCreateDestination = () => {
});
},
{
onSuccess: (data, ctx) => {
analyticsService.track("New Destination - Action", {
action: "Tested connector - success",
connector_destination: ctx.destinationConnector?.name,
connector_destination_definition_id: ctx.destinationConnector?.destinationDefinitionId,
});
onSuccess: (data) => {
queryClient.setQueryData(destinationsKeys.lists(), (lst: DestinationList | undefined) => ({
destinations: [data, ...(lst?.destinations ?? [])],
}));
},
onError: (_, ctx) => {
analyticsService.track("New Destination - Action", {
action: "Tested connector - failure",
connector_destination: ctx.destinationConnector?.name,
connector_destination_definition_id: ctx.destinationConnector?.destinationDefinitionId,
});
},
}
);
};
Expand Down
19 changes: 0 additions & 19 deletions airbyte-webapp/src/hooks/services/useSourceHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,9 @@ const useCreateSource = () => {
const queryClient = useQueryClient();
const workspace = useCurrentWorkspace();

const analyticsService = useAnalyticsService();

return useMutation(
async (createSourcePayload: { values: ValuesProps; sourceConnector?: ConnectorProps }) => {
const { values, sourceConnector } = createSourcePayload;
analyticsService.track("New Source - Action", {
action: "Test a connector",
connector_source: sourceConnector?.name,
connector_source_id: sourceConnector?.sourceDefinitionId,
});

try {
// Try to crete source
const result = await service.create({
Expand All @@ -88,19 +80,8 @@ const useCreateSource = () => {
connectionConfiguration: values.connectionConfiguration,
});

analyticsService.track("New Source - Action", {
action: "Tested connector - success",
connector_source: sourceConnector?.name,
connector_source_id: sourceConnector?.sourceDefinitionId,
});

return result;
} catch (e) {
analyticsService.track("New Source - Action", {
action: "Tested connector - failure",
connector_source: sourceConnector?.name,
connector_source_id: sourceConnector?.sourceDefinitionId,
});
throw e;
}
},
Expand Down
26 changes: 26 additions & 0 deletions airbyte-webapp/src/hooks/useTrackAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useCallback } from "react";

import { useAnalyticsService } from "./services/Analytics/useAnalyticsService";

export const enum TrackActionType {
NEW_SOURCE = "New Source",
NEW_DESTINATION = "New Destination",
}

interface TrackActionProperties {
connector_source?: string;
connector_source_definition_id?: string;
connector_destination?: string;
connector_destination_definition_id?: string;
}

export const useTrackAction = (type: TrackActionType) => {
const analyticsService = useAnalyticsService();

return useCallback(
(action: string, properties: TrackActionProperties) => {
analyticsService.track(`${type} - Action`, { action, ...properties });
},
[analyticsService, type]
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { FormattedMessage } from "react-intl";
import { ConnectionConfiguration } from "core/domain/connection";
import { DestinationDefinition } from "core/domain/connector";
import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import useRouter from "hooks/useRouter";
import { TrackActionType, useTrackAction } from "hooks/useTrackAction";
import { useGetDestinationDefinitionSpecificationAsync } from "services/connector/DestinationDefinitionSpecificationService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
Expand Down Expand Up @@ -39,7 +39,7 @@ const DestinationForm: React.FC<IProps> = ({
afterSelectConnector,
}) => {
const { location } = useRouter();
const analyticsService = useAnalyticsService();
const trackNewDestinationAction = useTrackAction(TrackActionType.NEW_DESTINATION);

const [destinationDefinitionId, setDestinationDefinitionId] = useState(
hasDestinationDefinitionId(location.state) ? location.state.destinationDefinitionId : null
Expand All @@ -58,9 +58,8 @@ const DestinationForm: React.FC<IProps> = ({
afterSelectConnector();
}

analyticsService.track("New Destination - Action", {
action: "Select a connector",
connector_destination_definition: connector?.name,
trackNewDestinationAction("Select a connector", {
connector_destination: connector?.name,
connector_destination_definition_id: destinationDefinitionId,
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { FormattedMessage } from "react-intl";

import { ConnectionConfiguration } from "core/domain/connection";
import { JobInfo } from "core/domain/job";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { useCreateDestination } from "hooks/services/useDestinationHook";
import { TrackActionType, useTrackAction } from "hooks/useTrackAction";
import { useDestinationDefinitionList } from "services/connector/DestinationDefinitionService";
import { useGetDestinationDefinitionSpecificationAsync } from "services/connector/DestinationDefinitionSpecificationService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
Expand All @@ -31,7 +31,7 @@ const DestinationStep: React.FC<Props> = ({ onNextStep, onSuccess }) => {
} | null>(null);

const { mutateAsync: createDestination } = useCreateDestination();
const analyticsService = useAnalyticsService();
const trackNewDestinationAction = useTrackAction(TrackActionType.NEW_DESTINATION);

const getDestinationDefinitionById = (id: string) =>
destinationDefinitions.find((item) => item.destinationDefinitionId === id);
Expand Down Expand Up @@ -64,8 +64,7 @@ const DestinationStep: React.FC<Props> = ({ onNextStep, onSuccess }) => {

const onDropDownSelect = (destinationDefinitionId: string) => {
const destinationConnector = getDestinationDefinitionById(destinationDefinitionId);
analyticsService.track("New Destination - Action", {
action: "Select a connector",
trackNewDestinationAction("Select a connector", {
connector_destination: destinationConnector?.name,
connector_destination_definition_id: destinationConnector?.destinationDefinitionId,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { FormattedMessage } from "react-intl";
import { ConnectionConfiguration } from "core/domain/connection";
import { JobInfo } from "core/domain/job";
import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { useCreateSource } from "hooks/services/useSourceHook";
import { TrackActionType, useTrackAction } from "hooks/useTrackAction";
import { useSourceDefinitionList } from "services/connector/SourceDefinitionService";
import { useGetSourceDefinitionSpecificationAsync } from "services/connector/SourceDefinitionSpecificationService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
Expand All @@ -31,7 +31,7 @@ const SourceStep: React.FC<IProps> = ({ onNextStep, onSuccess }) => {

const { mutateAsync: createSource } = useCreateSource();

const analyticsService = useAnalyticsService();
const trackNewSourceAction = useTrackAction(TrackActionType.NEW_SOURCE);

const getSourceDefinitionById = (id: string) => sourceDefinitions.find((item) => item.sourceDefinitionId === id);

Expand Down Expand Up @@ -64,10 +64,9 @@ const SourceStep: React.FC<IProps> = ({ onNextStep, onSuccess }) => {
const onServiceSelect = (sourceId: string) => {
const sourceDefinition = getSourceDefinitionById(sourceId);

analyticsService.track("New Source - Action", {
action: "Select a connector",
trackNewSourceAction("Select a connector", {
connector_source: sourceDefinition?.name,
connector_source_id: sourceDefinition?.sourceDefinitionId,
connector_source_definition_id: sourceDefinition?.sourceDefinitionId,
});

setError(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { FormattedMessage } from "react-intl";
import { ConnectionConfiguration } from "core/domain/connection";
import { SourceDefinition } from "core/domain/connector";
import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import useRouter from "hooks/useRouter";
import { TrackActionType, useTrackAction } from "hooks/useTrackAction";
import { useGetSourceDefinitionSpecificationAsync } from "services/connector/SourceDefinitionSpecificationService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
Expand Down Expand Up @@ -34,7 +34,7 @@ const hasSourceDefinitionId = (state: unknown): state is { sourceDefinitionId: s

const SourceForm: React.FC<IProps> = ({ onSubmit, sourceDefinitions, error, hasSuccess, afterSelectConnector }) => {
const { location } = useRouter();
const analyticsService = useAnalyticsService();
const trackNewSourceAction = useTrackAction(TrackActionType.NEW_SOURCE);

const [sourceDefinitionId, setSourceDefinitionId] = useState<string | null>(
hasSourceDefinitionId(location.state) ? location.state.sourceDefinitionId : null
Expand All @@ -54,9 +54,8 @@ const SourceForm: React.FC<IProps> = ({ onSubmit, sourceDefinitions, error, hasS
afterSelectConnector();
}

analyticsService.track("New Source - Action", {
action: "Select a connector",
connector_source_definition: connector?.name,
trackNewSourceAction("Select a connector", {
connector_source: connector?.name,
connector_source_definition_id: sourceDefinitionId,
});
};
Expand Down
51 changes: 32 additions & 19 deletions airbyte-webapp/src/views/Connector/ConnectorCard/ConnectorCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import JobItem from "components/JobItem";
import { Connector, ConnectorT, Scheduler } from "core/domain/connector";
import { JobInfo } from "core/domain/job/Job";
import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalytics } from "hooks/services/Analytics";
import { TrackActionType, useTrackAction } from "hooks/useTrackAction";
import { createFormErrorMessage } from "utils/errorStatusMessage";
import { ServiceForm, ServiceFormProps, ServiceFormValues } from "views/Connector/ServiceForm";

Expand Down Expand Up @@ -39,33 +39,46 @@ const ConnectorCard: React.FC<

const { testConnector, isTestConnectionInProgress, onStopTesting, error } = useTestConnector(props);

const analyticsService = useAnalytics().service;
const trackNewSourceAction = useTrackAction(TrackActionType.NEW_SOURCE);
const trackNewDestinationAction = useTrackAction(TrackActionType.NEW_DESTINATION);

const onHandleSubmit = async (values: ServiceFormValues) => {
setErrorStatusRequest(null);

const connector = props.availableServices.find((item) => Connector.id(item) === values.serviceType);

try {
if (connector) {
if (props.formType === "source") {
analyticsService.track("New Source - Action", {
action: "Test a connector",
connector_source: connector?.name,
connector_source_definition_id: Connector.id(connector),
});
} else {
analyticsService.track("New Destination - Action", {
action: "Test a connector",
connector_destination: connector?.name,
connector_destination_definition_id: Connector.id(connector),
});
}
const trackAction = (action: string) => {
if (!connector) {
return;
}

await testConnector(values);
await onSubmit(values);
if (props.formType === "source") {
trackNewSourceAction(action, {
connector_source: connector?.name,
connector_source_definition_id: Connector.id(connector),
});
} else {
trackNewDestinationAction(action, {
connector_destination: connector?.name,
connector_destination_definition_id: Connector.id(connector),
});
}
};

const testConnectorWithTracking = async () => {
trackAction("Test a connector");
try {
await testConnector(values);
trackAction("Tested connector - success");
} catch (e) {
trackAction("Tested connector - failure");
throw e;
}
};

try {
await testConnectorWithTracking();
await onSubmit(values);
setSaved(true);
} catch (e) {
setErrorStatusRequest(e);
Expand Down

0 comments on commit 7e79cac

Please sign in to comment.