Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send Crash Reports to Sentry #4571

Merged
merged 6 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions .github/workflows/create-pullrequest-prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ jobs:
NODE_ENV: "production"
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_PUBLIC_KEY: ${{ secrets.ALGOLIA_PUBLIC_KEY }}
SENTRY_DSN: "https://9edbb8417b284aa2bbead9b4c318918b@sentry10.cfdata.org/583"
penalosa marked this conversation as resolved.
Show resolved Hide resolved
CI_OS: ${{ runner.os }}

- name: Pack miniflare
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/prereleases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ jobs:
# this is the "test/staging" key for sparrow analytics
SPARROW_SOURCE_KEY: "5adf183f94b3436ba78d67f506965998"
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
SENTRY_DSN: "https://9edbb8417b284aa2bbead9b4c318918b@sentry10.cfdata.org/583"
ALGOLIA_PUBLIC_KEY: ${{ secrets.ALGOLIA_PUBLIC_KEY }}
working-directory: packages/wrangler

Expand Down Expand Up @@ -111,6 +112,7 @@ jobs:
NODE_ENV: "production"
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_PUBLIC_KEY: ${{ secrets.ALGOLIA_PUBLIC_KEY }}
SENTRY_DSN: "https://9edbb8417b284aa2bbead9b4c318918b@sentry10.cfdata.org/583"
CI_OS: ${{ runner.os }}

- name: Build & Publish Prerelease Registry
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ jobs:
NPM_PUBLISH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_PUBLIC_KEY: ${{ secrets.ALGOLIA_PUBLIC_KEY }}
SENTRY_DSN: "https://9edbb8417b284aa2bbead9b4c318918b@sentry10.cfdata.org/583"

NODE_ENV: "production"
# This is the "production" key for sparrow analytics.
# Include this here because this step will rebuild Wrangler and needs to have this available
Expand Down
5 changes: 4 additions & 1 deletion packages/wrangler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,12 @@
"@cloudflare/pages-shared": "workspace:^",
"@cloudflare/types": "^6.18.4",
"@cloudflare/workers-tsconfig": "workspace:*",
"https-proxy-agent": "7.0.2",
"@cloudflare/workers-types": "^4.20230914.0",
"@iarna/toml": "^3.0.0",
"@microsoft/api-extractor": "^7.28.3",
"@sentry/node": "^7.86.0",
"@sentry/types": "^7.86.0",
"@sentry/utils": "^7.86.0",
"@types/body-parser": "^1.19.2",
"@types/busboy": "^1.5.0",
"@types/command-exists": "^1.2.0",
Expand Down Expand Up @@ -164,6 +166,7 @@
"get-port": "^6.1.2",
"glob-to-regexp": "0.4.1",
"http-terminator": "^3.2.0",
"https-proxy-agent": "7.0.2",
"ignore": "^5.2.0",
"ink": "^3.2.0",
"ink-select-input": "^4.2.1",
Expand Down
3 changes: 3 additions & 0 deletions packages/wrangler/scripts/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ async function buildMain(flags: BuildFlags = {}) {
...(process.env.ALGOLIA_PUBLIC_KEY
? { ALGOLIA_PUBLIC_KEY: `"${process.env.ALGOLIA_PUBLIC_KEY}"` }
: {}),
...(process.env.SENTRY_DSN
? { SENTRY_DSN: `"${process.env.SENTRY_DSN}"` }
: {}),
},
plugins: [embedWorkersPlugin],
};
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/api/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export async function unstable_dev(
logLevel: options?.logLevel ?? defaultLogLevel,
port: options?.port ?? 0,
updateCheck: options?.updateCheck ?? false,
metricsOptOut: undefined,
penalosa marked this conversation as resolved.
Show resolved Hide resolved
};

//due to Pages adoption of unstable_dev, we can't *just* disable rebuilds and watching. instead, we'll have two versions of startDev, which will converge.
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/generate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export async function generateHandler(args: GenerateArgs) {
_: args._,
$0: args.$0,
experimentalJsonConfig: false,
metricsOptOut: undefined,
});
}

Expand Down
61 changes: 61 additions & 0 deletions packages/wrangler/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import module from "node:module";
import os from "node:os";
import path from "node:path";
import TOML from "@iarna/toml";
import chalk from "chalk";
import { ProxyAgent, setGlobalDispatcher } from "undici";
import makeCLI from "yargs";
import { version as wranglerVersion } from "../package.json";
Expand Down Expand Up @@ -39,13 +41,24 @@ import { initHandler, initOptions } from "./init";
import { kvNamespace, kvKey, kvBulk } from "./kv";
import { logBuildFailure, logger } from "./logger";
import * as metrics from "./metrics";
import {
CURRENT_METRICS_DATE,
getMetricsConfigPath,
writeMetricsConfig,
} from "./metrics/metrics-config";
import { mTlsCertificateCommands } from "./mtls-certificate/cli";
import { pages } from "./pages";
import { formatMessage, ParseError } from "./parse";
import { pubSubCommands } from "./pubsub/pubsub-commands";
import { queues } from "./queues/cli/commands";
import { r2 } from "./r2";
import { secret, secretBulkHandler, secretBulkOptions } from "./secret";
import {
captureGlobalException,
captureWranglerCommand,
closeSentry,
setupSentry,
} from "./sentry";
import { tailOptions, tailHandler } from "./tail";
import { generateTypes } from "./type-generation";
import { printWranglerBanner } from "./update-check";
Expand All @@ -54,6 +67,7 @@ import { vectorize } from "./vectorize/index";
import { whoami } from "./whoami";

import type { Config } from "./config";
import type { OnlyCamelCase } from "./config/config";
import type { CommonYargsArgv, CommonYargsOptions } from "./yargs-types";
import type Yargs from "yargs";

Expand Down Expand Up @@ -201,6 +215,11 @@ export function createCLIParser(argv: string[]) {
describe: `Experimental: Support wrangler.json`,
type: "boolean",
})
.option("metrics-opt-out", {
describe: `Opt out of crash reports & usage metrics, and remember the choice`,
type: "boolean",
hidden: true,
})
penalosa marked this conversation as resolved.
Show resolved Hide resolved
.check((args) => {
// Grab locally specified env params from `.env` file
const loaded = loadDotEnv(".env", args.env);
Expand Down Expand Up @@ -242,6 +261,24 @@ export function createCLIParser(argv: string[]) {
} else {
logger.log(wranglerVersion);
}
} else if (args.metricsOptOut) {
await writeMetricsConfig({
permission: {
enabled: !args.metricsOptOut,
date: CURRENT_METRICS_DATE,
},
});
logger.log(
`${chalk.green(
"Successfully opted out of metrics collection"
)}.\nYour choice has been saved in the following file: ${path.relative(
process.cwd(),
getMetricsConfigPath()
)}.\n\n` +
" You can override the user level setting for a project in `wrangler.toml`:\n\n" +
" - to disable sending metrics for a project: `send_metrics = false`\n" +
" - to enable sending metrics for a project: `send_metrics = true`"
);
} else {
wrangler.showHelp("log");
}
Expand Down Expand Up @@ -700,11 +737,32 @@ export function createCLIParser(argv: string[]) {
return wrangler;
}

export function createConfigArgParser(argv: string[]) {
return makeCLI(argv)
.scriptName("wrangler")

.option("config", {
alias: "c",
describe: "Path to .toml configuration file",
type: "string",
requiresArg: true,
});
}
export async function main(argv: string[]): Promise<void> {
setupSentry();
captureWranglerCommand(argv);

const wrangler = createCLIParser(argv);
try {
await wrangler.parse();
} catch (e) {
const configParser = createConfigArgParser(argv);
const parsed = await configParser.argv;
const config = readConfig(
parsed.config,
{} as OnlyCamelCase<CommonYargsOptions>
);

logger.log(""); // Just adds a bit of space
if (e instanceof CommandLineArgsError) {
logger.error(e.message);
Expand All @@ -720,6 +778,7 @@ export async function main(argv: string[]): Promise<void> {
text: "\nIf you think this is a bug, please open an issue at: https://github.com/cloudflare/workers-sdk/issues/new/choose",
});
logger.log(formatMessage(e));
await captureGlobalException(e, config.send_metrics);
penalosa marked this conversation as resolved.
Show resolved Hide resolved
} else if (
e instanceof Error &&
e.message.includes("Raw mode is not supported on")
Expand Down Expand Up @@ -755,9 +814,11 @@ export async function main(argv: string[]): Promise<void> {
`${fgGreenColor}%s${resetColor}`,
"If you think this is a bug then please create an issue at https://github.com/cloudflare/workers-sdk/issues/new/choose"
);
await captureGlobalException(e, config.send_metrics);
}
throw e;
} finally {
await closeSentry();
// In the bootstrapper script `bin/wrangler.js`, we open an IPC channel, so
// IPC messages from this process are propagated through the bootstrapper.
// Make sure this channel is closed once it's no longer needed, so we can
Expand Down
49 changes: 29 additions & 20 deletions packages/wrangler/src/metrics/metrics-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { getAPIToken } from "../user";
* This allows us to prompt the user to re-opt-in when we make substantive changes to our metrics
* gathering.
*/
export const CURRENT_METRICS_DATE = new Date(2022, 6, 4);
export const CURRENT_METRICS_DATE = new Date(2023, 12, 8);
export const USER_ID_CACHE_PATH = "user-id.json";

export const getWranglerSendMetricsFromEnv = getEnvironmentVariableFactory({
Expand Down Expand Up @@ -100,7 +100,7 @@ export async function getMetricsConfig({
return { enabled: permission.enabled, deviceId, userId };
} else if (permission.enabled) {
logger.log(
"Usage metrics tracking has changed since you last granted permission."
"Usage metrics & crash reporting has changed since you last granted permission."
);
}
}
Expand All @@ -113,24 +113,33 @@ export async function getMetricsConfig({

// Otherwise, let's ask the user and store the result in the metrics config.
const enabled = await confirm(
"Would you like to help improve Wrangler by sending usage metrics to Cloudflare?"
"Would you like to help improve Wrangler by automatically sending crash reports & usage metrics to Cloudflare?"
);
logger.log(
`Your choice has been saved in the following file: ${path.relative(
process.cwd(),
getMetricsConfigPath()
)}.\n\n` +
" You can override the user level setting for a project in `wrangler.toml`:\n\n" +
" - to disable sending metrics for a project: `send_metrics = false`\n" +
" - to enable sending metrics for a project: `send_metrics = true`"
);
writeMetricsConfig({
permission: {
enabled,
date: CURRENT_METRICS_DATE,
},
deviceId,
});
if (enabled) {
logger.log(
`Your choice has been saved in the following file: ${path.relative(
process.cwd(),
getMetricsConfigPath()
)}.\n\n` +
" You can override the user level setting for a project in `wrangler.toml`:\n\n" +
" - to disable sending metrics for a project: `send_metrics = false`\n" +
" - to enable sending metrics for a project: `send_metrics = true`"
);
writeMetricsConfig({
permission: {
enabled,
date: CURRENT_METRICS_DATE,
},
deviceId,
});
} else {
logger.log(
"Not sending crash reports or usage metrics to Cloudflare. For Wrangler to remember this choice, run `wrangler --metrics-opt-out`.\n\n" +
" You can override the user level setting for a project in `wrangler.toml`:\n\n" +
" - to disable sending metrics for a project: `send_metrics = false`\n" +
" - to enable sending metrics for a project: `send_metrics = true`"
);
}
return { enabled, deviceId, userId };
}

Expand Down Expand Up @@ -166,7 +175,7 @@ export function readMetricsConfig(): MetricsConfigFile {
/**
* Get the path to the metrics config file.
*/
function getMetricsConfigPath(): string {
export function getMetricsConfigPath(): string {
return path.resolve(getGlobalWranglerConfigPath(), "metrics.json");
}

Expand Down
Loading
Loading