Skip to content

meta(changelog): Update changelog for 7.71.0 #9103

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

Merged
merged 16 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions .craft.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,7 @@ targets:
onlyIfPresent: /^sentry-sveltekit-\d.*\.tgz$/
'npm:@sentry/opentelemetry-node':
onlyIfPresent: /^sentry-opentelemetry-node-\d.*\.tgz$/
'npm:@sentry/bun':
onlyIfPresent: /^sentry-bun-\d.*\.tgz$/
'npm:@sentry/vercel-edge':
onlyIfPresent: /^sentry-vercel-edge-\d.*\.tgz$/
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

## 7.71.0

- feat(bun): Instrument Bun.serve (#9080)
- fix(core): Ensure global event processors are always applied to event (#9064)
- fix(core): Run client eventProcessors before global ones (#9032)
- fix(nextjs): Use webpack module paths to attempt to resolve internal request async storage module (#9100)
- fix(react): Add actual error name to boundary error name (#9065)
- fix(react): Compare location against `basename`-prefixed route. (#9076)
- ref(browser): Refactor browser integrations to use `processEvent` (#9022)

Work in this release contributed by @jorrit. Thank you for your contribution!

## 7.70.0

### Important Changes
Expand Down
44 changes: 19 additions & 25 deletions packages/browser/src/integrations/dedupe.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types';
import type { Event, Exception, Integration, StackFrame } from '@sentry/types';
import { logger } from '@sentry/utils';

/** Deduplication filter */
Expand All @@ -22,36 +22,30 @@ export class Dedupe implements Integration {
this.name = Dedupe.id;
}

/** @inheritDoc */
public setupOnce(_addGlobaleventProcessor: unknown, _getCurrentHub: unknown): void {
// noop
}

/**
* @inheritDoc
*/
public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
const eventProcessor: EventProcessor = currentEvent => {
// We want to ignore any non-error type events, e.g. transactions or replays
// These should never be deduped, and also not be compared against as _previousEvent.
if (currentEvent.type) {
return currentEvent;
}
public processEvent(currentEvent: Event): Event | null {
// We want to ignore any non-error type events, e.g. transactions or replays
// These should never be deduped, and also not be compared against as _previousEvent.
if (currentEvent.type) {
return currentEvent;
}

const self = getCurrentHub().getIntegration(Dedupe);
if (self) {
// Juuust in case something goes wrong
try {
if (_shouldDropEvent(currentEvent, self._previousEvent)) {
__DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.');
return null;
}
} catch (_oO) {
return (self._previousEvent = currentEvent);
}

return (self._previousEvent = currentEvent);
// Juuust in case something goes wrong
try {
if (_shouldDropEvent(currentEvent, this._previousEvent)) {
__DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.');
return null;
}
return currentEvent;
};
} catch (_oO) {} // eslint-disable-line no-empty

eventProcessor.id = this.name;
addGlobalEventProcessor(eventProcessor);
return (this._previousEvent = currentEvent);
}
}

Expand Down
47 changes: 23 additions & 24 deletions packages/browser/src/integrations/httpcontext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core';
import type { Event, Integration } from '@sentry/types';

import { WINDOW } from '../helpers';
Expand All @@ -23,28 +22,28 @@ export class HttpContext implements Integration {
* @inheritDoc
*/
public setupOnce(): void {
addGlobalEventProcessor((event: Event) => {
if (getCurrentHub().getIntegration(HttpContext)) {
// if none of the information we want exists, don't bother
if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {
return event;
}

// grab as much info as exists and add it to the event
const url = (event.request && event.request.url) || (WINDOW.location && WINDOW.location.href);
const { referrer } = WINDOW.document || {};
const { userAgent } = WINDOW.navigator || {};

const headers = {
...(event.request && event.request.headers),
...(referrer && { Referer: referrer }),
...(userAgent && { 'User-Agent': userAgent }),
};
const request = { ...event.request, ...(url && { url }), headers };

return { ...event, request };
}
return event;
});
// noop
}

/** @inheritDoc */
public preprocessEvent(event: Event): void {
// if none of the information we want exists, don't bother
if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {
return;
}

// grab as much info as exists and add it to the event
const url = (event.request && event.request.url) || (WINDOW.location && WINDOW.location.href);
const { referrer } = WINDOW.document || {};
const { userAgent } = WINDOW.navigator || {};

const headers = {
...(event.request && event.request.headers),
...(referrer && { Referer: referrer }),
...(userAgent && { 'User-Agent': userAgent }),
};
const request = { ...event.request, ...(url && { url }), headers };

event.request = request;
}
}
2 changes: 1 addition & 1 deletion packages/browser/src/profiling/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class BrowserProfilingIntegration implements Integration {
/**
* @inheritDoc
*/
public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
public setupOnce(_addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
this.getCurrentHub = getCurrentHub;
const client = this.getCurrentHub().getClient() as BrowserClient;

Expand Down
4 changes: 2 additions & 2 deletions packages/bun/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ To use this SDK, call `init(options)` as early as possible in the main entry mod
hook into the environment. Note that you can turn off almost all side effects using the respective options.

```javascript
// ES5 Syntax
// CJS Syntax
const Sentry = require('@sentry/bun');
// ES6 Syntax
// ESM Syntax
import * as Sentry from '@sentry/bun';

Sentry.init({
Expand Down
3 changes: 3 additions & 0 deletions packages/bun/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ export { defaultIntegrations, init } from './sdk';
import { Integrations as CoreIntegrations } from '@sentry/core';
import { Integrations as NodeIntegrations } from '@sentry/node';

import * as BunIntegrations from './integrations';

const INTEGRATIONS = {
...CoreIntegrations,
...NodeIntegrations,
...BunIntegrations,
};

export { INTEGRATIONS as Integrations };
132 changes: 132 additions & 0 deletions packages/bun/src/integrations/bunserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { captureException, getCurrentHub, runWithAsyncContext, startSpan, Transaction } from '@sentry/core';
import type { Integration } from '@sentry/types';
import { addExceptionMechanism, getSanitizedUrlString, parseUrl, tracingContextFromHeaders } from '@sentry/utils';

function sendErrorToSentry(e: unknown): unknown {
captureException(e, scope => {
scope.addEventProcessor(event => {
addExceptionMechanism(event, {
type: 'bun',
handled: false,
data: {
function: 'serve',
},
});
return event;
});

return scope;
});

return e;
}

/**
* Instruments `Bun.serve` to automatically create transactions and capture errors.
*/
export class BunServer implements Integration {
/**
* @inheritDoc
*/
public static id: string = 'BunServer';

/**
* @inheritDoc
*/
public name: string = BunServer.id;

/**
* @inheritDoc
*/
public setupOnce(): void {
instrumentBunServe();
}
}

/**
* Instruments Bun.serve by patching it's options.
*/
export function instrumentBunServe(): void {
Bun.serve = new Proxy(Bun.serve, {
apply(serveTarget, serveThisArg, serveArgs: Parameters<typeof Bun.serve>) {
instrumentBunServeOptions(serveArgs[0]);
return serveTarget.apply(serveThisArg, serveArgs);
},
});
}

/**
* Instruments Bun.serve `fetch` option to automatically create spans and capture errors.
*/
function instrumentBunServeOptions(serveOptions: Parameters<typeof Bun.serve>[0]): void {
serveOptions.fetch = new Proxy(serveOptions.fetch, {
apply(fetchTarget, fetchThisArg, fetchArgs: Parameters<typeof serveOptions.fetch>) {
return runWithAsyncContext(() => {
const hub = getCurrentHub();

const request = fetchArgs[0];
const upperCaseMethod = request.method.toUpperCase();
if (upperCaseMethod === 'OPTIONS' || upperCaseMethod === 'HEAD') {
return fetchTarget.apply(fetchThisArg, fetchArgs);
}

const sentryTrace = request.headers.get('sentry-trace') || '';
const baggage = request.headers.get('baggage');
const { traceparentData, dynamicSamplingContext, propagationContext } = tracingContextFromHeaders(
sentryTrace,
baggage,
);
hub.getScope().setPropagationContext(propagationContext);

const parsedUrl = parseUrl(request.url);
const data: Record<string, unknown> = {
'http.request.method': request.method || 'GET',
};
if (parsedUrl.search) {
data['http.query'] = parsedUrl.search;
}

const url = getSanitizedUrlString(parsedUrl);
return startSpan(
{
op: 'http.server',
name: `${request.method} ${parsedUrl.path || '/'}`,
origin: 'auto.http.bun.serve',
...traceparentData,
data,
metadata: {
source: 'url',
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
request: {
url,
method: request.method,
headers: request.headers.toJSON(),
},
},
},
async span => {
try {
const response = await (fetchTarget.apply(fetchThisArg, fetchArgs) as ReturnType<
typeof serveOptions.fetch
>);
if (response && response.status) {
span?.setHttpStatus(response.status);
span?.setData('http.response.status_code', response.status);
if (span instanceof Transaction) {
span.setContext('response', {
headers: response.headers.toJSON(),
status_code: response.status,
});
}
}
return response;
} catch (e) {
sendErrorToSentry(e);
throw e;
}
},
);
});
},
});
}
1 change: 1 addition & 0 deletions packages/bun/src/integrations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { BunServer } from './bunserver';
3 changes: 3 additions & 0 deletions packages/bun/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Integrations as CoreIntegrations } from '@sentry/core';
import { init as initNode, Integrations as NodeIntegrations } from '@sentry/node';

import { BunClient } from './client';
import { BunServer } from './integrations';
import { makeFetchTransport } from './transports';
import type { BunOptions } from './types';

Expand All @@ -25,6 +26,8 @@ export const defaultIntegrations = [
new NodeIntegrations.RequestData(),
// Misc
new NodeIntegrations.LinkedErrors(),
// Bun Specific
new BunServer(),
];

/**
Expand Down
14 changes: 14 additions & 0 deletions packages/bun/test/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createTransport } from '@sentry/core';
import { resolvedSyncPromise } from '@sentry/utils';

import type { BunClientOptions } from '../src/types';

export function getDefaultBunClientOptions(options: Partial<BunClientOptions> = {}): BunClientOptions {
return {
integrations: [],
transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => resolvedSyncPromise({})),
stackParser: () => [],
instrumenter: 'sentry',
...options,
};
}
Loading