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

feat: nextjs integration #1030

Merged
merged 14 commits into from
Apr 14, 2023
Merged
7 changes: 5 additions & 2 deletions packages/js/src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Honeybadger extends Client {
]

protected __afterNotifyHandlers: Types.AfterNotifyHandler[] = [
(_error: any, notice?: Types.Notice) => {
(_error?: unknown, notice?: Types.Notice) => {
if (notice) {
this.__lastNoticeId = notice.id
}
Expand Down Expand Up @@ -157,7 +157,10 @@ class Honeybadger extends Client {
HTTP_COOKIE: undefined
}

cgiData.HTTP_USER_AGENT = navigator.userAgent
if (typeof navigator !== 'undefined' && navigator.userAgent) {
cgiData.HTTP_USER_AGENT = navigator.userAgent
}

if (typeof document !== 'undefined' && document.referrer.match(/\S/)) {
cgiData.HTTP_REFERER = document.referrer
}
Expand Down
30 changes: 24 additions & 6 deletions packages/js/src/browser/integrations/breadcrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ export default function (_window = globalThisOrWindow()): Types.Plugin {

// Breadcrumbs: instrument console
(function () {
if (!breadcrumbsEnabled('console')) { return }
if (!breadcrumbsEnabled('console')) {
return
}

function inspectArray(obj) {
if (!Array.isArray(obj)) { return '' }
Expand Down Expand Up @@ -55,7 +57,13 @@ export default function (_window = globalThisOrWindow()): Types.Plugin {

// Breadcrumbs: instrument click events
(function () {
if (!breadcrumbsEnabled('dom')) { return }
if (!breadcrumbsEnabled('dom')) {
return
}

if (typeof _window.addEventListener !== 'function') {
return
}

_window.addEventListener('click', (event) => {
let message, selector, text
Expand All @@ -80,15 +88,19 @@ export default function (_window = globalThisOrWindow()): Types.Plugin {
event
}
})
}, _window.location ? true : false) // In CloudFlare workers useCapture must be false. window.locaiton is a hacky way to detect it.
}, _window.location ? true : false) // In CloudFlare workers useCapture must be false. window.location is a hacky way to detect it.
})();

// Breadcrumbs: instrument XMLHttpRequest
(function () {
if (!breadcrumbsEnabled('network')) { return }
if (!breadcrumbsEnabled('network')) {
return
}

// Some environments may not support XMLHttpRequest.
if (typeof XMLHttpRequest === 'undefined') return
if (typeof XMLHttpRequest === 'undefined') {
return
}

// -- On xhr.open: capture initial metadata
instrument(XMLHttpRequest.prototype, 'open', function (original) {
Expand Down Expand Up @@ -160,7 +172,9 @@ export default function (_window = globalThisOrWindow()): Types.Plugin {

// Breadcrumbs: instrument fetch
(function () {
if (!breadcrumbsEnabled('network')) { return }
if (!breadcrumbsEnabled('network')) {
return
}

if (!nativeFetch()) {
// Polyfills use XHR.
Expand Down Expand Up @@ -253,6 +267,10 @@ export default function (_window = globalThisOrWindow()): Types.Plugin {
})
}

if (typeof _window.history === 'undefined') {
return
}

// https://developer.mozilla.org/en-US/docs/Web/API/History/pushState
// https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState
function historyWrapper(original) {
Expand Down
1 change: 1 addition & 0 deletions packages/js/src/browser/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export function nativeFetch () {

if (!global.fetch) { return false }
if (isNative(global.fetch)) { return true }
if (typeof document === 'undefined') { return false }

// If fetch isn't native, it may be wrapped by someone else. Try to get
// a pristine function from an iframe.
Expand Down
Empty file added packages/nextjs/CHANGELOG.md
Empty file.
21 changes: 21 additions & 0 deletions packages/nextjs/MIT-LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 Honeybadger Industries LLC

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
59 changes: 59 additions & 0 deletions packages/nextjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Honeybadger Next.js Integration

![Node CI](https://github.com/honeybadger-io/honeybadger-js/workflows/Node%20CI/badge.svg)
[![npm version](https://badge.fury.io/js/%40honeybadger-io%2Fnextjs.svg)](https://badge.fury.io/js/%40honeybadger-io%2Fnextjs)
[![npm dm](https://img.shields.io/npm/dm/@honeybadger-io/nextjs)](https://www.npmjs.com/package/@honeybadger-io/nextjs)
[![npm dt](https://img.shields.io/npm/dt/@honeybadger-io/nextjs)](https://www.npmjs.com/package/@honeybadger-io/nextjs)

## Documentation and Support

For comprehensive documentation and support, [check out our documentation site](https://docs.honeybadger.io/lib/javascript).

The documentation includes a detailed [Next.js integration guide](https://docs.honeybadger.io/lib/javascript/integration/nextjs).

## Project Goals

The goal is to provide an idiomatic, simple integration of Honeybadger's
exception monitoring service with Next.js applications.

## Project Status

This version is considered suitable for preview.

## Features

- Automatic reporting of uncaught exceptions (see [Limitations](#limitations))
- Breadcrumbs
- Source map upload to Honeybadger
- CLI command to generate Honeybadger configuration files for Next.js runtimes

## Limitations

The following limitations are known to exist and will be tackled in future releases:

- [Issue link](https://github.com/honeybadger-io/honeybadger-js/issues/1055): A custom `_error.js` component is used to report uncaught exceptions to Honeybadger.
This is necessary because Next.js does not provide a way to hook into the error handler.
This is not a catch-all errors solution. There are some caveats to this approach, as reported [here](https://nextjs.org/docs/advanced-features/custom-error-page#caveats).
This is a limitation of Next.js, not Honeybadger's Next.js integration.
Errors thrown in middlewares or API routes will not be reported to Honeybadger, since when they reach _error.js, the response status code is 404 and no error information is available.
Additionally, there is an open [issue](https://github.com/vercel/next.js/issues/45535) about 404 being reported with Next.js apps deployed on Vercel, when they should be reported as 500.
- [Issue link](https://github.com/honeybadger-io/honeybadger-js/issues/1056):Source maps for the [Edge runtime](https://vercel.com/docs/concepts/functions/edge-functions/edge-runtime) are not supported yet.

## Example app

A separate repository, [nextjs-with-honeybadger](https://github.com/honeybadger-io/nextjs-with-honeybadger) exists with an example app using this package.
Follow the README instructions to run the example app.

## Development

```bash
# install dependencies
npm install

# build for production
npm run build
```

### License

This package is MIT licensed. See the [MIT-LICENSE](./MIT-LICENSE) file in this folder for details.
Loading