@neowhale/telemetry 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +334 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,334 @@
1
+ # @neowhale/telemetry
2
+
3
+ Error tracking, analytics, Web Vitals, and AI/LLM call monitoring for WhaleTools stores. Zero dependencies. Works in the browser and on the server.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @neowhale/telemetry
9
+ ```
10
+
11
+ Peer dependencies: `react >=18` (optional -- only needed for `@neowhale/telemetry/react`).
12
+
13
+ ## Quick Start
14
+
15
+ ### Browser (React)
16
+
17
+ ```tsx
18
+ import { WhaleTelemetry, WhaleErrorBoundary } from '@neowhale/telemetry/react'
19
+
20
+ export default function App() {
21
+ return (
22
+ <WhaleTelemetry apiKey="wk_live_..." storeId="your-store-uuid">
23
+ <WhaleErrorBoundary fallback={<p>Something went wrong.</p>}>
24
+ <YourApp />
25
+ </WhaleErrorBoundary>
26
+ </WhaleTelemetry>
27
+ )
28
+ }
29
+ ```
30
+
31
+ `WhaleTelemetry` calls `init()` on mount and `destroy()` on unmount. In the browser it automatically captures:
32
+
33
+ - Unhandled errors and promise rejections
34
+ - Page views (initial load and SPA navigation)
35
+ - Web Vitals (LCP, FID, CLS, FCP)
36
+ - Breadcrumbs (clicks, navigation, console warnings/errors, fetch)
37
+
38
+ ### Browser (Vanilla)
39
+
40
+ ```ts
41
+ import { whaletools } from '@neowhale/telemetry'
42
+
43
+ whaletools.init({ apiKey: 'wk_live_...', storeId: 'your-store-uuid' })
44
+
45
+ whaletools.track('add_to_cart', { product_id: 'abc', price: 29.99 })
46
+ whaletools.captureError(new Error('Payment failed'))
47
+ ```
48
+
49
+ ### Server (Next.js App Router)
50
+
51
+ ```ts
52
+ import { withTelemetry } from '@neowhale/telemetry/server'
53
+
54
+ const config = { apiKey: 'wk_live_...', storeId: 'your-store-uuid' }
55
+
56
+ export const GET = withTelemetry(async (req) => {
57
+ return Response.json({ ok: true })
58
+ }, config)
59
+ ```
60
+
61
+ ### Server (Manual Error Reporting)
62
+
63
+ ```ts
64
+ import { reportServerError } from '@neowhale/telemetry/server'
65
+
66
+ const config = { apiKey: 'wk_live_...', storeId: 'your-store-uuid' }
67
+
68
+ try {
69
+ await riskyOperation()
70
+ } catch (err) {
71
+ await reportServerError(err as Error, config, { context: 'cron_job' })
72
+ }
73
+ ```
74
+
75
+ ### Server (AI/LLM Call Tracking)
76
+
77
+ ```ts
78
+ import { reportAICall } from '@neowhale/telemetry/server'
79
+
80
+ const config = { apiKey: 'wk_live_...', storeId: 'your-store-uuid' }
81
+
82
+ const start = Date.now()
83
+ const response = await openai.chat.completions.create({ model: 'gpt-4o', messages })
84
+
85
+ await reportAICall({
86
+ model: 'gpt-4o',
87
+ provider: 'openai',
88
+ prompt_tokens: response.usage?.prompt_tokens,
89
+ completion_tokens: response.usage?.completion_tokens,
90
+ duration_ms: Date.now() - start,
91
+ status: 'ok',
92
+ }, config)
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Configuration
98
+
99
+ ### `WhaleToolsConfig` (browser)
100
+
101
+ | Option | Type | Default | Description |
102
+ |---|---|---|---|
103
+ | `apiKey` | `string` | **required** | API key (`wk_live_...` or `wk_test_...`) |
104
+ | `storeId` | `string` | **required** | Store UUID |
105
+ | `endpoint` | `string` | `"https://whale-gateway.fly.dev"` | Gateway URL |
106
+ | `errors` | `boolean` | `true` | Auto-capture unhandled errors |
107
+ | `analytics` | `boolean` | `true` | Auto-capture page views |
108
+ | `vitals` | `boolean` | `true` | Collect Web Vitals |
109
+ | `breadcrumbs` | `boolean` | `true` | Auto-collect breadcrumbs |
110
+ | `environment` | `string` | `"production"` | Environment tag |
111
+ | `serviceName` | `string` | `"store_client"` | Service name tag |
112
+ | `serviceVersion` | `string` | `""` | Service version tag |
113
+ | `flushInterval` | `number` | `5000` | Flush interval in ms |
114
+ | `flushThreshold` | `number` | `10` | Max queued items before auto-flush |
115
+ | `debug` | `boolean` | `false` | Log telemetry to console |
116
+ | `sampleRate` | `number` | `1` | Analytics sample rate (0--1) |
117
+ | `beforeSend` | `(error: ErrorPayload) => ErrorPayload \| false` | -- | Mutate or drop errors before send |
118
+
119
+ ### `ServerConfig` (server)
120
+
121
+ | Option | Type | Default | Description |
122
+ |---|---|---|---|
123
+ | `apiKey` | `string` | **required** | API key |
124
+ | `storeId` | `string` | **required** | Store UUID |
125
+ | `endpoint` | `string` | `"https://whale-gateway.fly.dev"` | Gateway URL |
126
+ | `serviceName` | `string` | `"store_server"` | Service name tag |
127
+ | `environment` | `string` | `"production"` | Environment tag |
128
+
129
+ ---
130
+
131
+ ## API Reference
132
+
133
+ ### Core -- `@neowhale/telemetry`
134
+
135
+ The default export provides a pre-initialized `whaletools` singleton of type `WhaleToolsClient`.
136
+
137
+ ```ts
138
+ import { whaletools } from '@neowhale/telemetry'
139
+ ```
140
+
141
+ #### `whaletools.init(config: WhaleToolsConfig): void`
142
+
143
+ Initialize the client. Must be called once before other methods. In the browser, automatically installs error handlers, page view tracking, Web Vitals collection, and breadcrumb capture based on config flags.
144
+
145
+ #### `whaletools.captureError(error: Error | string, extra?: Record<string, unknown>): void`
146
+
147
+ Manually capture an error. Generates a SHA-256 fingerprint, attaches breadcrumbs, and queues for delivery.
148
+
149
+ #### `whaletools.captureMessage(message: string, severity?: Severity, extra?: Record<string, unknown>): void`
150
+
151
+ Capture a message as an error event. Severity is one of `"debug" | "info" | "warning" | "error" | "fatal"` (default `"info"`).
152
+
153
+ #### `whaletools.track(eventName: string, properties?: Record<string, unknown>): void`
154
+
155
+ Track a custom analytics event. Automatically enriched with `page_url` and `page_title`. Subject to `sampleRate`.
156
+
157
+ #### `whaletools.page(properties?: Record<string, unknown>): void`
158
+
159
+ Track a page view. Enriched with `page_url`, `page_path`, and `page_title`. Called automatically on init and SPA navigation when `analytics` is enabled.
160
+
161
+ #### `whaletools.identify(userId: string, traits?: Record<string, unknown>): void`
162
+
163
+ Set user context. Traits such as `email` and `name` are attached to subsequent telemetry payloads.
164
+
165
+ #### `whaletools.trackAICall(call: AICallPayload): void`
166
+
167
+ Track an AI/LLM API call. Automatically calculates `total_tokens` from `prompt_tokens + completion_tokens` if omitted.
168
+
169
+ #### `whaletools.addBreadcrumb(category: string, message: string, data?: Record<string, unknown>): void`
170
+
171
+ Add a manual breadcrumb to the ring buffer (max 25).
172
+
173
+ #### `whaletools.flush(): void`
174
+
175
+ Force-flush all queued errors, events, vitals, and AI calls to the gateway.
176
+
177
+ #### `whaletools.destroy(): void`
178
+
179
+ Stop the flush timer, perform a final flush, and reset the initialized state.
180
+
181
+ #### `addBreadcrumb(category, message, level?, data?)` (standalone)
182
+
183
+ ```ts
184
+ import { addBreadcrumb } from '@neowhale/telemetry'
185
+
186
+ addBreadcrumb('checkout', 'User entered payment info', 'info', { step: 3 })
187
+ ```
188
+
189
+ Add a breadcrumb directly to the global ring buffer without going through the client instance.
190
+
191
+ ---
192
+
193
+ ### React -- `@neowhale/telemetry/react`
194
+
195
+ ```ts
196
+ import { WhaleTelemetry, WhaleErrorBoundary } from '@neowhale/telemetry/react'
197
+ ```
198
+
199
+ #### `<WhaleTelemetry {...config} />`
200
+
201
+ Provider component. Accepts all `WhaleToolsConfig` props plus `children`. Calls `whaletools.init()` on mount and `whaletools.destroy()` on unmount.
202
+
203
+ #### `<WhaleErrorBoundary />`
204
+
205
+ React error boundary that reports caught render errors to WhaleTools.
206
+
207
+ | Prop | Type | Description |
208
+ |---|---|---|
209
+ | `children` | `ReactNode` | Child components to wrap |
210
+ | `fallback` | `ReactNode \| (error: Error) => ReactNode` | Fallback UI on error |
211
+ | `onError` | `(error: Error, errorInfo: { componentStack: string }) => void` | Callback on error |
212
+
213
+ ---
214
+
215
+ ### Server -- `@neowhale/telemetry/server`
216
+
217
+ ```ts
218
+ import { withTelemetry, reportServerError, reportAICall, reportAICallBatch } from '@neowhale/telemetry/server'
219
+ ```
220
+
221
+ #### `withTelemetry(handler, config): handler`
222
+
223
+ Wraps a route handler (Next.js App Router, etc.) with automatic error capture. Catches unhandled errors, reports them to the gateway, and re-throws so the framework can handle the response.
224
+
225
+ #### `reportServerError(error: Error, config: ServerConfig, extra?: Record<string, unknown>): Promise<void>`
226
+
227
+ Manually report a server-side error. Use in `catch` blocks where `withTelemetry` is not applicable.
228
+
229
+ #### `reportAICall(call: AICallReport, config: ServerConfig): Promise<void>`
230
+
231
+ Report a single AI/LLM API call. `total_tokens` is auto-calculated from `prompt_tokens + completion_tokens` if omitted.
232
+
233
+ #### `reportAICallBatch(calls: AICallReport[], config: ServerConfig): Promise<void>`
234
+
235
+ Report multiple AI/LLM calls in a single request.
236
+
237
+ ---
238
+
239
+ ## Types
240
+
241
+ ### `ErrorPayload`
242
+
243
+ ```ts
244
+ interface ErrorPayload {
245
+ error_type: string
246
+ error_message: string
247
+ stack_trace: string
248
+ fingerprint: string
249
+ severity: 'debug' | 'info' | 'warning' | 'error' | 'fatal'
250
+ source_file: string
251
+ source_line: number
252
+ source_function: string
253
+ tags: Record<string, string>
254
+ extra: Record<string, unknown>
255
+ breadcrumbs: Breadcrumb[]
256
+ occurred_at: string
257
+ platform: string
258
+ }
259
+ ```
260
+
261
+ ### `Breadcrumb`
262
+
263
+ ```ts
264
+ interface Breadcrumb {
265
+ timestamp: string
266
+ category: string
267
+ message: string
268
+ level: 'debug' | 'info' | 'warning' | 'error'
269
+ data?: Record<string, unknown>
270
+ }
271
+ ```
272
+
273
+ ### `AnalyticsEvent`
274
+
275
+ ```ts
276
+ interface AnalyticsEvent {
277
+ event_name: string
278
+ properties: Record<string, unknown>
279
+ timestamp: string
280
+ }
281
+ ```
282
+
283
+ ### `WebVital`
284
+
285
+ ```ts
286
+ interface WebVital {
287
+ name: 'CLS' | 'FID' | 'LCP' | 'INP' | 'TTFB' | 'FCP'
288
+ value: number
289
+ rating: 'good' | 'needs-improvement' | 'poor'
290
+ timestamp: string
291
+ }
292
+ ```
293
+
294
+ ### `AICallPayload`
295
+
296
+ ```ts
297
+ interface AICallPayload {
298
+ model: string // required
299
+ provider?: string
300
+ operation?: string
301
+ prompt_tokens?: number
302
+ completion_tokens?: number
303
+ total_tokens?: number
304
+ cost?: number
305
+ duration_ms?: number
306
+ status?: 'ok' | 'error'
307
+ error_message?: string
308
+ http_status?: number
309
+ agent_id?: string
310
+ conversation_id?: string
311
+ tool_name?: string
312
+ parent_span_id?: string
313
+ attributes?: Record<string, unknown>
314
+ timestamp?: string
315
+ }
316
+ ```
317
+
318
+ ---
319
+
320
+ ## Internals
321
+
322
+ **Transport** -- Telemetry is batched and sent via HTTP POST to `/v1/stores/{storeId}/telemetry/ingest`. On page unload, the client falls back to `navigator.sendBeacon` to avoid data loss.
323
+
324
+ **Sessions** -- `visitor_id` is persisted in `localStorage` (`wt_vid`). `session_id` (`wt_sid`) resets after 30 minutes of inactivity.
325
+
326
+ **Fingerprinting** -- Errors are deduplicated using a SHA-256 hash of `type|message|source`. Falls back to djb2 when SubtleCrypto is unavailable.
327
+
328
+ **Breadcrumbs** -- Automatically collected categories: `ui.click`, `navigation`, `console.warn`, `console.error`, `fetch`. Stored in a ring buffer (max 25 entries) and attached to error payloads.
329
+
330
+ **Web Vitals** -- LCP, FID, CLS, and FCP are measured via `PerformanceObserver`. Ratings follow web.dev thresholds.
331
+
332
+ ## License
333
+
334
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neowhale/telemetry",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Error tracking, analytics, and Web Vitals for WhaleTools stores",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",