Skip to content

Commit f34219f

Browse files
author
Luca Forstner
authored
fix(core): Fix telemetry option logic (#128)
1 parent 10e8d96 commit f34219f

File tree

9 files changed

+306
-224
lines changed

9 files changed

+306
-224
lines changed

packages/bundler-plugin-core/src/index.ts

Lines changed: 78 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ import {
1111
} from "./sentry/releasePipeline";
1212
import "@sentry/tracing";
1313
import {
14-
addPluginOptionTags,
14+
addPluginOptionInformationToHub,
1515
addSpanToTransaction,
1616
captureMinimalError,
1717
makeSentryClient,
18-
turnOffTelemetryForSelfHostedSentry,
18+
shouldSendTelemetry,
1919
} from "./sentry/telemetry";
2020
import { Span, Transaction } from "@sentry/types";
2121
import { createLogger, Logger } from "./sentry/logger";
2222
import { InternalOptions, normalizeUserOptions, validateOptions } from "./options-mapping";
2323
import { getSentryCli } from "./sentry/cli";
24-
import { Hub } from "@sentry/node";
24+
import { Hub, makeMain } from "@sentry/node";
2525

2626
// We prefix the polyfill id with \0 to tell other plugins not to try to load or transform it.
2727
// This hack is taken straight from https://rollupjs.org/guide/en/#resolveid.
@@ -60,11 +60,21 @@ const ALLOWED_TRANSFORMATION_FILE_ENDINGS = [".js", ".ts", ".jsx", ".tsx", ".cjs
6060
const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
6161
const internalOptions = normalizeUserOptions(options);
6262

63-
const { hub: sentryHub } = makeSentryClient(
63+
const allowedToSendTelemetryPromise = shouldSendTelemetry(internalOptions);
64+
65+
const { sentryHub, sentryClient } = makeSentryClient(
6466
"https://4c2bae7d9fbc413e8f7385f55c515d51@o1.ingest.sentry.io/6690737",
65-
internalOptions.telemetry
67+
allowedToSendTelemetryPromise
6668
);
67-
addPluginOptionTags(internalOptions, sentryHub);
69+
70+
addPluginOptionInformationToHub(internalOptions, sentryHub, unpluginMetaContext.framework);
71+
72+
//TODO: This call is problematic because as soon as we set our hub as the current hub
73+
// we might interfere with other plugins that use Sentry. However, for now, we'll
74+
// leave it in because without it, we can't get distributed traces (which are pretty nice)
75+
// Let's keep it until someone complains about interference.
76+
// The ideal solution would be a code change in the JS SDK but it's not a straight-forward fix.
77+
makeMain(sentryHub);
6878

6979
const logger = createLogger({
7080
hub: sentryHub,
@@ -83,19 +93,14 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
8393

8494
const cli = getSentryCli(internalOptions, logger);
8595

86-
if (internalOptions.telemetry) {
87-
logger.info("Sending error and performance telemetry data to Sentry.");
88-
logger.info("To disable telemetry, set `options.telemetry` to `false`.");
89-
}
90-
91-
sentryHub.setTags({
92-
organization: internalOptions.org,
93-
project: internalOptions.project,
94-
bundler: unpluginMetaContext.framework,
96+
const releaseNamePromise = new Promise<string>((resolve) => {
97+
if (options.release) {
98+
resolve(options.release);
99+
} else {
100+
resolve(cli.releases.proposeVersion());
101+
}
95102
});
96103

97-
sentryHub.setUser({ id: internalOptions.org });
98-
99104
let transaction: Transaction | undefined;
100105
let releaseInjectionSpan: Span | undefined;
101106

@@ -107,14 +112,18 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
107112
* Responsible for starting the plugin execution transaction and the release injection span
108113
*/
109114
async buildStart() {
110-
await turnOffTelemetryForSelfHostedSentry(cli, sentryHub);
115+
logger.debug("Called 'buildStart'");
111116

112-
if (!internalOptions.release) {
113-
internalOptions.release = await cli.releases.proposeVersion();
117+
const isAllowedToSendToSendTelemetry = await allowedToSendTelemetryPromise;
118+
if (isAllowedToSendToSendTelemetry) {
119+
logger.info("Sending error and performance telemetry data to Sentry.");
120+
logger.info("To disable telemetry, set `options.telemetry` to `false`.");
114121
}
115122

123+
const releaseName = await releaseNamePromise;
124+
116125
// At this point, we either have determined a release or we have to bail
117-
if (!internalOptions.release) {
126+
if (!releaseName) {
118127
handleError(
119128
new Error(
120129
"Unable to determine a release name. Make sure to set the `release` option or use an environment that supports auto-detection https://docs.sentry.io/cli/releases/#creating-releases`"
@@ -129,6 +138,7 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
129138
op: "function.plugin",
130139
name: "Sentry Bundler Plugin execution",
131140
});
141+
132142
releaseInjectionSpan = addSpanToTransaction(
133143
{ hub: sentryHub, parentSpan: transaction, logger, cli },
134144
"function.plugin.inject_release",
@@ -148,11 +158,7 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
148158
* @returns `"sentry-release-injector"` when the imported file is called `"sentry-release-injector"`. Otherwise returns `undefined`.
149159
*/
150160
resolveId(id, importer, { isEntry }) {
151-
sentryHub.addBreadcrumb({
152-
category: "resolveId",
153-
message: `isEntry: ${String(isEntry)}`,
154-
level: "info",
155-
});
161+
logger.debug('Called "resolveId":', { id, importer, isEntry });
156162

157163
if (id === RELEASE_INJECTOR_ID) {
158164
return RELEASE_INJECTOR_ID;
@@ -162,7 +168,7 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
162168
},
163169

164170
loadInclude(id) {
165-
logger.info(`Called "loadInclude": ${JSON.stringify({ id })}`);
171+
logger.debug('Called "loadInclude":', { id });
166172
return id === RELEASE_INJECTOR_ID;
167173
},
168174

@@ -173,15 +179,12 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
173179
* @param id Always the absolute (fully resolved) path to the module.
174180
* @returns The global injector code when we load the "sentry-release-injector" module. Otherwise returns `undefined`.
175181
*/
176-
load(id) {
177-
sentryHub.addBreadcrumb({
178-
category: "load",
179-
level: "info",
180-
});
182+
async load(id) {
183+
logger.debug('Called "load":', { id });
181184

182185
if (id === RELEASE_INJECTOR_ID) {
183186
return generateGlobalInjectorCode({
184-
release: internalOptions.release,
187+
release: await releaseNamePromise,
185188
injectReleasesMap: internalOptions.injectReleasesMap,
186189
org: internalOptions.org,
187190
project: internalOptions.project,
@@ -200,10 +203,7 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
200203
* want to transform the release injector file.
201204
*/
202205
transformInclude(id) {
203-
sentryHub.addBreadcrumb({
204-
category: "transformInclude",
205-
level: "info",
206-
});
206+
logger.debug('Called "transformInclude":', { id });
207207

208208
// We don't want to transform our injected code.
209209
if (id === RELEASE_INJECTOR_ID) {
@@ -242,11 +242,8 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
242242
* @param id Always the absolute (fully resolved) path to the module.
243243
* @returns transformed code + source map
244244
*/
245-
transform(code) {
246-
sentryHub.addBreadcrumb({
247-
category: "transform",
248-
level: "info",
249-
});
245+
transform(code, id) {
246+
logger.debug('Called "transform":', { id });
250247

251248
// The MagicString library allows us to generate sourcemaps for the changes we make to the user code.
252249
const ms = new MagicString(code);
@@ -272,7 +269,9 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
272269
* Responsible for executing the sentry release creation pipeline (i.e. creating a release on
273270
* Sentry.io, uploading sourcemaps, associating commits and deploys and finalizing the release)
274271
*/
275-
writeBundle() {
272+
async writeBundle() {
273+
logger.debug('Called "writeBundle"');
274+
276275
releaseInjectionSpan?.finish();
277276
const releasePipelineSpan =
278277
transaction &&
@@ -289,45 +288,58 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
289288

290289
const ctx: BuildContext = { hub: sentryHub, parentSpan: releasePipelineSpan, logger, cli };
291290

292-
createNewRelease(internalOptions, ctx)
293-
.then(() => cleanArtifacts(internalOptions, ctx))
294-
.then(() => uploadSourceMaps(internalOptions, ctx))
295-
.then(() => setCommits(internalOptions, ctx))
296-
.then(() => finalizeRelease(internalOptions, ctx))
297-
.then(() => addDeploy(internalOptions, ctx))
298-
.then(() => transaction?.setStatus("ok"))
299-
.catch((e: Error) => {
300-
transaction?.setStatus("cancelled");
301-
handleError(e, logger, internalOptions.errorHandler, sentryHub);
302-
})
303-
.finally(() => {
304-
sentryHub.addBreadcrumb({
305-
category: "writeBundle:finish",
306-
level: "info",
307-
});
308-
releasePipelineSpan?.finish();
309-
transaction?.finish();
291+
const releaseName = await releaseNamePromise;
292+
293+
try {
294+
await createNewRelease(internalOptions, ctx, releaseName);
295+
await cleanArtifacts(internalOptions, ctx, releaseName);
296+
await uploadSourceMaps(internalOptions, ctx, releaseName);
297+
await setCommits(internalOptions, ctx, releaseName);
298+
await finalizeRelease(internalOptions, ctx, releaseName);
299+
await addDeploy(internalOptions, ctx, releaseName);
300+
transaction?.setStatus("ok");
301+
} catch (e: unknown) {
302+
transaction?.setStatus("cancelled");
303+
handleError(e, logger, internalOptions.errorHandler, sentryHub);
304+
} finally {
305+
sentryHub.addBreadcrumb({
306+
category: "writeBundle:finish",
307+
level: "info",
308+
});
309+
releasePipelineSpan?.finish();
310+
transaction?.finish();
311+
await sentryClient.flush().then(null, () => {
312+
logger.warn("Sending of telemetry failed");
310313
});
314+
}
311315
},
312316
};
313317
});
314318

315319
function handleError(
316-
error: Error,
320+
unknownError: unknown,
317321
logger: Logger,
318322
errorHandler: InternalOptions["errorHandler"],
319323
sentryHub?: Hub
320324
) {
321-
logger.error(error.message);
325+
if (unknownError instanceof Error) {
326+
logger.error(unknownError.message);
327+
} else {
328+
logger.error(String(unknownError));
329+
}
322330

323331
if (sentryHub) {
324-
captureMinimalError(error, sentryHub);
332+
captureMinimalError(unknownError, sentryHub);
325333
}
326334

327335
if (errorHandler) {
328-
errorHandler(error);
336+
if (unknownError instanceof Error) {
337+
errorHandler(unknownError);
338+
} else {
339+
errorHandler(new Error("An unknown error occured"));
340+
}
329341
} else {
330-
throw error;
342+
throw unknownError;
331343
}
332344
}
333345

packages/bundler-plugin-core/src/options-mapping.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { arrayify } from "./utils";
55
type RequiredInternalOptions = Required<
66
Pick<
77
UserOptions,
8-
| "release"
98
| "finalize"
109
| "dryRun"
1110
| "debug"
@@ -114,12 +113,6 @@ export function normalizeUserOptions(userOptions: UserOptions): InternalOptions
114113
configFile: userOptions.configFile,
115114
};
116115

117-
// We only want to enable telemetry for SaaS users
118-
// This is not the final check (we need to call Sentry CLI at a later point)
119-
// but we can already at this point make a first decision.
120-
// @see `turnOffTelemetryForSelfHostedSentry` (telemetry.ts) for the second check.
121-
options.telemetry = options.telemetry && options.url === SENTRY_SAAS_URL;
122-
123116
return options;
124117
}
125118

packages/bundler-plugin-core/src/sentry/logger.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,12 @@ export function createLogger(options: LoggerOptions): Logger {
4848

4949
addBreadcrumb("error", message);
5050
},
51-
5251
debug(message: string, ...params: unknown[]) {
5352
if (!options.silent && options.debug) {
5453
// eslint-disable-next-line no-console
5554
console.log(`${options.prefix} Debug: ${message}`, ...params);
55+
// We're not creating breadcrumbs for debug logs because it is super spammy
5656
}
57-
58-
addBreadcrumb("debug", message);
5957
},
6058
};
6159
}

0 commit comments

Comments
 (0)