From cea689a4f7b788bd5767bc3b2345f066e50dfa50 Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:31:45 +0300 Subject: [PATCH 1/8] chore: init --- README.md | 82 ++++++++++++++++++++++ src/index.ts | 55 ++++++++++++++- src/modules/breadcrumbs.ts | 137 +++++++++++++++++++++++++++++++++++++ types/index.ts | 11 +++ 4 files changed, 282 insertions(+), 3 deletions(-) create mode 100644 src/modules/breadcrumbs.ts diff --git a/README.md b/README.md index 8f32369..e718af4 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Initialization params: | `context` | object | optional | Any data you want to pass with every message. | | `disableGlobalErrorsHandling` | boolean | optional | Do not initialize global errors handling | | `beforeSend` | function(event) => event | optional | This Method allows you to filter any data you don't want sending to Hawk | +| `breadcrumbs` | `false` or object | optional | Pass `false` to disable. Pass options object to configure (see [Breadcrumbs](#breadcrumbs)). Default: enabled. | ## Usage @@ -152,6 +153,87 @@ Available fields: } ``` +### Breadcrumbs + +Breadcrumbs track events leading up to an error, providing context for debugging. Same API as [@hawk.so/javascript](https://www.npmjs.com/package/@hawk.so/javascript) (add, get, clear); in Node there is no automatic tracking of fetch/navigation/clicks, only manual breadcrumbs. + +#### Default configuration + +By default, breadcrumbs are enabled (custom breadcrumbs only): + +```js +HawkCatcher.init({ + token: 'INTEGRATION_TOKEN' + // breadcrumbs enabled by default +}); +``` + +#### Disabling breadcrumbs + +To disable breadcrumbs entirely: + +```js +HawkCatcher.init({ + token: 'INTEGRATION_TOKEN', + breadcrumbs: false +}); +``` + +#### Custom configuration + +Configure breadcrumbs (same options as JS where applicable): + +```js +HawkCatcher.init({ + token: 'INTEGRATION_TOKEN', + breadcrumbs: { + maxBreadcrumbs: 20, + beforeBreadcrumb: (breadcrumb, hint) => { + if (breadcrumb.category === 'auth' && breadcrumb.data?.userId) { + return null; // Discard + } + 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). | +| `beforeBreadcrumb` | `function` | `undefined` | Hook called before each breadcrumb is stored. Receives `(breadcrumb, hint)` and can return modified breadcrumb, `null` to discard it, or the original breadcrumb. | + +#### Manual breadcrumbs + +Add custom breadcrumbs manually (they are attached to the next event sent): + +```js +HawkCatcher.breadcrumbs.add({ + type: 'logic', + category: 'auth', + message: 'User logged in', + level: 'info', + data: { userId: '123' } +}); +``` + +#### Breadcrumb methods + +Same as in JS catcher: + +```js +// Add a breadcrumb +HawkCatcher.breadcrumbs.add(breadcrumb, hint); + +// Get current breadcrumbs +const breadcrumbs = HawkCatcher.breadcrumbs.get(); + +// Clear all breadcrumbs +HawkCatcher.breadcrumbs.clear(); +``` + ### Sensitive data filtering You can filter any data that you don't want to send to Hawk. Use the `beforeSend()` hook for that reason. diff --git a/src/index.ts b/src/index.ts index b09bd89..956c0ef 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import process from 'process'; import type { EventContext, AffectedUser, + Breadcrumb, EncodedIntegrationToken, DecodedIntegrationToken, EventData, @@ -12,6 +13,7 @@ import type { Json } from '@hawk.so/types'; import EventPayload from './modules/event.js'; +import { BreadcrumbManager, type BreadcrumbInput, type BreadcrumbHint } from './modules/breadcrumbs.js'; import type { AxiosResponse } from 'axios'; import axios from 'axios'; import { VERSION } from './version.js'; @@ -62,6 +64,11 @@ class Catcher { */ private readonly beforeSend?: (event: EventData) => EventData; + /** + * Whether breadcrumbs are enabled (false when settings.breadcrumbs === false) + */ + public readonly breadcrumbsEnabled: boolean; + /** * @param settings - If settings is a string, it means an Integration Token */ @@ -76,6 +83,15 @@ class Catcher { this.context = settings.context ?? undefined; this.release = settings.release ?? undefined; this.beforeSend = settings.beforeSend?.bind(undefined); + this.breadcrumbsEnabled = settings.breadcrumbs !== false; + + if (this.breadcrumbsEnabled) { + BreadcrumbManager.getInstance().init( + typeof settings.breadcrumbs === 'object' && settings.breadcrumbs !== null + ? settings.breadcrumbs + : {}, + ); + } if (!this.token) { throw new Error('Integration Token is missed. You can get it on https://hawk.so at Project Settings.'); @@ -227,6 +243,8 @@ class Catcher { */ private formatAndSend(err: Error, context?: EventContext, user?: AffectedUser): void { const eventPayload = new EventPayload(err); + const breadcrumbs = this.breadcrumbsEnabled ? BreadcrumbManager.getInstance().getBreadcrumbs() : []; + let payload: EventData = { title: eventPayload.getTitle(), type: eventPayload.getType(), @@ -235,6 +253,7 @@ class Catcher { context: this.getContext(context), release: this.release, catcherVersion: Catcher.getVersion(), + breadcrumbs: breadcrumbs.length > 0 ? breadcrumbs : null, }; /** @@ -319,8 +338,38 @@ export default class HawkCatcher { return _instance.send(error, context, user); } } + + /** + * Breadcrumbs API (same as in JS catcher: add, get, clear). + * No-op when breadcrumbs were disabled (breadcrumbs: false). + */ + public static get breadcrumbs(): BreadcrumbsAPI { + return { + add: (breadcrumb, hint) => { + if (_instance !== undefined && _instance.breadcrumbsEnabled) { + BreadcrumbManager.getInstance().addBreadcrumb(breadcrumb, hint); + } + }, + get: () => + _instance !== undefined && _instance.breadcrumbsEnabled + ? BreadcrumbManager.getInstance().getBreadcrumbs() + : [], + clear: () => { + if (_instance !== undefined && _instance.breadcrumbsEnabled) { + BreadcrumbManager.getInstance().clear(); + } + }, + }; + } +} + +/** + * Breadcrumbs API - same surface as in @hawk.so/javascript (add, get, clear) + */ +export interface BreadcrumbsAPI { + add(breadcrumb: BreadcrumbInput, hint?: BreadcrumbHint): void; + get(): Breadcrumb[]; + clear(): void; } -export type { - HawkNodeJSInitialSettings -}; +export type { BreadcrumbInput, BreadcrumbHint, HawkNodeJSInitialSettings }; diff --git a/src/modules/breadcrumbs.ts b/src/modules/breadcrumbs.ts new file mode 100644 index 0000000..cabce87 --- /dev/null +++ b/src/modules/breadcrumbs.ts @@ -0,0 +1,137 @@ +/** + * @file Breadcrumbs module - chronological trail of events before an error + * + * Current: custom breadcrumbs only (HawkCatcher.breadcrumbs.add()). + * Possible future auto-capture: outgoing HTTP (patch http.request / https.request or + * undici), unhandledRejection/uncaughtException as last breadcrumb before send, + * optional console.log/intercept, DB query hooks (driver-specific). + */ +import type { Breadcrumb } from '@hawk.so/types'; + +/** + * Default maximum number of breadcrumbs to store + */ +const DEFAULT_MAX_BREADCRUMBS = 15; + +/** + * Hint object passed to beforeBreadcrumb callback (same concept as in JS catcher; in Node no event/response yet, use for custom context) + */ +export interface BreadcrumbHint { + [key: string]: unknown; +} + +/** + * Configuration options for breadcrumbs (same shape as @hawk.so/javascript; no trackFetch/trackNavigation/trackClicks in Node) + */ +export interface BreadcrumbsOptions { + /** + * Maximum number of breadcrumbs to store (FIFO). When the limit is reached, oldest are removed. + * + * @default 15 + */ + maxBreadcrumbs?: number; + + /** + * Hook called before each breadcrumb is stored. + * Return null to discard the breadcrumb. Return modified breadcrumb to store it. + */ + beforeBreadcrumb?: (breadcrumb: Breadcrumb, hint?: BreadcrumbHint) => Breadcrumb | null; +} + +/** + * Breadcrumb input - timestamp optional (auto-generated if omitted). Same as @hawk.so/javascript BreadcrumbInput. + */ +export type BreadcrumbInput = Omit & { timestamp?: Breadcrumb['timestamp'] }; + +interface InternalBreadcrumbsOptions { + maxBreadcrumbs: number; + beforeBreadcrumb?: BreadcrumbsOptions['beforeBreadcrumb']; +} + +/** + * Manages breadcrumb buffer and add/get/clear API + */ +export class BreadcrumbManager { + private static instance: BreadcrumbManager | null = null; + + private readonly breadcrumbs: Breadcrumb[] = []; + + private options: InternalBreadcrumbsOptions = { + maxBreadcrumbs: DEFAULT_MAX_BREADCRUMBS, + }; + + private isInitialized = false; + + private constructor() {} + + public static getInstance(): BreadcrumbManager { + if (BreadcrumbManager.instance === null) { + BreadcrumbManager.instance = new BreadcrumbManager(); + } + + return BreadcrumbManager.instance; + } + + /** + * Initialize with options. Call once when HawkCatcher.init() runs. + */ + public init(options: BreadcrumbsOptions = {}): void { + if (this.isInitialized) { + return; + } + + this.options = { + maxBreadcrumbs: options.maxBreadcrumbs ?? DEFAULT_MAX_BREADCRUMBS, + beforeBreadcrumb: options.beforeBreadcrumb, + }; + + this.isInitialized = true; + } + + /** + * Add a breadcrumb. Timestamp is set to Date.now() if omitted. + */ + public addBreadcrumb(breadcrumb: BreadcrumbInput, hint?: BreadcrumbHint): void { + const bc: Breadcrumb = { + ...breadcrumb, + timestamp: breadcrumb.timestamp ?? Date.now(), + }; + + if (this.options.beforeBreadcrumb) { + const result = this.options.beforeBreadcrumb(bc, hint); + + if (result === null) { + return; + } + + Object.assign(bc, result); + } + + this.breadcrumbs.push(bc); + + if (this.breadcrumbs.length > this.options.maxBreadcrumbs) { + this.breadcrumbs.shift(); + } + } + + /** + * Snapshot of current breadcrumbs (oldest to newest) + */ + public getBreadcrumbs(): Breadcrumb[] { + return [...this.breadcrumbs]; + } + + /** + * Clear all breadcrumbs (e.g. after sending an event) + */ + public clear(): void { + this.breadcrumbs.length = 0; + } + + /** + * Reset singleton (for tests) + */ + public static resetInstance(): void { + BreadcrumbManager.instance = null; + } +} diff --git a/types/index.ts b/types/index.ts index 46c218e..f6f7a3b 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,4 +1,7 @@ import type { EventData, NodeJSAddons } from '@hawk.so/types'; +import type { BreadcrumbsOptions } from '../src/modules/breadcrumbs.js'; + +export type { BreadcrumbsOptions }; /** * Initial settings object @@ -34,6 +37,14 @@ export interface HawkNodeJSInitialSettings { * This options still allow you send events manually */ disableGlobalErrorsHandling?: boolean; + + /** + * Pass false to disable breadcrumbs. + * Pass options object to configure maxBreadcrumbs and beforeBreadcrumb hook. + * + * @default { maxBreadcrumbs: 15 } + */ + breadcrumbs?: false | BreadcrumbsOptions; } /** From 0e1ce583c97c63383fb26b91ed3dbe96a6c4f476 Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:52:49 +0300 Subject: [PATCH 2/8] fix: build --- example/example.js | 2 +- src/index.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/example.js b/example/example.js index 51a6d16..0a224a7 100644 --- a/example/example.js +++ b/example/example.js @@ -16,7 +16,7 @@ * HawkCatcher.send(err); * } */ -const HawkCatcher = require('../dist/src/index').default; +const HawkCatcher = require('../dist/cjs/src/index.js').default; /** * Initialize Hawk catcher diff --git a/src/index.ts b/src/index.ts index 956c0ef..9965169 100644 --- a/src/index.ts +++ b/src/index.ts @@ -245,7 +245,7 @@ class Catcher { const eventPayload = new EventPayload(err); const breadcrumbs = this.breadcrumbsEnabled ? BreadcrumbManager.getInstance().getBreadcrumbs() : []; - let payload: EventData = { + let payload = { title: eventPayload.getTitle(), type: eventPayload.getType(), backtrace: eventPayload.getBacktrace(), @@ -254,7 +254,7 @@ class Catcher { release: this.release, catcherVersion: Catcher.getVersion(), breadcrumbs: breadcrumbs.length > 0 ? breadcrumbs : null, - }; + } as EventData; /** * Filter sensitive data From 519dfc19f40abc308eaba9bc9c88dd99a2818c2a Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:02:23 +0300 Subject: [PATCH 3/8] fix: lint --- src/index.ts | 17 +++++++++++------ src/modules/breadcrumbs.ts | 14 +++++++------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9965169..50f7788 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,6 +34,11 @@ let _instance: Catcher; * @copyright CodeX */ class Catcher { + /** + * Whether breadcrumbs are enabled (false when settings.breadcrumbs === false) + */ + public readonly breadcrumbsEnabled: boolean; + /** * Type is a family name of a catcher */ @@ -64,11 +69,6 @@ class Catcher { */ private readonly beforeSend?: (event: EventData) => EventData; - /** - * Whether breadcrumbs are enabled (false when settings.breadcrumbs === false) - */ - public readonly breadcrumbsEnabled: boolean; - /** * @param settings - If settings is a string, it means an Integration Token */ @@ -89,7 +89,7 @@ class Catcher { BreadcrumbManager.getInstance().init( typeof settings.breadcrumbs === 'object' && settings.breadcrumbs !== null ? settings.breadcrumbs - : {}, + : {} ); } @@ -367,8 +367,13 @@ export default class HawkCatcher { * Breadcrumbs API - same surface as in @hawk.so/javascript (add, get, clear) */ export interface BreadcrumbsAPI { + /** Add a breadcrumb to the buffer (attached to the next sent event) */ add(breadcrumb: BreadcrumbInput, hint?: BreadcrumbHint): void; + + /** Get current breadcrumbs snapshot (oldest to newest) */ get(): Breadcrumb[]; + + /** Clear all breadcrumbs */ clear(): void; } diff --git a/src/modules/breadcrumbs.ts b/src/modules/breadcrumbs.ts index cabce87..6356340 100644 --- a/src/modules/breadcrumbs.ts +++ b/src/modules/breadcrumbs.ts @@ -1,10 +1,5 @@ /** - * @file Breadcrumbs module - chronological trail of events before an error - * - * Current: custom breadcrumbs only (HawkCatcher.breadcrumbs.add()). - * Possible future auto-capture: outgoing HTTP (patch http.request / https.request or - * undici), unhandledRejection/uncaughtException as last breadcrumb before send, - * optional console.log/intercept, DB query hooks (driver-specific). + * @file Breadcrumbs module - chronological trail of events before an error. Custom breadcrumbs only (HawkCatcher.breadcrumbs.add()). Possible future auto-capture: outgoing HTTP, unhandledRejection/uncaughtException, console.log/intercept, DB query hooks. */ import type { Breadcrumb } from '@hawk.so/types'; @@ -26,7 +21,6 @@ export interface BreadcrumbHint { export interface BreadcrumbsOptions { /** * Maximum number of breadcrumbs to store (FIFO). When the limit is reached, oldest are removed. - * * @default 15 */ maxBreadcrumbs?: number; @@ -43,8 +37,14 @@ export interface BreadcrumbsOptions { */ export type BreadcrumbInput = Omit & { timestamp?: Breadcrumb['timestamp'] }; +/** + * Internal breadcrumbs options (all fields set during init from BreadcrumbsOptions) + */ interface InternalBreadcrumbsOptions { + /** Maximum number of breadcrumbs to keep (FIFO) */ maxBreadcrumbs: number; + + /** Optional hook before storing each breadcrumb */ beforeBreadcrumb?: BreadcrumbsOptions['beforeBreadcrumb']; } From b99f941f19526024be1dd6e5c798bac0b1d75472 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:03:03 +0000 Subject: [PATCH 4/8] Bump version up to 3.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 83af9ff..a44d00c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hawk.so/nodejs", - "version": "3.2.0", + "version": "3.2.1", "description": "Node.js catcher for Hawk", "license": "AGPL-3.0-only", "engines": { From ad43bb1786ca13a040a258fc086dd3e2e66e0e2b Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:08:42 +0300 Subject: [PATCH 5/8] fix: lint --- src/modules/breadcrumbs.ts | 24 +++++++++++++++--------- types/index.ts | 4 +--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/modules/breadcrumbs.ts b/src/modules/breadcrumbs.ts index 6356340..07f59fb 100644 --- a/src/modules/breadcrumbs.ts +++ b/src/modules/breadcrumbs.ts @@ -26,8 +26,10 @@ export interface BreadcrumbsOptions { maxBreadcrumbs?: number; /** - * Hook called before each breadcrumb is stored. - * Return null to discard the breadcrumb. Return modified breadcrumb to store it. + * Hook called before each breadcrumb is stored. Return null to discard. Return modified breadcrumb to store it. + * @param breadcrumb - Breadcrumb to store (can be mutated and returned) + * @param hint - Optional context (e.g. for filtering) + * @returns Modified breadcrumb to store, or null to discard */ beforeBreadcrumb?: (breadcrumb: Breadcrumb, hint?: BreadcrumbHint) => Breadcrumb | null; } @@ -35,6 +37,7 @@ export interface BreadcrumbsOptions { /** * Breadcrumb input - timestamp optional (auto-generated if omitted). Same as @hawk.so/javascript BreadcrumbInput. */ +// eslint-disable-next-line jsdoc/require-jsdoc -- type alias documented above export type BreadcrumbInput = Omit & { timestamp?: Breadcrumb['timestamp'] }; /** @@ -62,8 +65,15 @@ export class BreadcrumbManager { private isInitialized = false; + /** + * Private constructor for singleton + */ private constructor() {} + /** + * Get singleton instance (created on first call). + * @returns The shared BreadcrumbManager + */ public static getInstance(): BreadcrumbManager { if (BreadcrumbManager.instance === null) { BreadcrumbManager.instance = new BreadcrumbManager(); @@ -74,6 +84,7 @@ export class BreadcrumbManager { /** * Initialize with options. Call once when HawkCatcher.init() runs. + * @param options - Configuration (maxBreadcrumbs, beforeBreadcrumb) */ public init(options: BreadcrumbsOptions = {}): void { if (this.isInitialized) { @@ -90,6 +101,8 @@ export class BreadcrumbManager { /** * Add a breadcrumb. Timestamp is set to Date.now() if omitted. + * @param breadcrumb - Breadcrumb data (type, message, category, level, data) + * @param hint - Optional hint for beforeBreadcrumb callback */ public addBreadcrumb(breadcrumb: BreadcrumbInput, hint?: BreadcrumbHint): void { const bc: Breadcrumb = { @@ -127,11 +140,4 @@ export class BreadcrumbManager { public clear(): void { this.breadcrumbs.length = 0; } - - /** - * Reset singleton (for tests) - */ - public static resetInstance(): void { - BreadcrumbManager.instance = null; - } } diff --git a/types/index.ts b/types/index.ts index f6f7a3b..88c5c31 100644 --- a/types/index.ts +++ b/types/index.ts @@ -39,9 +39,7 @@ export interface HawkNodeJSInitialSettings { disableGlobalErrorsHandling?: boolean; /** - * Pass false to disable breadcrumbs. - * Pass options object to configure maxBreadcrumbs and beforeBreadcrumb hook. - * + * Pass false to disable breadcrumbs. Pass options object to configure maxBreadcrumbs and beforeBreadcrumb hook. * @default { maxBreadcrumbs: 15 } */ breadcrumbs?: false | BreadcrumbsOptions; From be82694d040ab07f41cb6af3eaac438de757dd4a Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Wed, 4 Feb 2026 17:35:11 +0300 Subject: [PATCH 6/8] chore: bump version to 3.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a44d00c..ef3562c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hawk.so/nodejs", - "version": "3.2.1", + "version": "3.3.0", "description": "Node.js catcher for Hawk", "license": "AGPL-3.0-only", "engines": { From 5399d08e5619f0548656ff2e74c06d21e8d3c486 Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Sat, 7 Feb 2026 16:46:10 +0300 Subject: [PATCH 7/8] refactor: update type exports in index.ts --- src/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 50f7788..38c84a2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -377,4 +377,5 @@ export interface BreadcrumbsAPI { clear(): void; } -export type { BreadcrumbInput, BreadcrumbHint, HawkNodeJSInitialSettings }; +export type { BreadcrumbInput, BreadcrumbHint, BreadcrumbsOptions } from './modules/breadcrumbs.js'; +export type { HawkNodeJSInitialSettings } from '../types/index.js'; From fafe24eb5b218de3bb3cc9172e10ad909c8bd49c Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Sat, 7 Feb 2026 19:47:28 +0300 Subject: [PATCH 8/8] docs: clarify breadcrumbs behavior in README and index.ts --- README.md | 2 +- src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e718af4..9cac71c 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ HawkCatcher.init({ #### Manual breadcrumbs -Add custom breadcrumbs manually (they are attached to the next event sent): +Add custom breadcrumbs manually. Breadcrumbs accumulate in a buffer and are attached to every event until explicitly cleared via `HawkCatcher.breadcrumbs.clear()`: ```js HawkCatcher.breadcrumbs.add({ diff --git a/src/index.ts b/src/index.ts index 38c84a2..407c453 100644 --- a/src/index.ts +++ b/src/index.ts @@ -367,7 +367,7 @@ export default class HawkCatcher { * Breadcrumbs API - same surface as in @hawk.so/javascript (add, get, clear) */ export interface BreadcrumbsAPI { - /** Add a breadcrumb to the buffer (attached to the next sent event) */ + /** Add a breadcrumb to the buffer (attached to every event until cleared) */ add(breadcrumb: BreadcrumbInput, hint?: BreadcrumbHint): void; /** Get current breadcrumbs snapshot (oldest to newest) */