Skip to content

Latest commit

 

History

History
400 lines (289 loc) · 14.3 KB

File metadata and controls

400 lines (289 loc) · 14.3 KB

Hawk JavaScript Catcher

Error tracking for JavaScript/TypeScript applications.

Features

  • 🦅 Automatic error catching
  • 💎 Manual error and logs sending
  • 🙂 Attaching user information
  • 📦 Attaching additional context
  • 🛡️ Sensitive data filtering
  • 🌟 Source maps consuming
  • 💬 Console logs tracking
  • 🧊 Main-thread blocking detection (Long Tasks + LoAF, Chromium-only)
  • 📊 Aggregated Web Vitals issues monitoring
  • ⚙️ Unified issues configuration (errors + performance detectors)
  •  Vue support
  •  React support

Installation

We recommend adding Hawk script to page above others to prevent missing any errors.

Install via NPM or Yarn

Install package

npm install @hawk.so/javascript --save
yarn add @hawk.so/javascript

Then import @hawk.so/javascript module to your code.

import HawkCatcher from '@hawk.so/javascript';

Load from CDN

Get a specific version bundle path from @hawk.so/javascript — open the page and copy the link. Do not use @latest, as your setup may break in case of a major API update.

Then require this script on your site.

<script src="..." async></script>

Usage

Get an Integration Token

First of all, you should register an account on hawk.so.

Then create a Workspace and a Project in there. You'll get an Integration Token.

Initialize Catcher

Create HawkCatcher class instance when script will be ready and pass your Integration Token:

const hawk = new HawkCatcher({token: 'INTEGRATION_TOKEN'});

// or

const hawk = new HawkCatcher('INTEGRATION_TOKEN');

Alternately, add onload="const hawk = new HawkCatcher({token: 'INTEGRATION_TOKEN'})" attribute to the <script> tag.

<script src="https://cdn.jsdelivr.net/npm/@hawk.so/javascript@latest/dist/hawk.js"
        onload="const hawk = new HawkCatcher({token: 'INTEGRATION_TOKEN'})"></script>

Initialization settings:

name type required description
token string required Your project's Integration Token
release string/number optional Unique identifier of the release. Used for source map consuming (see below)
user {id: string, name?: string, image?: string, url?: string} optional Current authenticated user
context object optional Any data you want to pass with every message. Has limitation of length.
vue Vue constructor optional Pass Vue constructor to set up the Vue integration
disableGlobalErrorsHandling boolean optional Deprecated. Use issues.errors: false instead.
disableVueErrorHandler boolean optional Do not initialize Vue errors handling
consoleTracking boolean optional Initialize console logs tracking
breadcrumbs false or BreadcrumbsOptions object optional Configure breadcrumbs tracking (see below)
beforeSend function(event) => event | false | void optional Filter data before sending. Return modified event, false to drop the event.
issues IssuesOptions object optional Issues config: errors, webVitals, longTasks.thresholdMs, longAnimationFrames.thresholdMs

Other available initial settings are described at the type definition.

Manual sending

You can send errors or other messages to the Hawk manually, for example at your catch blocks or any debug conditions.

Use the .send(message, context) method for that. This method accepts the message of type Error or string as the first parameter. The second parameter is optional, it allows passing any additional data with the event. If you specify the context with the HawkCatcher constructor, it will be merged with the context passed to the send method.

// init Hawk Catcher instance
const hawk = new HawkCatcher({token: 'INTEGRATION_TOKEN'});

// somewhere in try-catch block or other custom place
hawk.send(new Error('Something went wrong'), {
  myOwnDebugInfo: '1234',
});

User Management

You can dynamically manage user information after the catcher is initialized:

const hawk = new HawkCatcher({token: 'INTEGRATION_TOKEN'});

// Set user information
hawk.setUser({
  id: 'user123',
  name: 'John Doe',
  url: '/users/123',
  image: 'https://example.com/avatar.jpg',
});

// Clear user (revert to generated user)
hawk.clearUser();

Context Management

You can dynamically update context data that will be sent with all events:

const hawk = new HawkCatcher({token: 'INTEGRATION_TOKEN'});

// Set context data
hawk.setContext({
  feature: 'user-dashboard',
  version: '2.1.0',
  environment: 'production',
});

Breadcrumbs

Breadcrumbs track user interactions and events leading up to an error, providing context for debugging.

Default Configuration

By default, breadcrumbs are enabled with tracking for fetch/XHR requests, navigation, and UI clicks:

const hawk = new HawkCatcher({
  token: 'INTEGRATION_TOKEN'
  // breadcrumbs enabled by default
});

Disabling Breadcrumbs

To disable breadcrumbs entirely:

const hawk = new HawkCatcher({
  token: 'INTEGRATION_TOKEN',
  breadcrumbs: false
});

Custom Configuration

Configure breadcrumbs tracking behavior:

const hawk = new HawkCatcher({
  token: 'INTEGRATION_TOKEN',
  breadcrumbs: {
    maxBreadcrumbs: 20,         // Maximum breadcrumbs to store (default: 15)
    trackFetch: true,           // Track fetch/XHR requests (default: true)
    trackNavigation: true,      // Track navigation events (default: true)
    trackClicks: true,          // Track UI clicks (default: true)
    beforeBreadcrumb: (breadcrumb, hint) => {
      // Filter or modify breadcrumbs before storing
      if (breadcrumb.category === 'fetch' && breadcrumb.data?.url?.includes('/sensitive')) {
        return false; // Discard this breadcrumb
      }
      return breadcrumb;
    }
  }
});

Breadcrumbs Options

Option Type Default Description
maxBreadcrumbs number 15 Maximum number of breadcrumbs to store. When the limit is reached, oldest breadcrumbs are removed (FIFO).
trackFetch boolean true Automatically track fetch() and XMLHttpRequest calls as breadcrumbs. Captures request URL, method, status code, and response time.
trackNavigation boolean true Automatically track navigation events (History API: pushState, replaceState, popstate). Captures route changes.
trackClicks boolean true Automatically track UI click events. Captures element selector, coordinates, and other click metadata.
beforeBreadcrumb function undefined Hook called before each breadcrumb is stored. Receives (breadcrumb, hint). Return modified breadcrumb to keep it, false to discard.

Manual Breadcrumbs

Add custom breadcrumbs manually:

hawk.breadcrumbs.add({
  type: 'logic',
  category: 'auth',
  message: 'User logged in',
  level: 'info',
  data: { userId: '123' }
});

Breadcrumb Methods

// Add a breadcrumb
hawk.breadcrumbs.add(breadcrumb, hint);

// Get current breadcrumbs
const breadcrumbs = hawk.breadcrumbs.get();

// Clear all breadcrumbs
hawk.breadcrumbs.clear();

Issues Detection

issues is an umbrella option for problems detected by the catcher. Browser support depends on the specific detector:

  • errors — works in all supported browsers
  • webVitals — via web-vitals package
  • longTasks / longAnimationFrames — Chromium-only (long-animation-frame requires Chrome/Edge 123+)

It currently includes three groups:

  • issues.errors — global runtime errors handling
  • issues.webVitals — aggregated Core Web Vitals report
  • issues.longTasks and issues.longAnimationFrames — freeze-related detectors

Freeze detectors use two complementary APIs:

  • Long Tasks API — browser reports tasks taking longer than 50 ms.
  • Long Animation Frames (LoAF) — browser reports frames taking longer than 50 ms with richer script attribution (Chrome 123+, Edge 123+).

Both freeze detectors are disabled by default. If enabled and one API is unsupported, the other still works. Each detected freeze is reported immediately with detailed context (duration, blocking time, scripts involved, etc.). thresholdMs is an additional Hawk filter on top of browser reporting. Hawk emits an issue when measured duration is equal to or greater than this value. Values below 50ms are clamped to 50ms.

Web Vitals (Aggregated)

When issues.webVitals is enabled, Hawk collects Core Web Vitals (LCP, FCP, TTFB, INP, CLS) and sends a single issue event when at least one metric is rated poor. Reporting happens when all five metrics are collected, or earlier on timeout/page unload to avoid waiting indefinitely on pages where some metrics never fire.

The event context contains all metrics with:

  • value
  • rating
  • delta

web-vitals is optional and used only when issues.webVitals: true:

  • NPM/ESM setup: install web-vitals as dependency.
  • CDN setup: expose global window.webVitals before Hawk initialization.

Disabling

Disable global errors handling:

const hawk = new HawkCatcher({
  token: 'INTEGRATION_TOKEN',
  issues: {
    errors: false
  }
});

Selective Configuration

Configure all issue detectors:

const hawk = new HawkCatcher({
  token: 'INTEGRATION_TOKEN',
  issues: {
    errors: true,
    webVitals: true,
    longTasks: {
      thresholdMs: 70
    },
    longAnimationFrames: {
      thresholdMs: 200
    }
  }
});

Options

Option Type Default Description
errors boolean true Enable global errors handling (window.onerror and unhandledrejection).
webVitals boolean false Collect all Core Web Vitals and send one issue event when at least one metric is rated poor. Requires optional web-vitals dependency.
longTasks boolean or { thresholdMs?: number } false false disables. true enables with default threshold. Object enables and uses thresholdMs when valid; otherwise fallback threshold 70ms is used (minimum effective value 50ms).
longAnimationFrames boolean or { thresholdMs?: number } false false disables. true enables with default threshold. Object enables and uses thresholdMs when valid; otherwise fallback threshold 200ms is used (minimum effective value 50ms). Requires Chrome 123+ / Edge 123+.

Source maps consuming

If your bundle is minified, it is useful to pass source-map files to the Hawk. After that you will see beautiful original source code lines in Hawk Garage instead of minified code.

To enable source map consuming you should do two things:

  • Send the source map and the release identifier to the Hawk after you build a new version of the script. For example with the Hawk Webpack Plugin or with cURL request.
  • Pass the release identifier to the Hawk Catcher using release option.

Testing and server responses

To make sure that Hawk is working right, call test() method from HawkCatcher class instance in browser's console. test() method sends fake error to server. Then, open Hawk and find a test event at the Project's page.

Sensitive data filtering

You can filter any data that you don't want to send to Hawk. Use the beforeSend() hook for that reason.

window.hawk = new HawkCatcher({
  token: 'INTEGRATION TOKEN',
  beforeSend(event) {
    if (event.user && event.user.name) {
      delete event.user.name;
    }

    return event;
  }
})

Dismiss error

You can use the beforeSend() hook to prevent sending a particular event. Return false for that.

Usage with    Vue.js

Vue apps have their own error handler, so if you want to catcher errors thrown inside Vue components, you should set up a Vue integration.

Pass the Vue constructor with the initial settings:

import Vue from 'vue';

const hawk = new HawkCatcher({
  token: 'INTEGRATION_TOKEN',
  vue: Vue // the Vue constructor you tweak
});

or pass it any moment after Hawk Catcher was instantiated:

import Vue from 'vue';

const hawk = new HawkCatcher({
  token: 'INTEGRATION_TOKEN',
});

hawk.connectVue(Vue)

Usage with    React

React is suppported out of the box. No additional setup required.

Create the Hawk Catcher instance in a index.js file of your project.

import HawkCatcher from '@hawk.so/javascript';

const hawk = new HawkCatcher({
  token: 'INTEGRATION_TOKEN'
});

License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file for the full text.