Skip to content

Commit

Permalink
🪟🔧Update Segment tracking event names (#13859)
Browse files Browse the repository at this point in the history
* wip

* Update high priority segment calls

* other segment calls use new format

* allow for non-legacy segment calls

* comment

* cleanup

* use single TrackActionAction

* renames from code review

* typo fix

* WIP connect hook to react hooks testing library

* test parsing of legacy namespace

* cleanup
  • Loading branch information
teallarson authored Jul 8, 2022
1 parent 111ccce commit df24831
Show file tree
Hide file tree
Showing 14 changed files with 182 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { JobItem } from "components/JobItem/JobItem";
import LoadingSchema from "components/LoadingSchema";

import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { useCreateConnection, ValuesProps } from "hooks/services/useConnectionHook";
import { TrackActionLegacyType, TrackActionType, TrackActionNamespace, useTrackAction } from "hooks/useTrackAction";
import ConnectionForm from "views/Connection/ConnectionForm";
import { ConnectionFormProps } from "views/Connection/ConnectionForm/ConnectionForm";
import { FormikConnectionFormValues } from "views/Connection/ConnectionForm/formConfig";
Expand Down Expand Up @@ -43,7 +43,10 @@ const CreateConnectionContent: React.FC<CreateConnectionContentProps> = ({
noTitles,
}) => {
const { mutateAsync: createConnection } = useCreateConnection();
const analyticsService = useAnalyticsService();
const trackNewConnectionAction = useTrackAction(
TrackActionNamespace.CONNECTION,
TrackActionLegacyType.NEW_CONNECTION
);

const { schema, isLoading, schemaErrorStatus, catalogId, onDiscoverSchema } = useDiscoverSchema(source.sourceId);

Expand Down Expand Up @@ -87,14 +90,19 @@ const CreateConnectionContent: React.FC<CreateConnectionContentProps> = ({
};

const onSelectFrequency = (item: IDataItem | null) => {
analyticsService.track("New Connection - Action", {
action: "Select a frequency",
frequency: item?.label,
connector_source_definition: source?.sourceName,
connector_source_definition_id: source?.sourceDefinitionId,
connector_destination_definition: destination?.destinationName,
connector_destination_definition_id: destination?.destinationDefinitionId,
});
const enabledStreams = connection.syncCatalog.streams.filter((stream) => stream.config?.selected).length;

if (item) {
trackNewConnectionAction("Select a frequency", TrackActionType.FREQUENCY, {
frequency: item.label,
connector_source_definition: source?.sourceName,
connector_source_definition_id: source?.sourceDefinitionId,
connector_destination_definition: destination?.destinationName,
connector_destination_definition_id: destination?.destinationDefinitionId,
available_streams: connection.syncCatalog.streams.length,
enabled_streams: enabledStreams,
});
}
};

if (schemaErrorStatus) {
Expand Down
22 changes: 15 additions & 7 deletions airbyte-webapp/src/components/EntityTable/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getFrequencyConfig } from "config/utils";
import { buildConnectionUpdate } from "core/domain/connection";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { useSyncConnection, useUpdateConnection } from "hooks/services/useConnectionHook";
import { TrackActionLegacyType, TrackActionType, TrackActionNamespace, useTrackAction } from "hooks/useTrackAction";

import { ConnectionStatus, WebBackendConnectionRead } from "../../core/request/AirbyteClient";

Expand All @@ -11,7 +11,7 @@ const useSyncActions = (): {
} => {
const { mutateAsync: updateConnection } = useUpdateConnection();
const { mutateAsync: syncConnection } = useSyncConnection();
const analyticsService = useAnalyticsService();
const trackSourceAction = useTrackAction(TrackActionNamespace.CONNECTION, TrackActionLegacyType.SOURCE);

const changeStatus = async (connection: WebBackendConnectionRead) => {
await updateConnection(
Expand All @@ -22,13 +22,21 @@ const useSyncActions = (): {

const frequency = getFrequencyConfig(connection.schedule);

analyticsService.track("Source - Action", {
action: connection.status === "active" ? "Disable connection" : "Reenable connection",
const enabledStreams = connection.syncCatalog.streams.filter((stream) => stream.config?.selected).length;

const trackableAction =
connection.status === ConnectionStatus.active ? TrackActionType.DISABLE : TrackActionType.REENABLE;

const trackableActionString = `${trackableAction} connection`;

trackSourceAction(trackableActionString, trackableAction, {
frequency: frequency?.type,
connector_source: connection.source?.sourceName,
connector_source_id: connection.source?.sourceDefinitionId,
connector_destination: connection.destination?.destinationName,
connector_source_definition_id: connection.source?.sourceDefinitionId,
connector_destination: connection.destination?.name,
connector_destination_definition_id: connection.destination?.destinationDefinitionId,
frequency: frequency?.type,
available_streams: connection.syncCatalog.streams.length,
enabled_streams: enabledStreams,
});
};

Expand Down
19 changes: 10 additions & 9 deletions airbyte-webapp/src/hooks/services/useConnectionHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getFrequencyConfig } from "config/utils";
import { SyncSchema } from "core/domain/catalog";
import { WebBackendConnectionService } from "core/domain/connection";
import { ConnectionService } from "core/domain/connection/ConnectionService";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { TrackActionLegacyType, useTrackAction, TrackActionNamespace, TrackActionType } from "hooks/useTrackAction";
import { useInitService } from "services/useInitService";

import { useConfig } from "../../config";
Expand Down Expand Up @@ -88,15 +88,14 @@ export const useConnectionLoad = (

export const useSyncConnection = () => {
const service = useConnectionService();
const analyticsService = useAnalyticsService();
const trackSourceAction = useTrackAction(TrackActionNamespace.SOURCE, TrackActionLegacyType.SOURCE);

return useMutation((connection: WebBackendConnectionRead) => {
const frequency = getFrequencyConfig(connection.schedule);

analyticsService.track("Source - Action", {
action: "Full refresh sync",
trackSourceAction("Full refresh sync", TrackActionType.SYNC, {
connector_source: connection.source?.sourceName,
connector_source_id: connection.source?.sourceDefinitionId,
connector_source_definition_id: connection.source?.sourceDefinitionId,
connector_destination: connection.destination?.name,
connector_destination_definition_id: connection.destination?.destinationDefinitionId,
frequency: frequency?.type,
Expand All @@ -121,7 +120,10 @@ const useGetConnection = (connectionId: string, options?: { refetchInterval: num
const useCreateConnection = () => {
const service = useWebConnectionService();
const queryClient = useQueryClient();
const analyticsService = useAnalyticsService();
const trackNewConnectionAction = useTrackAction(
TrackActionNamespace.CONNECTION,
TrackActionLegacyType.NEW_CONNECTION
);

return useMutation(
async ({
Expand All @@ -144,9 +146,8 @@ const useCreateConnection = () => {

const frequencyData = getFrequencyConfig(values.schedule);

analyticsService.track("New Connection - Action", {
action: "Set up connection",
frequency: frequencyData?.type,
trackNewConnectionAction("Set up connection", TrackActionType.CREATE, {
frequency: frequencyData?.type || "",
connector_source_definition: source?.sourceName,
connector_source_definition_id: sourceDefinition?.sourceDefinitionId,
connector_destination_definition: destination?.destinationName,
Expand Down
9 changes: 4 additions & 5 deletions airbyte-webapp/src/hooks/services/useDestinationHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from "react-query";

import { ConnectionConfiguration } from "core/domain/connection";
import { DestinationService } from "core/domain/connector/DestinationService";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { TrackActionLegacyType, TrackActionType, TrackActionNamespace, useTrackAction } from "hooks/useTrackAction";
import { useInitService } from "services/useInitService";
import { isDefined } from "utils/common";

Expand Down Expand Up @@ -92,17 +92,16 @@ const useCreateDestination = () => {
const useDeleteDestination = () => {
const service = useDestinationService();
const queryClient = useQueryClient();
const analyticsService = useAnalyticsService();
const trackDestinationAction = useTrackAction(TrackActionNamespace.DESTINATION, TrackActionLegacyType.SOURCE);

return useMutation(
(payload: { destination: DestinationRead; connectionsWithDestination: WebBackendConnectionRead[] }) =>
service.delete(payload.destination.destinationId),
{
onSuccess: (_data, ctx) => {
analyticsService.track("Destination - Action", {
action: "Delete destination",
trackDestinationAction("Delete destination", TrackActionType.DELETE, {
connector_destination: ctx.destination.destinationName,
connector_destination_id: ctx.destination.destinationDefinitionId,
connector_destination_definition_id: ctx.destination.destinationDefinitionId,
});

queryClient.removeQueries(destinationsKeys.detail(ctx.destination.destinationId));
Expand Down
9 changes: 4 additions & 5 deletions airbyte-webapp/src/hooks/services/useSourceHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SyncSchema } from "core/domain/catalog";
import { ConnectionConfiguration } from "core/domain/connection";
import { SourceService } from "core/domain/connector/SourceService";
import { JobInfo } from "core/domain/job";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { TrackActionLegacyType, TrackActionType, TrackActionNamespace, useTrackAction } from "hooks/useTrackAction";
import { useInitService } from "services/useInitService";
import { isDefined } from "utils/common";

Expand Down Expand Up @@ -98,17 +98,16 @@ const useCreateSource = () => {
const useDeleteSource = () => {
const service = useSourceService();
const queryClient = useQueryClient();
const analyticsService = useAnalyticsService();
const trackSourceAction = useTrackAction(TrackActionNamespace.SOURCE, TrackActionLegacyType.SOURCE);

return useMutation(
(payload: { source: SourceRead; connectionsWithSource: WebBackendConnectionRead[] }) =>
service.delete(payload.source.sourceId),
{
onSuccess: (_data, ctx) => {
analyticsService.track("Source - Action", {
action: "Delete source",
trackSourceAction("Delete source", TrackActionType.DELETE, {
connector_source: ctx.source.sourceName,
connector_source_id: ctx.source.sourceDefinitionId,
connector_source_definition_id: ctx.source.sourceDefinitionId,
});

queryClient.removeQueries(sourcesKeys.detail(ctx.source.sourceId));
Expand Down
36 changes: 36 additions & 0 deletions airbyte-webapp/src/hooks/useTrackAction.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { renderHook } from "@testing-library/react-hooks";

import { useAnalyticsService } from "./services/Analytics/useAnalyticsService";
import { TrackActionLegacyType, TrackActionNamespace, TrackActionType, useTrackAction } from "./useTrackAction";

jest.mock("./services/Analytics/useAnalyticsService", () => {
const mockTrack = jest.fn();
return { useAnalyticsService: () => ({ track: mockTrack }) };
});

describe("With legacy namespace", () => {
test("it parses namespace and legacy name when calling the hook", () => {
const mockUseTrackAction = renderHook(() =>
useTrackAction(TrackActionNamespace.SOURCE, TrackActionLegacyType.NEW_SOURCE)
);
mockUseTrackAction.result.current("test action sent", TrackActionType.CREATE, {});
const analyticsService = useAnalyticsService();

expect(analyticsService.track).toHaveBeenCalledWith(
"Airbyte.UI.Source.Create",
expect.objectContaining({ legacy_event_name: "New Source - Action" })
);
});
});

describe("Without legacy namespace", () => {
test("legacy namespace is passed as empty string if none is received", () => {
const mockUseTrackAction = renderHook(() => useTrackAction(TrackActionNamespace.CONNECTION));
mockUseTrackAction.result.current("another test action", TrackActionType.CREATE, {});
const analyticsService = useAnalyticsService();
expect(analyticsService.track).toHaveBeenCalledWith(
"Airbyte.UI.Connection.Create",
expect.objectContaining({ legacy_event_name: "" })
);
});
});
55 changes: 49 additions & 6 deletions airbyte-webapp/src/hooks/useTrackAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,68 @@ import { useCallback } from "react";

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

export const enum TrackActionType {
export const enum TrackActionLegacyType {
NEW_SOURCE = "New Source",
NEW_DESTINATION = "New Destination",
NEW_CONNECTION = "New Connection",
SOURCE = "Source",
}

interface TrackActionProperties {
export const enum TrackActionType {
CREATE = "Create",
TEST = "Test",
SELECT = "Select",
SUCCESS = "TestSuccess",
FAILURE = "TestFailure",
FREQUENCY = "FrequencySet",
SYNC = "FullRefreshSync",
SCHEMA = "EditSchema",
DISABLE = "Disable",
REENABLE = "Reenable",
DELETE = "Delete",
}

export const enum TrackActionNamespace {
SOURCE = "Source",
DESTINATION = "Destination",
CONNECTION = "Connection",
}

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

export const useTrackAction = (type: TrackActionType) => {
interface TrackConnectionActionProperties {
frequency: string;
connector_source_definition: string;
connector_source_definition_id: string;
connector_destination_definition: string;
connector_destination_definition_id: string;
available_streams: number;
enabled_streams: number;
}

export const useTrackAction = (namespace: TrackActionNamespace, legacyType?: TrackActionLegacyType) => {
const analyticsService = useAnalyticsService();

return useCallback(
(action: string, properties: TrackActionProperties) => {
analyticsService.track(`${type} - Action`, { action, ...properties });
(
actionDescription: string,
actionType: TrackActionType,
properties: TrackConnectorActionProperties | TrackConnectionActionProperties
) => {
// Calls that did not exist in the legacy format will not have a legacy event name
const legacyEventName = legacyType ? `${legacyType} - Action` : "";

analyticsService.track(`Airbyte.UI.${namespace}.${actionType}`, {
actionDescription,
...properties,
legacy_event_name: legacyEventName,
});
},
[analyticsService, type]
[analyticsService, namespace, legacyType]
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import HeadTitle from "components/HeadTitle";

import { getFrequencyConfig } from "config/utils";
import { ConnectionStatus } from "core/request/AirbyteClient";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { useGetConnection } from "hooks/services/useConnectionHook";
import { TrackActionLegacyType, TrackActionType, TrackActionNamespace, useTrackAction } from "hooks/useTrackAction";
import TransformationView from "pages/ConnectionPage/pages/ConnectionItemPage/components/TransformationView";

import ConnectionPageTitle from "./components/ConnectionPageTitle";
Expand All @@ -29,15 +29,14 @@ const ConnectionItemPage: React.FC = () => {

const { source, destination } = connection;

const analyticsService = useAnalyticsService();

const frequency = getFrequencyConfig(connection.schedule);

const trackSourceAction = useTrackAction(TrackActionNamespace.SOURCE, TrackActionLegacyType.SOURCE);

const onAfterSaveSchema = () => {
analyticsService.track("Source - Action", {
action: "Edit schema",
trackSourceAction("Edit schema", TrackActionType.SCHEMA, {
connector_source: source.sourceName,
connector_source_id: source.sourceDefinitionId,
connector_source_definition_id: source.sourceDefinitionId,
connector_destination: destination.destinationName,
connector_destination_definition_id: destination.destinationDefinitionId,
frequency: frequency?.type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import styled from "styled-components";
import { Switch } from "components";

import { buildConnectionUpdate } from "core/domain/connection";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { useUpdateConnection } from "hooks/services/useConnectionHook";
import { TrackActionLegacyType, TrackActionType, TrackActionNamespace, useTrackAction } from "hooks/useTrackAction";

import { ConnectionStatus, WebBackendConnectionRead } from "../../../../../core/request/AirbyteClient";

Expand Down Expand Up @@ -37,7 +37,7 @@ interface EnabledControlProps {

const EnabledControl: React.FC<EnabledControlProps> = ({ connection, disabled, frequencyType, onStatusUpdating }) => {
const { mutateAsync: updateConnection, isLoading } = useUpdateConnection();
const analyticsService = useAnalyticsService();
const trackSourceAction = useTrackAction(TrackActionNamespace.SOURCE, TrackActionLegacyType.SOURCE);

const onChangeStatus = async () => {
await updateConnection(
Expand All @@ -46,10 +46,14 @@ const EnabledControl: React.FC<EnabledControlProps> = ({ connection, disabled, f
})
);

analyticsService.track("Source - Action", {
action: connection.status === ConnectionStatus.active ? "Disable connection" : "Reenable connection",
const trackableAction =
connection.status === ConnectionStatus.active ? TrackActionType.DISABLE : TrackActionType.REENABLE;

const trackableActionString = `${trackableAction} connection`;

trackSourceAction(trackableActionString, trackableAction, {
connector_source: connection.source?.sourceName,
connector_source_id: connection.source?.sourceDefinitionId,
connector_source_definition_id: connection.source?.sourceDefinitionId,
connector_destination: connection.destination?.name,
connector_destination_definition_id: connection.destination?.destinationDefinitionId,
frequency: frequencyType,
Expand Down
Loading

0 comments on commit df24831

Please sign in to comment.