Skip to content

Commit

Permalink
Stop emitting telemetry from tests and example projects (#320)
Browse files Browse the repository at this point in the history
* test: dont emit telemetry events from tests

* feat: add isCi to telemetry context

* rename to is example project
  • Loading branch information
0xOlias authored Aug 16, 2023
1 parent 8271ee7 commit 22bc524
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 47 deletions.
1 change: 1 addition & 0 deletions packages/core/src/_test/art-gobblers/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const setup = async ({ context }: { context: TestContext }) => {
...options,
uiEnabled: false,
logLevel: "error",
telemetryDisabled: true,
} as const;

const ponder = new Ponder({
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/_test/ens/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const setup = async ({ context }: { context: TestContext }) => {
...options,
uiEnabled: false,
logLevel: "error",
telemetryDisabled: true,
} as const;

const ponder = new Ponder({
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/_test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ declare module "vitest" {
}

beforeEach((context) => {
const options = buildOptions({ cliOptions: { configFile: "", rootDir: "" } });
const options = {
...buildOptions({
cliOptions: { configFile: "", rootDir: "" },
}),
telemetryDisabled: true,
};
context.common = {
options,
logger: new LoggerService({ level: "silent" }),
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/config/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type Options = {
maxHealthcheckDuration: number;
telemetryUrl: string;
telemetryDisabled: boolean;
telemetryIsExampleProject: boolean;

logLevel: LevelWithSilent;
uiEnabled: boolean;
Expand Down Expand Up @@ -58,6 +59,9 @@ export const buildOptions = ({

telemetryUrl: "https://ponder.sh/api/telemetry",
telemetryDisabled: Boolean(process.env.PONDER_TELEMETRY_DISABLED),
telemetryIsExampleProject: Boolean(
process.env.PONDER_TELEMETRY_IS_EXAMPLE_PROJECT
),

logLevel,
uiEnabled: true,
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/telemetry/detached-flush.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import path from "node:path";
import process from "node:process";
import { expect, test } from "vitest";

test("detached flush script should run without error", async ({ common }) => {
test("detached flush script should run without error", async () => {
// This is a service that always responds to POST requests with a 200 OK.
const telemetryUrl = "https://reqres.in/api/users";

const events = Array.from({ length: 5 }, () => ({
event: "test",
payload: {},
Expand All @@ -22,7 +25,7 @@ test("detached flush script should run without error", async ({ common }) => {
stderr: string;
}>((resolve) => {
child_process.exec(
`${process.execPath} ${flushDetachedScriptPath} ${common.options.telemetryUrl} ${telemetryEventsFilePath}`,
`${process.execPath} ${flushDetachedScriptPath} ${telemetryUrl} ${telemetryEventsFilePath}`,
(error, stdout, stderr) => resolve({ error, stdout, stderr })
);
});
Expand All @@ -31,6 +34,6 @@ test("detached flush script should run without error", async ({ common }) => {
expect(stderr).toBe("");
expect(error).toBe(null);
expect(stdout).toContain(
`Sending 5 telemetry events to https://ponder.sh/api/telemetry from temporary file ${telemetryEventsFilePath}`
`Sending 5 telemetry events to ${telemetryUrl} from temporary file ${telemetryEventsFilePath}`
);
});
60 changes: 21 additions & 39 deletions packages/core/src/telemetry/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,26 @@ import child_process from "node:child_process";
import fs from "node:fs";
import { tmpdir } from "node:os";
import path from "path";
import process from "process";
import { afterAll, beforeEach, expect, test, vi } from "vitest";
import { beforeAll, beforeEach, expect, test, vi } from "vitest";

import { buildOptions } from "@/config/options";
import { TelemetryService } from "@/telemetry/service";

// Prevents the detached-flush script from sending events to API during tests.
vi.mock("node-fetch");

const fetchSpy = vi.fn().mockImplementation(() => vi.fn());
const fetchSpy = vi.fn();

beforeEach(() => {
fetchSpy.mockReset();
vi.stubGlobal("fetch", fetchSpy);
return () => vi.unstubAllGlobals();
});

afterAll(() => {
vi.restoreAllMocks();
});

test("should be disabled if PONDER_TELEMETRY_DISABLED flag is set", async () => {
process.env.PONDER_TELEMETRY_DISABLED = "true";

// we're not using the options from the context because we want to test that
// build options will correctly set the telemetry service as disabled if the
// env var is set
const options = buildOptions({ cliOptions: { configFile: "", rootDir: "" } });
const telemetry = new TelemetryService({ options });

expect(telemetry.disabled).toBe(true);

delete process.env.PONDER_TELEMETRY_DISABLED;
beforeAll(() => {
// Prevents the detached-flush script from sending events to API during tests.
vi.mock("node-fetch");
return () => vi.restoreAllMocks();
});

test("events are processed", async ({ common: { options } }) => {
test("events are processed", async (context) => {
const options = { ...context.common.options, telemetryDisabled: false };
const telemetry = new TelemetryService({ options });

telemetry.record({ event: "test", properties: { test: "data" } });
Expand All @@ -54,22 +38,18 @@ test("events are processed", async ({ common: { options } }) => {
});
});

test("events are not processed if telemetry is disabled", async ({
common: { options },
}) => {
const telemetry = new TelemetryService({
options: { ...options, telemetryDisabled: true },
});
test("events are not processed if telemetry is disabled", async (context) => {
const options = { ...context.common.options, telemetryDisabled: true };
const telemetry = new TelemetryService({ options });

telemetry.record({ event: "test" });
await telemetry.flush();

expect(fetchSpy).not.toHaveBeenCalled();
});

test("events are put back in queue if telemetry service is killed", async ({
common: { options },
}) => {
test("events are put back in queue if telemetry service is killed", async (context) => {
const options = { ...context.common.options, telemetryDisabled: false };
const telemetry = new TelemetryService({ options });

fetchSpy.mockImplementationOnce(() => {
Expand All @@ -82,14 +62,16 @@ test("events are put back in queue if telemetry service is killed", async ({
expect(telemetry["events"].length).toBe(1);
});

test("kill method should persist events and trigger detached flush", async ({
common: { options },
}) => {
const options_ = { ...options, ponderDir: tmpdir() };
test("kill method should persist events and trigger detached flush", async (context) => {
const options = {
...context.common.options,
telemetryDisabled: false,
ponderDir: tmpdir(),
};

const spawn = vi.spyOn(child_process, "spawn");
const telemetry = new TelemetryService({ options: options_ });
const fileName = path.join(options_.ponderDir, "telemetry-events.json");
const telemetry = new TelemetryService({ options });
const fileName = path.join(options.ponderDir, "telemetry-events.json");

const writeFileSyncSpy = vi
.spyOn(fs, "writeFileSync")
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/telemetry/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,18 @@ type TelemetryDeviceConfig = {
type TelemetryEventContext = {
projectId: string;
sessionId: string;
// package.json information
nodeVersion: string;
packageManager: string;
packageManagerVersion: string;
nodeVersion: string;
ponderVersion: string;
// Software information
systemPlatform: NodeJS.Platform;
systemRelease: string;
systemArchitecture: string;
// Machine information
cpuCount: number;
cpuModel: string | null;
cpuSpeed: number | null;
memoryInMb: number;
isExampleProject: boolean;
};

export class TelemetryService {
Expand Down Expand Up @@ -235,6 +233,7 @@ export class TelemetryService {
cpuModel: cpus.length ? cpus[0].model : null,
cpuSpeed: cpus.length ? cpus[0].speed : null,
memoryInMb: Math.trunc(os.totalmem() / Math.pow(1024, 2)),
isExampleProject: this.options.telemetryIsExampleProject,
} satisfies TelemetryEventContext;

return this.context;
Expand Down

1 comment on commit 22bc524

@vercel
Copy link

@vercel vercel bot commented on 22bc524 Aug 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.