Skip to content

Commit

Permalink
Merge pull request #12272 from getsentry/prepare-release/8.6.00
Browse files Browse the repository at this point in the history
meta: Add Changelog entry for 8.6.0
  • Loading branch information
Lms24 authored May 29, 2024
2 parents d3f3313 + 787a29b commit 264675d
Show file tree
Hide file tree
Showing 113 changed files with 1,961 additions and 890 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,7 @@ jobs:
'nextjs-app-dir',
'nextjs-14',
'nextjs-15',
'react-19',
'react-create-hash-router',
'react-router-6-use-routes',
'react-router-5',
Expand Down
54 changes: 54 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,60 @@

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

## 8.6.0

### Important Changes

- **feat(metrics): Add `timings` method to metrics (#12226)**

This introduces a new method, `metrics.timing()`, which can be used in two ways:

1. With a numeric value, to simplify creating a distribution metric. This will default to `second` as unit:

```js
Sentry.metrics.timing('myMetric', 100);
```

2. With a callback, which will wrap the duration of the callback. This can accept a sync or async callback. It will
create an inactive span around the callback and at the end emit a metric with the duration of the span in seconds:

```js
const returnValue = Sentry.metrics.timing('myMetric', measureThisFunction);
```

- **feat(react): Add `Sentry.reactErrorHandler` (#12147)**

This PR introduces `Sentry.reactErrorHandler`, which you can use in React 19 as follows:

```js
import * as Sentry from '@sentry/react';
import { hydrateRoot } from 'react-dom/client';
ReactDOM.hydrateRoot(
document.getElementById('root'),
<React.StrictMode>
<App />
</React.StrictMode>,
{
onUncaughtError: Sentry.reactErrorHandler(),
onCaughtError: Sentry.reactErrorHandler((error, errorInfo) => {
// optional callback if users want custom config.
}),
},
);
```

For more details, take a look at [the PR](https://github.com/getsentry/sentry-javascript/pull/12147). Our
documentation will be updated soon!

### Other Changes

- feat(sveltekit): Add request data to server-side events (#12254)
- fix(core): Pass in cron monitor config correctly (#12248)
- fix(nextjs): Don't capture suspense errors in server components (#12261)
- fix(tracing): Ensure sent spans are limited to 1000 (#12252)
- ref(core): Use versioned carrier on global object (#12206)
## 8.5.0
### Important Changes
Expand Down
140 changes: 137 additions & 3 deletions dev-packages/browser-integration-tests/fixtures/loader.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,139 @@
!function(n,e,r,t,i,o,a,c,s){for(var u=s,f=0;f<document.scripts.length;f++)if(document.scripts[f].src.indexOf(o)>-1){u&&"no"===document.scripts[f].getAttribute("data-lazy")&&(u=!1);break}var p=[];function l(n){return"e"in n}function d(n){return"p"in n}function _(n){return"f"in n}var v=[];function y(n){u&&(l(n)||d(n)||_(n)&&n.f.indexOf("capture")>-1||_(n)&&n.f.indexOf("showReportDialog")>-1)&&m(),v.push(n)}function g(){y({e:[].slice.call(arguments)})}function h(n){y({p:n})}function E(){try{n.SENTRY_SDK_SOURCE="loader";var e=n[i],o=e.init;e.init=function(i){n.removeEventListener(r,g),n.removeEventListener(t,h);var a=c;for(var s in i)Object.prototype.hasOwnProperty.call(i,s)&&(a[s]=i[s]);!function(n,e){var r=n.integrations||[];if(!Array.isArray(r))return;var t=r.map((function(n){return n.name}));n.tracesSampleRate&&-1===t.indexOf("BrowserTracing")&&(e.BrowserTracing?r.push(new e.BrowserTracing):e.browserTracingIntegration&&r.push(e.browserTracingIntegration()));(n.replaysSessionSampleRate||n.replaysOnErrorSampleRate)&&-1===t.indexOf("Replay")&&(e.Replay?r.push(new e.Replay):e.replayIntegration&&r.push(e.replayIntegration()));n.integrations=r}(a,e),o(a)},setTimeout((function(){return function(e){try{"function"==typeof n.sentryOnLoad&&(n.sentryOnLoad(),n.sentryOnLoad=void 0);for(var r=0;r<p.length;r++)"function"==typeof p[r]&&p[r]();p.splice(0);for(r=0;r<v.length;r++){_(o=v[r])&&"init"===o.f&&e.init.apply(e,o.a)}L()||e.init();var t=n.onerror,i=n.onunhandledrejection;for(r=0;r<v.length;r++){var o;if(_(o=v[r])){if("init"===o.f)continue;e[o.f].apply(e,o.a)}else l(o)&&t?t.apply(n,o.e):d(o)&&i&&i.apply(n,[o.p])}}catch(n){console.error(n)}}(e)}))}catch(n){console.error(n)}}var O=!1;function m(){if(!O){O=!0;var n=e.scripts[0],r=e.createElement("script");r.src=a,r.crossOrigin="anonymous",r.addEventListener("load",E,{once:!0,passive:!0}),n.parentNode.insertBefore(r,n)}}function L(){var e=n.__SENTRY__;return!(void 0===e||!e.hub||!e.hub.getClient())}n[i]=n[i]||{},n[i].onLoad=function(n){L()?n():p.push(n)},n[i].forceLoad=function(){setTimeout((function(){m()}))},["init","addBreadcrumb","captureMessage","captureException","captureEvent","configureScope","withScope","showReportDialog"].forEach((function(e){n[i][e]=function(){y({f:e,a:arguments})}})),n.addEventListener(r,g),n.addEventListener(t,h),u||setTimeout((function(){m()}))}
(
!(function (n, e, r, t, i, o, a, c, s) {
for (var u = s, f = 0; f < document.scripts.length; f++)
if (document.scripts[f].src.indexOf(o) > -1) {
u && 'no' === document.scripts[f].getAttribute('data-lazy') && (u = !1);
break;
}
var p = [];
function l(n) {
return 'e' in n;
}
function d(n) {
return 'p' in n;
}
function _(n) {
return 'f' in n;
}
var v = [];
function y(n) {
u &&
(l(n) || d(n) || (_(n) && n.f.indexOf('capture') > -1) || (_(n) && n.f.indexOf('showReportDialog') > -1)) &&
m(),
v.push(n);
}
function g() {
y({ e: [].slice.call(arguments) });
}
function h(n) {
y({ p: n });
}
function E() {
try {
n.SENTRY_SDK_SOURCE = 'loader';
var e = n[i],
o = e.init;
(e.init = function (i) {
n.removeEventListener(r, g), n.removeEventListener(t, h);
var a = c;
for (var s in i) Object.prototype.hasOwnProperty.call(i, s) && (a[s] = i[s]);
!(function (n, e) {
var r = n.integrations || [];
if (!Array.isArray(r)) return;
var t = r.map(function (n) {
return n.name;
});
n.tracesSampleRate &&
-1 === t.indexOf('BrowserTracing') &&
(e.BrowserTracing
? r.push(new e.BrowserTracing())
: e.browserTracingIntegration && r.push(e.browserTracingIntegration()));
(n.replaysSessionSampleRate || n.replaysOnErrorSampleRate) &&
-1 === t.indexOf('Replay') &&
(e.Replay ? r.push(new e.Replay()) : e.replayIntegration && r.push(e.replayIntegration()));
n.integrations = r;
})(a, e),
o(a);
}),
setTimeout(function () {
return (function (e) {
try {
'function' == typeof n.sentryOnLoad && (n.sentryOnLoad(), (n.sentryOnLoad = void 0));
for (var r = 0; r < p.length; r++) 'function' == typeof p[r] && p[r]();
p.splice(0);
for (r = 0; r < v.length; r++) {
_((o = v[r])) && 'init' === o.f && e.init.apply(e, o.a);
}
L() || e.init();
var t = n.onerror,
i = n.onunhandledrejection;
for (r = 0; r < v.length; r++) {
var o;
if (_((o = v[r]))) {
if ('init' === o.f) continue;
e[o.f].apply(e, o.a);
} else l(o) && t ? t.apply(n, o.e) : d(o) && i && i.apply(n, [o.p]);
}
} catch (n) {
console.error(n);
}
})(e);
});
} catch (n) {
console.error(n);
}
}
var O = !1;
function m() {
if (!O) {
O = !0;
var n = e.scripts[0],
r = e.createElement('script');
(r.src = a),
(r.crossOrigin = 'anonymous'),
r.addEventListener('load', E, { once: !0, passive: !0 }),
n.parentNode.insertBefore(r, n);
}
}
function L() {
var e = n.__SENTRY__;

// TODO: This is a temporary hack to make the loader script compatible with the versioned
// carrier. This needs still needs to be added to the actual loader script before we
// release the loader for v8!
var v = e && e.version && e[e.version];

return !(void 0 === e || !e.hub || !e.hub.getClient()) || !!v;
}
(n[i] = n[i] || {}),
(n[i].onLoad = function (n) {
L() ? n() : p.push(n);
}),
(n[i].forceLoad = function () {
setTimeout(function () {
m();
});
}),
[
'init',
'addBreadcrumb',
'captureMessage',
'captureException',
'captureEvent',
'configureScope',
'withScope',
'showReportDialog',
].forEach(function (e) {
n[i][e] = function () {
y({ f: e, a: arguments });
};
}),
n.addEventListener(r, g),
n.addEventListener(t, h),
u ||
setTimeout(function () {
m();
});
})(
window,
document,
'error',
Expand All @@ -8,5 +142,5 @@
'loader.js',
__LOADER_BUNDLE__,
__LOADER_OPTIONS__,
__LOADER_LAZY__
__LOADER_LAZY__,
);
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,9 @@ window.sentryIsLoaded = () => {
const __sentry = window.__SENTRY__;

// If there is a global __SENTRY__ that means that in any of the callbacks init() was already invoked
return !!(!(typeof __sentry === 'undefined') && __sentry.hub && __sentry.hub.getClient());
return !!(
!(typeof __sentry === 'undefined') &&
__sentry.version &&
!!__sentry[__sentry.version]
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,20 @@ Sentry.metrics.gauge('gauge', 5);
Sentry.metrics.gauge('gauge', '15');
Sentry.metrics.set('set', 'nope');
Sentry.metrics.set('set', 'another');

Sentry.metrics.timing('timing', 99, 'hour');
Sentry.metrics.timing('timingSync', () => {
sleepSync(200);
});
Sentry.metrics.timing('timingAsync', async () => {
await new Promise(resolve => setTimeout(resolve, 200));
});

function sleepSync(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if (new Date().getTime() - start > milliseconds) {
break;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@ sentryTest('collects metrics', async ({ getLocalTestUrl, page }) => {
const statsdBuffer = await getFirstSentryEnvelopeRequest<Uint8Array>(page, url, properEnvelopeRequestParser);
const statsdString = new TextDecoder().decode(statsdBuffer);
// Replace all the Txxxxxx to remove the timestamps
const normalisedStatsdString = statsdString.replace(/T\d+\n?/g, 'T000000');
const normalisedStatsdString = statsdString.replace(/T\d+\n?/g, 'T000000').trim();

expect(normalisedStatsdString).toEqual(
'increment@none:6|c|T000000distribution@none:42:45|d|T000000gauge@none:15:5:15:20:2|g|T000000set@none:3387254:3443787523|s|T000000',
);
const parts = normalisedStatsdString.split('T000000');

expect(parts).toEqual([
'increment@none:6|c|',
'distribution@none:42:45|d|',
'gauge@none:15:5:15:20:2|g|',
'set@none:3387254:3443787523|s|',
'timing@hour:99|d|',
expect.stringMatching(/timingSync@second:0.(\d+)\|d\|/),
expect.stringMatching(/timingAsync@second:0.(\d+)\|d\|/),
'', // trailing element
]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
tracesSampleRate: 1.0,
release: '1.0.0',
autoSessionTracking: false,
});

window.timingSync = () => {
// Ensure we always have a wrapping span
return Sentry.startSpan({ name: 'manual span' }, () => {
return Sentry.metrics.timing('timingSync', () => {
sleepSync(200);
return 'sync done';
});
});
};

window.timingAsync = () => {
// Ensure we always have a wrapping span
return Sentry.startSpan({ name: 'manual span' }, () => {
return Sentry.metrics.timing('timingAsync', async () => {
await new Promise(resolve => setTimeout(resolve, 200));
return 'async done';
});
});
};

function sleepSync(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if (new Date().getTime() - start > milliseconds) {
break;
}
}
}
Loading

0 comments on commit 264675d

Please sign in to comment.