Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
grahamlangford committed Jul 9, 2024
1 parent 482f52a commit 3bd672d
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 97 deletions.
8 changes: 4 additions & 4 deletions src/background/telemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
TEST_flushAll,
} from "@/background/telemetry";
import { appApiMock } from "@/testUtils/appApiMock";
import { type Event } from "@/telemetry/events";
import { type TelemetryEvent } from "@/telemetry/telemetryTypes";

const EXPECTED_RUNTIME_ID = "abc123";
const expectedManifestValues = {
Expand Down Expand Up @@ -53,13 +53,13 @@ beforeEach(async () => {

describe("recordEvent", () => {
test("runs", async () => {
await recordEvent({ event: "TestEvent" as Event, data: {} });
await recordEvent({ event: "TestEvent" as TelemetryEvent, data: {} });
const events = await flushEvents();
expect(events).toHaveLength(1);
});

test("includes expected default properties", async () => {
const testEvent = { event: "TestEvent" as Event, data: {} };
const testEvent = { event: "TestEvent" as TelemetryEvent, data: {} };
await recordEvent(testEvent);
const events = await flushEvents();
expect(events[0]).toMatchObject({
Expand All @@ -76,7 +76,7 @@ describe("recordEvent", () => {
test("successfully persists concurrent telemetry events to local storage", async () => {
// Easiest way to test race condition without having to mock
const recordTestEvents = Array.from({ length: 100 }, async () =>
recordEvent({ event: "TestEvent" as Event, data: {} }),
recordEvent({ event: "TestEvent" as TelemetryEvent, data: {} }),
);
await Promise.all(recordTestEvents);

Expand Down
4 changes: 2 additions & 2 deletions src/background/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { count as logSize } from "@/telemetry/logging";
import { count as traceSize } from "@/telemetry/trace";
import { getUUID } from "@/telemetry/telemetryHelpers";
import { getExtensionVersion, getTabsWithAccess } from "@/utils/extensionUtils";
import { type Event } from "@/telemetry/events";
import { type TelemetryEvent } from "@/telemetry/telemetryTypes";

const EVENT_BUFFER_DEBOUNCE_MS = 2000;
const EVENT_BUFFER_MAX_MS = 10_000;
Expand Down Expand Up @@ -333,7 +333,7 @@ export async function recordEvent({
event,
data = {},
}: {
event: Event;
event: TelemetryEvent;
data: UnknownObject | undefined;
}): Promise<void> {
if (await allowsTrack()) {
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useUserAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@

import { type DependencyList, useCallback } from "react";
import notify from "@/utils/notify";
import { type Event } from "@/telemetry/events";
import { type TelemetryEvent } from "@/telemetry/telemetryTypes";
import { CancelError } from "@/errors/businessErrors";
import reportEvent from "@/telemetry/reportEvent";

type Options = {
event?: Event;
event?: TelemetryEvent;
errorMessage?: string;
successMessage?: string;
};
Expand Down
23 changes: 0 additions & 23 deletions src/telemetry/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,26 +166,3 @@ export const Events = {

SHORTCUT_SNIPPET_RUN: "TextCommandRun",
} as const;

export type Event = (typeof Events)[keyof typeof Events];

const RESERVED_KEYS = [
"blockId",
"blockVersion",
"blueprintId",
"blueprintVersion",
"extensionId",
"extensionLabel",
"extensionPointId",
"extensions",
"recipeId",
"recipeToActivate",
"serviceId",
"serviceVersion",
] as const;

type ReservedKeys = {
[K in (typeof RESERVED_KEYS)[number]]?: never;
};

export type ReportEventData = UnknownObject & ReservedKeys;
2 changes: 1 addition & 1 deletion src/telemetry/initErrorReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import type { LogsEvent } from "@datadog/browser-logs/src/logsEvent.types";
import {
cleanDatadogVersionName,
mapAppUserToTelemetryUser,
type TelemetryUser,
} from "@/telemetry/telemetryHelpers";
import { type TelemetryUser } from "@/telemetry/telemetryTypes";

// eslint-disable-next-line prefer-destructuring -- process.env
const ENVIRONMENT = process.env.ENVIRONMENT;
Expand Down
59 changes: 7 additions & 52 deletions src/telemetry/reportEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
*/

import { backgroundTarget as bg, getNotifier } from "webext-messenger";
import { type Event, type ReportEventData } from "@/telemetry/events";
import { expectContext } from "@/utils/expectContext";
import {
type TelemetryEvent,
type ReportEventData,
} from "@/telemetry/telemetryTypes";
import { mapEventDataToDeprecatedTerminology } from "@/telemetry/telemetryHelpers";

expectContext(
"extension",
Expand All @@ -27,64 +31,15 @@ expectContext(
// Private method. Do not move to api.ts
const _record = getNotifier("RECORD_EVENT", bg);

function transformEventData(data: UnknownObject): UnknownObject {
if (data.brickId) {
data.blockId = data.brickId;
}

if (data.brickVersion) {
data.blockVersion = data.brickVersion;
}

if (data.integrationId) {
data.serviceId = data.integrationId;
}

if (data.integrationVersion) {
data.serviceVersion = data.integrationVersion;
}

if (data.modId) {
data.blueprintId = data.modId;
data.recipeId = data.modId;
}

if (data.modComponentId) {
data.extensionId = data.modComponentId;
}

if (data.modComponentLabel) {
data.extensionLabel = data.modComponentLabel;
}

if (data.modComponents) {
data.extensions = data.modComponents;
}

if (data.modToActivate) {
data.recipeToActivate = data.modToActivate;
}

if (data.modVersion) {
data.blueprintVersion = data.modVersion;
}

if (data.starterBrickId) {
data.extensionPointId = data.starterBrickId;
}

return data;
}

/**
* Report an event to the PixieBrix telemetry service, if the user doesn't have DNT set.
* @see selectEventData
*/
export default function reportEvent<TData extends UnknownObject>(
event: Event,
event: TelemetryEvent,
data: ReportEventData = {},
): void {
// eslint-disable-next-line prefer-rest-params -- Needs `arguments` to avoid printing the default
console.debug(...arguments);
_record({ event, data: transformEventData(data) });
_record({ event, data: mapEventDataToDeprecatedTerminology(data) });
}
64 changes: 52 additions & 12 deletions src/telemetry/telemetryHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,12 @@
*/

import type { UserData } from "@/auth/authTypes";
import { type TelemetryUser } from "@/telemetry/telemetryTypes";
import { uuidv4 } from "@/types/helpers";
import type { UUID } from "@/types/stringTypes";
import { once } from "lodash";
import { StorageItem } from "webext-storage";

/**
* The Person model for application error telemetry.
*/
export type TelemetryUser = {
/**
* User id or browser distinct id, if the user is anonymous.
*/
id: UUID;
email?: string;
organizationId?: UUID | null;
};

export const uuidStorage = new StorageItem<UUID>("USER_UUID");

/**
Expand Down Expand Up @@ -97,3 +86,54 @@ export async function mapAppUserToTelemetryUser(
organizationId: telemetryOrganizationId ?? organizationId,
};
}

export function mapEventDataToDeprecatedTerminology(
data: UnknownObject,
): UnknownObject {
if (data.brickId) {
data.blockId = data.brickId;
}

if (data.brickVersion) {
data.blockVersion = data.brickVersion;
}

if (data.integrationId) {
data.serviceId = data.integrationId;
}

if (data.integrationVersion) {
data.serviceVersion = data.integrationVersion;
}

if (data.modId) {
data.blueprintId = data.modId;
data.recipeId = data.modId;
}

if (data.modComponentId) {
data.extensionId = data.modComponentId;
}

if (data.modComponentLabel) {
data.extensionLabel = data.modComponentLabel;
}

if (data.modComponents) {
data.extensions = data.modComponents;
}

if (data.modToActivate) {
data.recipeToActivate = data.modToActivate;
}

if (data.modVersion) {
data.blueprintVersion = data.modVersion;
}

if (data.starterBrickId) {
data.extensionPointId = data.starterBrickId;
}

return data;
}
54 changes: 54 additions & 0 deletions src/telemetry/telemetryTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*

Check failure on line 1 in src/telemetry/telemetryTypes.ts

View workflow job for this annotation

GitHub Actions / strictNullChecks

strictNullChecks

src/telemetry/telemetryTypes.ts was not found in tsconfig.strictNullChecks.json
* Copyright (C) 2024 PixieBrix, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { type Events } from "@/telemetry/events";
import { type UUID } from "@/types/stringTypes";

/**
* The Person model for application error telemetry.
*/
export type TelemetryUser = {
/**
* User id or browser distinct id, if the user is anonymous.
*/
id: UUID;
email?: string;
organizationId?: UUID | null;
};

export type TelemetryEvent = (typeof Events)[keyof typeof Events];

const RESERVED_KEYS = [
"blockId",
"blockVersion",
"blueprintId",
"blueprintVersion",
"extensionId",
"extensionLabel",
"extensionPointId",
"extensions",
"recipeId",
"recipeToActivate",
"serviceId",
"serviceVersion",
] as const;

type ReservedKeys = {
[K in (typeof RESERVED_KEYS)[number]]?: never;
};

export type ReportEventData = UnknownObject & ReservedKeys;
2 changes: 1 addition & 1 deletion src/tinyPages/offscreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

import type { MessageContext } from "@/types/loggerTypes";
import { type TelemetryUser } from "@/telemetry/telemetryHelpers";
import { type TelemetryUser } from "@/telemetry/telemetryTypes";
import { type SemVerString } from "@/types/registryTypes";
import { type SerializedError } from "@/types/messengerTypes";
import { deserializeError } from "serialize-error";
Expand Down

0 comments on commit 3bd672d

Please sign in to comment.