Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/smooth-flowers-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudflare/workers-utils": minor
---

Improve `PackageJSON` type definition to use `Record<string, string>` for `dependencies`, `devDependencies`, and `scripts`.
7 changes: 7 additions & 0 deletions .changeset/smooth-flowers-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/workers-utils": minor
---

Add `getTelemetryDataCatalogWorkerURL` environment variable factory

Adds a new environment variable factory for `TELEMETRY_DATA_CATALOG_WORKER_URL` which configures the telemetry data catalog endpoint. Also improves PackageJSON type definitions to use `Record<string, string>` for dependencies, devDependencies, and scripts fields.
15 changes: 15 additions & 0 deletions .changeset/tidy-carrots-dance.md
Copy link
Contributor

Choose a reason for hiding this comment

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

i think we have a telemetry.md file, can you add this to that?

Copy link
Member Author

Choose a reason for hiding this comment

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

maybe.... but in regards to TELEMETRY_DATA_CATALOG_WORKER_URL I thought that maybe we could not surface this too much? it is mainly for us (for manual testing and unit testing). It would be part of the public API but users shouldn't really have a reason to mess with this (and if they want to disable this they could just do so by disabling all the wrangler telemetry). what do you think? 🙂

Regarding the other info, I checked and I think telemetry.md more or less generally included this type of information being collected, but I'll double check to see if that's actually the case 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

oh i don't mean the env var, i meant it would be good to include this list of what we collect in the telemetry.md file for transparency - dependency info (and account ids) is the big new one i guess

Copy link
Member Author

Choose a reason for hiding this comment

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

ah ok, sure 🙂👍

Copy link
Member Author

Choose a reason for hiding this comment

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

Info added: 6b4c759

Please let me if you think this is good 🙂

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"wrangler": minor
---

Add telemetry data catalog collection to wrangler deployments

Wrangler now sends anonymized usage data to a telemetry data catalog during `wrangler deploy`. This includes:

- Account ID and Worker name
- Wrangler version and package manager used
- Deployment timestamp
- Binding type counts (how many KV namespaces, R2 buckets, D1 databases, etc.)
- Public project dependency information (package names and versions from public packages in the package.json `dependencies` field)

This data helps the Cloudflare team understand Wrangler usage patterns. This telemetry respects the user's existing telemetry settings.
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ type VariableNames =
| "DOCKER_HOST"

/** Environment variable used to signal that the current process is being run by the open-next deploy command. */
| "OPEN_NEXT_DEPLOY";
| "OPEN_NEXT_DEPLOY"

/** URL for the telemetry data catalog worker (defaults to `""` in vitest, the production data collector worker otherwise; falsy disables collection). */
| "TELEMETRY_DATA_CATALOG_WORKER_URL";
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
| "TELEMETRY_DATA_CATALOG_WORKER_URL";
| "WRANGLER_TELEMETRY_WORKER_URL";

? to make it clear its for wrangler i guess

Copy link
Member Author

Choose a reason for hiding this comment

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

I was actually trying to distinguish this from "standard telemetry"... if we're going to have two different types of telemetry it'd be nice if we could have name them differently.... 🤔

PS: DATA_CATALOG is also probably not a hugely helpful term here? 😅

Copy link
Member

Choose a reason for hiding this comment

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

package catalog?

I do agree with Emily that we should count all of this stuff as the same currently. If we do break it up in the future we should do that more deliberately.

Copy link
Member Author

Choose a reason for hiding this comment

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

package catalog?

That's what you sort of initially suggested I think, the issue with that for me is that we also include the bindings count info though 😓 (which seems a bit unrelated to packages to me?)

I do agree with Emily that we should count all of this stuff as the same currently. If we do break it up in the future we should do that more deliberately.

sorry, when I said "two different types of telemetry" I meant this new telemetry data collection vs amplitude, these are going to be differently right of the bat, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

for a user, i don't think we should make any distinction in different types of telemetry

but this env var is for internal use, and we might want to use it for stuff outside wrangler in the future, so idm whatever its called 🤷

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't have a super strong preference either 😅

I think it's unlikely for this to be used by other tools and not just wrangler... but it might happen? 🤷

I'm also happy with whatever name here 😄


type DeprecatedNames =
| "CF_ACCOUNT_ID"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,45 @@ export const getCfFetchPathFromEnv = getEnvironmentVariableFactory({
export const getWranglerCacheDirFromEnv = getEnvironmentVariableFactory({
variableName: "WRANGLER_CACHE_DIR",
});

/**
* `TELEMETRY_DATA_CATALOG_WORKER_URL` specifies the URL for the telemetry data catalog worker that can be used
* to customize where wrangler sends the data. Setting this value to an empty string (`""`) disables the data collection altogether.
*/
const getEnvTelemetryDataCatalogWorkerURL = getEnvironmentVariableFactory({
variableName: "TELEMETRY_DATA_CATALOG_WORKER_URL",
});

/**
* Gets the URL or the worker to send the telemetry catalog data to
*
* @param complianceConfig Configuration containing the compliance region setting
* @returns The telemetry data catalog worker URL, or undefined if the data shouldn't be collected
*/
export function getTelemetryDataCatalogWorkerURL(
complianceConfig: ComplianceConfig
): string | undefined {
const envUrl = getEnvTelemetryDataCatalogWorkerURL();
if (envUrl !== undefined) {
// If a value has been specifically set via the `TELEMETRY_DATA_CATALOG_WORKER_URL`
// env variable we honor that
return envUrl;
}

if (getComplianceRegionSubdomain(complianceConfig)) {
// We don't currently collect data for compliance regions
return undefined;
}

if (getStagingSubdomain()) {
// We don't currently collect data for staging
return undefined;
}

if (typeof vitest !== "undefined") {
// This function is run in a test suite skip data collecting
return undefined;
}

return "https://telemetry-data-catalog-collector.devprod.workers.dev";
}
7 changes: 4 additions & 3 deletions packages/workers-utils/src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,10 @@ export function parseTOML(tomlContent: string, filePath?: string): unknown {
export type PackageJSON = {
name?: string;
version?: string;
devDependencies?: Record<string, unknown>;
dependencies?: Record<string, unknown>;
scripts?: Record<string, unknown>;
devDependencies?: Record<string, string>;
dependencies?: Record<string, string>;
scripts?: Record<string, string>;
private?: boolean;
};

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { afterEach, beforeEach, describe, it, vi } from "vitest";
import { getTelemetryDataCatalogWorkerURL } from "../../src/environment-variables/misc-variables";

describe("getTelemetryDataCatalogWorkerURL", () => {
beforeEach(() => {
vi.unstubAllEnvs();
});

afterEach(() => {
vi.unstubAllEnvs();
});

it("should return the env URL if TELEMETRY_DATA_CATALOG_WORKER_URL is set", ({
expect,
}) => {
vi.stubEnv(
"TELEMETRY_DATA_CATALOG_WORKER_URL",
"http://custom-telemetry.example.com"
);

const url = getTelemetryDataCatalogWorkerURL({
compliance_region: "public",
});

expect(url).toBe("http://custom-telemetry.example.com");
});

it("should return empty string if TELEMETRY_DATA_CATALOG_WORKER_URL is set to empty string", ({
expect,
}) => {
vi.stubEnv("TELEMETRY_DATA_CATALOG_WORKER_URL", "");

const url = getTelemetryDataCatalogWorkerURL({
compliance_region: "public",
});

expect(url).toBe("");
});

it("should return undefined for fedramp_high compliance region when env URL is not set", ({
expect,
}) => {
const url = getTelemetryDataCatalogWorkerURL({
compliance_region: "fedramp_high",
});

expect(url).toBeUndefined();
});

it("should return undefined for fedramp_high compliance region from env when env URL is not set", ({
expect,
}) => {
vi.stubEnv("CLOUDFLARE_COMPLIANCE_REGION", "fedramp_high");

const url = getTelemetryDataCatalogWorkerURL({});

expect(url).toBeUndefined();
});

it("should return undefined for staging environment when env URL is not set", ({
expect,
}) => {
vi.stubEnv("WRANGLER_API_ENVIRONMENT", "staging");

const url = getTelemetryDataCatalogWorkerURL({
compliance_region: "public",
});

expect(url).toBeUndefined();
});

it("should honor env URL even for compliance regions", ({ expect }) => {
vi.stubEnv(
"TELEMETRY_DATA_CATALOG_WORKER_URL",
"http://custom-telemetry.example.com"
);

const url = getTelemetryDataCatalogWorkerURL({
compliance_region: "fedramp_high",
});

// When the env URL is explicitly set, it takes precedence
expect(url).toBe("http://custom-telemetry.example.com");
});

it("should honor env URL even for staging environment", ({ expect }) => {
vi.stubEnv(
"TELEMETRY_DATA_CATALOG_WORKER_URL",
"http://custom-telemetry.example.com"
);
vi.stubEnv("WRANGLER_API_ENVIRONMENT", "staging");

const url = getTelemetryDataCatalogWorkerURL({
compliance_region: "public",
});

// When the env URL is explicitly set, it takes precedence
expect(url).toBe("http://custom-telemetry.example.com");
});

// Note: We cannot easily test the "typeof vitest !== 'undefined'" branch
// from within vitest itself, since vitest is always defined in this context.
// The production URL return case is effectively tested by the fact that
// we're running in vitest, so the function returns undefined instead of
// the production URL. This behavior is tested implicitly in other test suites
// that mock the TELEMETRY_DATA_CATALOG_WORKER_URL to avoid skipping the function.
});
4 changes: 4 additions & 0 deletions packages/workers-utils/vitest.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare global {
const vitest: unknown;
}
export {};
4 changes: 2 additions & 2 deletions packages/wrangler/src/__tests__/deploy/assets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { writeWranglerConfig } from "@cloudflare/workers-utils/test-helpers";
import { http, HttpResponse } from "msw";
import dedent from "ts-dedent";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { clearOutputFilePath } from "../../output";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { clearDialogs } from "../helpers/mock-dialogs";
Expand Down Expand Up @@ -54,7 +54,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
}));

vi.mock("../../autoconfig/run");
vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/wrangler/src/__tests__/deploy/bindings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { sync } from "command-exists";
import { http, HttpResponse } from "msw";
import * as TOML from "smol-toml";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { clearOutputFilePath } from "../../output";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { clearDialogs } from "../helpers/mock-dialogs";
Expand Down Expand Up @@ -55,7 +55,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
}));

vi.mock("../../autoconfig/run");
vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/wrangler/src/__tests__/deploy/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import {
import * as esbuild from "esbuild";
import { http, HttpResponse } from "msw";
import { afterEach, beforeEach, describe, expect, it, test, vi } from "vitest";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { printBundleSize } from "../../deployment-bundle/bundle-reporter";
import { clearOutputFilePath } from "../../output";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { diagnoseScriptSizeError } from "../../utils/friendly-validator-errors";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { clearDialogs } from "../helpers/mock-dialogs";
Expand Down Expand Up @@ -58,7 +58,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
}));

vi.mock("../../autoconfig/run");
vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
} from "@cloudflare/workers-utils/test-helpers";
import { http, HttpResponse } from "msw";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { clearOutputFilePath } from "../../output";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { clearDialogs, mockConfirm } from "../helpers/mock-dialogs";
Expand Down Expand Up @@ -65,7 +65,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
},
}));

vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/wrangler/src/__tests__/deploy/core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import * as TOML from "smol-toml";
import dedent from "ts-dedent";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { Static } from "../../autoconfig/frameworks/static";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { runAutoConfig } from "../../autoconfig/run";
import { clearOutputFilePath } from "../../output";
import { NpmPackageManager } from "../../package-manager";
import { writeAuthConfigFile } from "../../user";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockAuthDomain } from "../helpers/mock-auth-domain";
import { mockConsoleMethods } from "../helpers/mock-console";
Expand Down Expand Up @@ -77,7 +77,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
}));

vi.mock("../../autoconfig/run");
vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import * as fs from "node:fs";
import { writeWranglerConfig } from "@cloudflare/workers-utils/test-helpers";
import { http, HttpResponse } from "msw";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { clearOutputFilePath } from "../../output";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { clearDialogs } from "../helpers/mock-dialogs";
Expand Down Expand Up @@ -50,7 +50,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
}));

vi.mock("../../autoconfig/run");
vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/wrangler/src/__tests__/deploy/entry-points.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import * as esbuild from "esbuild";
import { http, HttpResponse } from "msw";
import dedent from "ts-dedent";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { clearOutputFilePath } from "../../output";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { clearDialogs, mockConfirm, mockPrompt } from "../helpers/mock-dialogs";
Expand Down Expand Up @@ -64,7 +64,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
}));

vi.mock("../../autoconfig/run");
vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/wrangler/src/__tests__/deploy/environments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import {
} from "@cloudflare/workers-utils/test-helpers";
import { http, HttpResponse } from "msw";
import { afterEach, beforeEach, describe, expect, it, test, vi } from "vitest";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { clearOutputFilePath } from "../../output";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { clearDialogs } from "../helpers/mock-dialogs";
Expand Down Expand Up @@ -57,7 +57,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
}));

vi.mock("../../autoconfig/run");
vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/wrangler/src/__tests__/deploy/formats.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import * as esbuild from "esbuild";
import { http, HttpResponse } from "msw";
import dedent from "ts-dedent";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getInstalledPackageVersion } from "../../autoconfig/frameworks/utils/packages";
import { clearOutputFilePath } from "../../output";
import { fetchSecrets } from "../../utils/fetch-secrets";
import { getInstalledPackageVersion } from "../../utils/packages";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { clearDialogs } from "../helpers/mock-dialogs";
Expand Down Expand Up @@ -55,7 +55,7 @@ vi.mock("../../package-manager", async (importOriginal) => ({
}));

vi.mock("../../autoconfig/run");
vi.mock("../../autoconfig/frameworks/utils/packages");
vi.mock("../../utils/packages");
vi.mock("../../autoconfig/c3-vendor/command");

describe("deploy", () => {
Expand Down
Loading
Loading