@fullevent/node 0.0.1
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.
- package/dist/index.d.mts +1096 -0
- package/dist/index.d.ts +1096 -0
- package/dist/index.js +573 -0
- package/dist/index.mjs +543 -0
- package/package.json +23 -0
- package/scripts/generate-docs.ts +917 -0
- package/src/builder.ts +307 -0
- package/src/client.ts +325 -0
- package/src/index.ts +272 -0
- package/src/middleware/express.ts +193 -0
- package/src/middleware/hono.ts +395 -0
- package/tsconfig.json +11 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,1096 @@
|
|
|
1
|
+
import { Context, Next } from 'hono';
|
|
2
|
+
import { Request, Response, NextFunction } from 'express';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for tail-based sampling.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Tail sampling makes the decision AFTER the request completes,
|
|
9
|
+
* allowing you to keep all errors and slow requests while sampling
|
|
10
|
+
* normal traffic. This gives you 100% visibility into problems.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const sampling: SamplingConfig = {
|
|
15
|
+
* defaultRate: 0.1, // Keep 10% of normal requests
|
|
16
|
+
* alwaysKeepErrors: true, // But 100% of errors
|
|
17
|
+
* slowRequestThresholdMs: 500, // And anything slow
|
|
18
|
+
* alwaysKeepPaths: ['/api/checkout', '/api/payment'],
|
|
19
|
+
* alwaysKeepUsers: ['usr_vip_123'],
|
|
20
|
+
* };
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @category Middleware
|
|
24
|
+
*/
|
|
25
|
+
interface SamplingConfig {
|
|
26
|
+
/**
|
|
27
|
+
* Base sample rate for normal successful requests.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* Value between 0.0 and 1.0. For example, 0.1 means 10% of
|
|
31
|
+
* successful requests are kept.
|
|
32
|
+
*
|
|
33
|
+
* @defaultValue `1.0` (keep all)
|
|
34
|
+
*/
|
|
35
|
+
defaultRate?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Always keep error responses (4xx/5xx status codes).
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Highly recommended to leave enabled. Errors are rare and
|
|
41
|
+
* you want 100% visibility into failures.
|
|
42
|
+
*
|
|
43
|
+
* @defaultValue `true`
|
|
44
|
+
*/
|
|
45
|
+
alwaysKeepErrors?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Always keep requests slower than this threshold.
|
|
48
|
+
*
|
|
49
|
+
* @remarks
|
|
50
|
+
* Slow requests often indicate problems. This ensures you
|
|
51
|
+
* capture them even at low sample rates.
|
|
52
|
+
*
|
|
53
|
+
* @defaultValue `2000` (2 seconds)
|
|
54
|
+
*/
|
|
55
|
+
slowRequestThresholdMs?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Always keep requests matching these paths.
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* Uses substring matching. Useful for critical paths like
|
|
61
|
+
* checkout, payment, or authentication.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* alwaysKeepPaths: ['/api/checkout', '/api/payment', '/auth']
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
alwaysKeepPaths?: string[];
|
|
69
|
+
/**
|
|
70
|
+
* Always keep requests from these user IDs.
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* Useful for debugging specific users or VIP accounts.
|
|
74
|
+
* Requires `user_id` to be set on the event.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* alwaysKeepUsers: ['usr_vip_123', 'usr_debug_456']
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
alwaysKeepUsers?: string[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Configuration for the wide logger middleware.
|
|
85
|
+
*
|
|
86
|
+
* @example Minimal Config
|
|
87
|
+
* ```typescript
|
|
88
|
+
* wideLogger({
|
|
89
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
90
|
+
* service: 'checkout-api',
|
|
91
|
+
* })
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* @example Full Config
|
|
95
|
+
* ```typescript
|
|
96
|
+
* wideLogger({
|
|
97
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
98
|
+
* service: 'checkout-api',
|
|
99
|
+
* environment: 'production',
|
|
100
|
+
* region: 'us-east-1',
|
|
101
|
+
* sampling: {
|
|
102
|
+
* defaultRate: 0.1,
|
|
103
|
+
* alwaysKeepErrors: true,
|
|
104
|
+
* slowRequestThresholdMs: 500,
|
|
105
|
+
* },
|
|
106
|
+
* })
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @category Middleware
|
|
110
|
+
*/
|
|
111
|
+
interface WideLoggerConfig {
|
|
112
|
+
/**
|
|
113
|
+
* Your FullEvent API key.
|
|
114
|
+
*
|
|
115
|
+
* @remarks
|
|
116
|
+
* Get this from your FullEvent dashboard under Project Settings → API Keys.
|
|
117
|
+
*/
|
|
118
|
+
apiKey: string;
|
|
119
|
+
/**
|
|
120
|
+
* Service name to tag all events with.
|
|
121
|
+
*
|
|
122
|
+
* @remarks
|
|
123
|
+
* Used for filtering and grouping in the dashboard.
|
|
124
|
+
* Examples: 'checkout-api', 'user-service', 'payment-worker'
|
|
125
|
+
*/
|
|
126
|
+
service: string;
|
|
127
|
+
/**
|
|
128
|
+
* Base URL for the FullEvent API.
|
|
129
|
+
*
|
|
130
|
+
* @defaultValue `'https://api.fullevent.io'`
|
|
131
|
+
*
|
|
132
|
+
* @remarks
|
|
133
|
+
* Only override for self-hosted deployments or local development.
|
|
134
|
+
*/
|
|
135
|
+
baseUrl?: string;
|
|
136
|
+
/**
|
|
137
|
+
* Environment tag for all events.
|
|
138
|
+
*
|
|
139
|
+
* @defaultValue `process.env.NODE_ENV` or `'development'`
|
|
140
|
+
*/
|
|
141
|
+
environment?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Region tag for all events.
|
|
144
|
+
*
|
|
145
|
+
* @remarks
|
|
146
|
+
* Useful for multi-region deployments. Examples: 'us-east-1', 'eu-west-1'
|
|
147
|
+
*/
|
|
148
|
+
region?: string;
|
|
149
|
+
/**
|
|
150
|
+
* Sampling configuration for tail-based sampling.
|
|
151
|
+
*
|
|
152
|
+
* @see {@link SamplingConfig}
|
|
153
|
+
*/
|
|
154
|
+
sampling?: SamplingConfig;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Type for Hono context variables.
|
|
158
|
+
*
|
|
159
|
+
* @remarks
|
|
160
|
+
* Use this to type your Hono app for proper TypeScript support.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* import { Hono } from 'hono';
|
|
165
|
+
* import { wideLogger, WideEventVariables } from '@fullevent/node-sdk';
|
|
166
|
+
*
|
|
167
|
+
* const app = new Hono<{ Variables: WideEventVariables }>();
|
|
168
|
+
*
|
|
169
|
+
* app.use(wideLogger({ apiKey: '...', service: 'my-api' }));
|
|
170
|
+
*
|
|
171
|
+
* app.get('/', (c) => {
|
|
172
|
+
* const event = c.get('wideEvent'); // Properly typed!
|
|
173
|
+
* event.user_id = 'usr_123';
|
|
174
|
+
* return c.text('Hello!');
|
|
175
|
+
* });
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @category Middleware
|
|
179
|
+
*/
|
|
180
|
+
type WideEventVariables = {
|
|
181
|
+
/** The wide event for the current request */
|
|
182
|
+
wideEvent: WideEvent;
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Hono middleware for Wide Event logging.
|
|
186
|
+
*
|
|
187
|
+
* @remarks
|
|
188
|
+
* Creates a single, rich event per request that captures the complete context.
|
|
189
|
+
* The event is initialized with request data and automatically finalized with
|
|
190
|
+
* status, duration, and outcome. Your handlers enrich it with business context.
|
|
191
|
+
*
|
|
192
|
+
* ## How It Works
|
|
193
|
+
*
|
|
194
|
+
* 1. **Request Start**: Middleware creates the event with request context
|
|
195
|
+
* 2. **Handler Runs**: Your code enriches the event via `c.get('wideEvent')`
|
|
196
|
+
* 3. **Request End**: Middleware adds status/duration and sends to FullEvent
|
|
197
|
+
*
|
|
198
|
+
* ## Features
|
|
199
|
+
*
|
|
200
|
+
* - **Automatic context capture**: method, path, status, duration, errors
|
|
201
|
+
* - **Distributed tracing**: Propagates `x-fullevent-trace-id` headers
|
|
202
|
+
* - **Tail-based sampling**: 100% error visibility at any sample rate
|
|
203
|
+
* - **Fire and forget**: Non-blocking, won't slow down your responses
|
|
204
|
+
*
|
|
205
|
+
* @param config - Middleware configuration
|
|
206
|
+
* @returns Hono middleware function
|
|
207
|
+
*
|
|
208
|
+
* @example Quick Start
|
|
209
|
+
* ```typescript
|
|
210
|
+
* import { Hono } from 'hono';
|
|
211
|
+
* import { wideLogger, WideEventVariables } from '@fullevent/node-sdk';
|
|
212
|
+
*
|
|
213
|
+
* const app = new Hono<{ Variables: WideEventVariables }>();
|
|
214
|
+
*
|
|
215
|
+
* app.use(wideLogger({
|
|
216
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
217
|
+
* service: 'checkout-api',
|
|
218
|
+
* }));
|
|
219
|
+
* ```
|
|
220
|
+
*
|
|
221
|
+
* @example Enriching Events
|
|
222
|
+
* ```typescript
|
|
223
|
+
* app.post('/checkout', async (c) => {
|
|
224
|
+
* const event = c.get('wideEvent');
|
|
225
|
+
*
|
|
226
|
+
* // Add user context
|
|
227
|
+
* event.user = {
|
|
228
|
+
* id: user.id,
|
|
229
|
+
* subscription: user.plan,
|
|
230
|
+
* account_age_days: daysSince(user.createdAt),
|
|
231
|
+
* };
|
|
232
|
+
*
|
|
233
|
+
* // Add cart context
|
|
234
|
+
* event.cart = {
|
|
235
|
+
* id: cart.id,
|
|
236
|
+
* item_count: cart.items.length,
|
|
237
|
+
* total_cents: cart.total,
|
|
238
|
+
* };
|
|
239
|
+
*
|
|
240
|
+
* // Add payment timing
|
|
241
|
+
* const paymentStart = Date.now();
|
|
242
|
+
* const payment = await processPayment(cart);
|
|
243
|
+
* event.payment = {
|
|
244
|
+
* provider: 'stripe',
|
|
245
|
+
* latency_ms: Date.now() - paymentStart,
|
|
246
|
+
* };
|
|
247
|
+
*
|
|
248
|
+
* return c.json({ orderId: payment.orderId });
|
|
249
|
+
* });
|
|
250
|
+
* ```
|
|
251
|
+
*
|
|
252
|
+
* @example With Sampling
|
|
253
|
+
* ```typescript
|
|
254
|
+
* app.use(wideLogger({
|
|
255
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
256
|
+
* service: 'checkout-api',
|
|
257
|
+
* sampling: {
|
|
258
|
+
* defaultRate: 0.1, // 10% of normal traffic
|
|
259
|
+
* alwaysKeepErrors: true, // 100% of errors
|
|
260
|
+
* slowRequestThresholdMs: 500, // Slow requests
|
|
261
|
+
* alwaysKeepPaths: ['/api/checkout'], // Critical paths
|
|
262
|
+
* },
|
|
263
|
+
* }));
|
|
264
|
+
* ```
|
|
265
|
+
*
|
|
266
|
+
* @category Middleware
|
|
267
|
+
*/
|
|
268
|
+
declare const wideLogger: (config: WideLoggerConfig) => (c: Context<{
|
|
269
|
+
Variables: WideEventVariables;
|
|
270
|
+
}>, next: Next) => Promise<void>;
|
|
271
|
+
|
|
272
|
+
declare global {
|
|
273
|
+
namespace Express {
|
|
274
|
+
interface Request {
|
|
275
|
+
/** The wide event for the current request */
|
|
276
|
+
wideEvent: WideEvent;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Express middleware for Wide Event logging.
|
|
282
|
+
*
|
|
283
|
+
* @remarks
|
|
284
|
+
* Creates a single, rich event per request that captures the complete context.
|
|
285
|
+
* The event is initialized with request data and automatically finalized with
|
|
286
|
+
* status, duration, and outcome. Your handlers enrich it with business context.
|
|
287
|
+
*
|
|
288
|
+
* ## How It Works
|
|
289
|
+
*
|
|
290
|
+
* 1. **Request Start**: Middleware creates the event with request context
|
|
291
|
+
* 2. **Handler Runs**: Your code enriches the event via `req.wideEvent`
|
|
292
|
+
* 3. **Response Finish**: Middleware adds status/duration and sends to FullEvent
|
|
293
|
+
*
|
|
294
|
+
* ## Features
|
|
295
|
+
*
|
|
296
|
+
* - **Automatic context capture**: method, path, status, duration
|
|
297
|
+
* - **Distributed tracing**: Propagates `x-fullevent-trace-id` headers
|
|
298
|
+
* - **Tail-based sampling**: 100% error visibility at any sample rate
|
|
299
|
+
* - **Fire and forget**: Non-blocking, won't slow down your responses
|
|
300
|
+
*
|
|
301
|
+
* @param config - Middleware configuration
|
|
302
|
+
* @returns Express middleware function
|
|
303
|
+
*
|
|
304
|
+
* @example Quick Start
|
|
305
|
+
* ```typescript
|
|
306
|
+
* import express from 'express';
|
|
307
|
+
* import { expressWideLogger } from '@fullevent/node-sdk';
|
|
308
|
+
*
|
|
309
|
+
* const app = express();
|
|
310
|
+
*
|
|
311
|
+
* app.use(expressWideLogger({
|
|
312
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
313
|
+
* service: 'checkout-api',
|
|
314
|
+
* }));
|
|
315
|
+
* ```
|
|
316
|
+
*
|
|
317
|
+
* @example Enriching Events
|
|
318
|
+
* ```typescript
|
|
319
|
+
* app.post('/checkout', async (req, res) => {
|
|
320
|
+
* const event = req.wideEvent;
|
|
321
|
+
*
|
|
322
|
+
* // Add user context
|
|
323
|
+
* event.user = {
|
|
324
|
+
* id: req.user.id,
|
|
325
|
+
* subscription: req.user.plan,
|
|
326
|
+
* };
|
|
327
|
+
*
|
|
328
|
+
* // Add cart context
|
|
329
|
+
* event.cart = {
|
|
330
|
+
* id: cart.id,
|
|
331
|
+
* item_count: cart.items.length,
|
|
332
|
+
* total_cents: cart.total,
|
|
333
|
+
* };
|
|
334
|
+
*
|
|
335
|
+
* // Add payment timing
|
|
336
|
+
* const paymentStart = Date.now();
|
|
337
|
+
* const payment = await processPayment(cart);
|
|
338
|
+
* event.payment = {
|
|
339
|
+
* provider: 'stripe',
|
|
340
|
+
* latency_ms: Date.now() - paymentStart,
|
|
341
|
+
* };
|
|
342
|
+
*
|
|
343
|
+
* res.json({ orderId: payment.orderId });
|
|
344
|
+
* });
|
|
345
|
+
* ```
|
|
346
|
+
*
|
|
347
|
+
* @example With Sampling
|
|
348
|
+
* ```typescript
|
|
349
|
+
* app.use(expressWideLogger({
|
|
350
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
351
|
+
* service: 'checkout-api',
|
|
352
|
+
* sampling: {
|
|
353
|
+
* defaultRate: 0.1, // 10% of normal traffic
|
|
354
|
+
* alwaysKeepErrors: true, // 100% of errors
|
|
355
|
+
* slowRequestThresholdMs: 500, // Slow requests
|
|
356
|
+
* },
|
|
357
|
+
* }));
|
|
358
|
+
* ```
|
|
359
|
+
*
|
|
360
|
+
* @category Middleware
|
|
361
|
+
*/
|
|
362
|
+
declare function expressWideLogger(config: WideLoggerConfig): (req: Request, res: Response, next: NextFunction) => void;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Configuration options for the FullEvent client.
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```typescript
|
|
369
|
+
* const client = new FullEvent({
|
|
370
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
371
|
+
* baseUrl: 'https://api.fullevent.io', // optional
|
|
372
|
+
* ping: true, // send a test ping on initialization
|
|
373
|
+
* });
|
|
374
|
+
* ```
|
|
375
|
+
*
|
|
376
|
+
* @category Client
|
|
377
|
+
*/
|
|
378
|
+
interface FullEventConfig {
|
|
379
|
+
/**
|
|
380
|
+
* Your FullEvent project API key.
|
|
381
|
+
*
|
|
382
|
+
* @remarks
|
|
383
|
+
* Get this from your FullEvent dashboard under Project Settings → API Keys.
|
|
384
|
+
*/
|
|
385
|
+
apiKey: string;
|
|
386
|
+
/**
|
|
387
|
+
* Base URL for the FullEvent API.
|
|
388
|
+
*
|
|
389
|
+
* @defaultValue `'https://api.fullevent.io'`
|
|
390
|
+
*
|
|
391
|
+
* @remarks
|
|
392
|
+
* Only override this for self-hosted deployments or local development.
|
|
393
|
+
*/
|
|
394
|
+
baseUrl?: string;
|
|
395
|
+
/**
|
|
396
|
+
* Send a ping event on initialization to verify connection.
|
|
397
|
+
*
|
|
398
|
+
* @defaultValue `false`
|
|
399
|
+
*
|
|
400
|
+
* @remarks
|
|
401
|
+
* Set to `true` during initial setup to verify your SDK configuration
|
|
402
|
+
* is working correctly. The ping is sent asynchronously and won't block
|
|
403
|
+
* your application startup.
|
|
404
|
+
*/
|
|
405
|
+
ping?: boolean;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Standard properties for HTTP request events.
|
|
409
|
+
*
|
|
410
|
+
* These properties are automatically extracted by FullEvent for first-class
|
|
411
|
+
* filtering, dashboards, and error rate calculations.
|
|
412
|
+
*
|
|
413
|
+
* @example
|
|
414
|
+
* ```typescript
|
|
415
|
+
* const props: HttpRequestProperties = {
|
|
416
|
+
* status_code: 200,
|
|
417
|
+
* method: 'POST',
|
|
418
|
+
* path: '/api/checkout',
|
|
419
|
+
* duration_ms: 234,
|
|
420
|
+
* outcome: 'success',
|
|
421
|
+
* // Plus any custom properties
|
|
422
|
+
* user_id: 'usr_123',
|
|
423
|
+
* order_total: 9999,
|
|
424
|
+
* };
|
|
425
|
+
* ```
|
|
426
|
+
*
|
|
427
|
+
* @category Client
|
|
428
|
+
*/
|
|
429
|
+
interface HttpRequestProperties {
|
|
430
|
+
/**
|
|
431
|
+
* HTTP status code (e.g., 200, 404, 500).
|
|
432
|
+
*
|
|
433
|
+
* @remarks
|
|
434
|
+
* Used for automatic error rate calculations:
|
|
435
|
+
* - `< 400` = success
|
|
436
|
+
* - `>= 400` = error
|
|
437
|
+
*/
|
|
438
|
+
status_code: number;
|
|
439
|
+
/**
|
|
440
|
+
* HTTP method (GET, POST, PUT, DELETE, etc.)
|
|
441
|
+
*/
|
|
442
|
+
method?: string;
|
|
443
|
+
/**
|
|
444
|
+
* Request path (e.g., `/api/users`, `/checkout`)
|
|
445
|
+
*/
|
|
446
|
+
path?: string;
|
|
447
|
+
/**
|
|
448
|
+
* Request duration in milliseconds.
|
|
449
|
+
*/
|
|
450
|
+
duration_ms?: number;
|
|
451
|
+
/**
|
|
452
|
+
* Explicit success/error indicator.
|
|
453
|
+
*
|
|
454
|
+
* @remarks
|
|
455
|
+
* If set, this takes precedence over `status_code` for error rate calculations.
|
|
456
|
+
*/
|
|
457
|
+
outcome?: 'success' | 'error';
|
|
458
|
+
/**
|
|
459
|
+
* Additional custom properties.
|
|
460
|
+
*
|
|
461
|
+
* @remarks
|
|
462
|
+
* Add any context relevant to your application.
|
|
463
|
+
*/
|
|
464
|
+
[key: string]: unknown;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* The main FullEvent client for ingesting events.
|
|
468
|
+
*
|
|
469
|
+
* @remarks
|
|
470
|
+
* Use this client to send events directly from your application.
|
|
471
|
+
* For automatic request logging, see the middleware integrations:
|
|
472
|
+
* - {@link wideLogger} for Hono
|
|
473
|
+
* - {@link expressWideLogger} for Express
|
|
474
|
+
*
|
|
475
|
+
* @example Basic Usage
|
|
476
|
+
* ```typescript
|
|
477
|
+
* import { FullEvent } from '@fullevent/node-sdk';
|
|
478
|
+
*
|
|
479
|
+
* const client = new FullEvent({
|
|
480
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
481
|
+
* });
|
|
482
|
+
*
|
|
483
|
+
* // Ingest a simple event
|
|
484
|
+
* await client.ingest('user.signup', {
|
|
485
|
+
* plan: 'pro',
|
|
486
|
+
* referral: 'newsletter',
|
|
487
|
+
* });
|
|
488
|
+
* ```
|
|
489
|
+
*
|
|
490
|
+
* @example Fire and Forget
|
|
491
|
+
* ```typescript
|
|
492
|
+
* // Don't await if you don't want to block
|
|
493
|
+
* client.ingest('page.view', { path: '/home' })
|
|
494
|
+
* .catch(err => console.error('FullEvent error:', err));
|
|
495
|
+
* ```
|
|
496
|
+
*
|
|
497
|
+
* @category Client
|
|
498
|
+
*/
|
|
499
|
+
declare class FullEvent {
|
|
500
|
+
private apiKey;
|
|
501
|
+
private baseUrl;
|
|
502
|
+
/**
|
|
503
|
+
* Creates a new FullEvent client instance.
|
|
504
|
+
*
|
|
505
|
+
* @param config - Configuration options
|
|
506
|
+
*/
|
|
507
|
+
constructor(config: FullEventConfig);
|
|
508
|
+
/**
|
|
509
|
+
* Ingest a generic event with any properties.
|
|
510
|
+
*
|
|
511
|
+
* @param event - Event name/type (e.g., 'user.signup', 'order.completed')
|
|
512
|
+
* @param properties - Key-value pairs of event data
|
|
513
|
+
* @param timestamp - Optional ISO timestamp (defaults to now)
|
|
514
|
+
* @returns Promise resolving to success/error status
|
|
515
|
+
*
|
|
516
|
+
* @remarks
|
|
517
|
+
* Events are processed asynchronously. The promise resolves when
|
|
518
|
+
* the event is accepted by the API, not when it's fully processed.
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* ```typescript
|
|
522
|
+
* await client.ingest('checkout.completed', {
|
|
523
|
+
* order_id: 'ord_123',
|
|
524
|
+
* total_cents: 9999,
|
|
525
|
+
* items: 3,
|
|
526
|
+
* user: {
|
|
527
|
+
* id: 'usr_456',
|
|
528
|
+
* plan: 'premium',
|
|
529
|
+
* },
|
|
530
|
+
* });
|
|
531
|
+
* ```
|
|
532
|
+
*/
|
|
533
|
+
ingest(event: string, properties?: Record<string, unknown>, timestamp?: string): Promise<{
|
|
534
|
+
success: boolean;
|
|
535
|
+
error?: unknown;
|
|
536
|
+
}>;
|
|
537
|
+
/**
|
|
538
|
+
* Ingest an HTTP request event with typed properties.
|
|
539
|
+
*
|
|
540
|
+
* @param properties - HTTP request properties with optional custom data
|
|
541
|
+
* @param timestamp - Optional ISO timestamp (defaults to now)
|
|
542
|
+
* @returns Promise resolving to success/error status
|
|
543
|
+
*
|
|
544
|
+
* @remarks
|
|
545
|
+
* This is a convenience method that provides TypeScript autocomplete
|
|
546
|
+
* for standard HTTP properties. Under the hood, it calls `ingest()`
|
|
547
|
+
* with the event type `'http_request'`.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```typescript
|
|
551
|
+
* await client.ingestHttpRequest({
|
|
552
|
+
* status_code: 200,
|
|
553
|
+
* method: 'POST',
|
|
554
|
+
* path: '/api/checkout',
|
|
555
|
+
* duration_ms: 234,
|
|
556
|
+
* outcome: 'success',
|
|
557
|
+
* // Custom properties
|
|
558
|
+
* user_id: 'usr_123',
|
|
559
|
+
* });
|
|
560
|
+
* ```
|
|
561
|
+
*/
|
|
562
|
+
ingestHttpRequest(properties: HttpRequestProperties, timestamp?: string): Promise<{
|
|
563
|
+
success: boolean;
|
|
564
|
+
error?: unknown;
|
|
565
|
+
}>;
|
|
566
|
+
/**
|
|
567
|
+
* Ping the FullEvent API to verify connection.
|
|
568
|
+
*
|
|
569
|
+
* @returns Promise resolving to connection status with latency
|
|
570
|
+
*
|
|
571
|
+
* @remarks
|
|
572
|
+
* Use this method to verify your SDK is correctly configured.
|
|
573
|
+
* It sends a lightweight ping event and measures round-trip latency.
|
|
574
|
+
* Commonly used during setup or in health check endpoints.
|
|
575
|
+
*
|
|
576
|
+
* @example Basic ping
|
|
577
|
+
* ```typescript
|
|
578
|
+
* const result = await client.ping();
|
|
579
|
+
* if (result.success) {
|
|
580
|
+
* console.log(`Connected! Latency: ${result.latency_ms}ms`);
|
|
581
|
+
* } else {
|
|
582
|
+
* console.error('Connection failed:', result.error);
|
|
583
|
+
* }
|
|
584
|
+
* ```
|
|
585
|
+
*
|
|
586
|
+
* @example Health check endpoint
|
|
587
|
+
* ```typescript
|
|
588
|
+
* app.get('/health', async (c) => {
|
|
589
|
+
* const ping = await fullevent.ping();
|
|
590
|
+
* return c.json({
|
|
591
|
+
* status: ping.success ? 'healthy' : 'degraded',
|
|
592
|
+
* fullevent: ping,
|
|
593
|
+
* });
|
|
594
|
+
* });
|
|
595
|
+
* ```
|
|
596
|
+
*/
|
|
597
|
+
ping(): Promise<{
|
|
598
|
+
success: boolean;
|
|
599
|
+
latency_ms?: number;
|
|
600
|
+
error?: unknown;
|
|
601
|
+
}>;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* A fluent builder for enriching wide events throughout the request lifecycle.
|
|
606
|
+
*
|
|
607
|
+
* @remarks
|
|
608
|
+
* While you can modify the event object directly (and that's perfectly fine),
|
|
609
|
+
* the builder provides chainable methods for cleaner code and useful helpers.
|
|
610
|
+
*
|
|
611
|
+
* ## Two Approaches
|
|
612
|
+
*
|
|
613
|
+
* **Direct access (simple):**
|
|
614
|
+
* ```typescript
|
|
615
|
+
* const event = c.get('wideEvent');
|
|
616
|
+
* event.user = { id: user.id, plan: user.plan };
|
|
617
|
+
* event.cart = { total: cart.total, items: cart.items.length };
|
|
618
|
+
* ```
|
|
619
|
+
*
|
|
620
|
+
* **Builder pattern (chainable):**
|
|
621
|
+
* ```typescript
|
|
622
|
+
* new WideEventBuilder(c.get('wideEvent'))
|
|
623
|
+
* .setContext('user', { id: user.id, plan: user.plan })
|
|
624
|
+
* .setContext('cart', { total: cart.total, items: cart.items.length })
|
|
625
|
+
* .setTiming('db_latency_ms', dbStart);
|
|
626
|
+
* ```
|
|
627
|
+
*
|
|
628
|
+
* @example Full Example
|
|
629
|
+
* ```typescript
|
|
630
|
+
* const builder = new WideEventBuilder(c.get('wideEvent'));
|
|
631
|
+
*
|
|
632
|
+
* builder
|
|
633
|
+
* .setUser(user.id)
|
|
634
|
+
* .setContext('user', {
|
|
635
|
+
* subscription: user.plan,
|
|
636
|
+
* account_age_days: daysSince(user.createdAt),
|
|
637
|
+
* lifetime_value_cents: user.ltv,
|
|
638
|
+
* })
|
|
639
|
+
* .setContext('cart', {
|
|
640
|
+
* id: cart.id,
|
|
641
|
+
* item_count: cart.items.length,
|
|
642
|
+
* total_cents: cart.total,
|
|
643
|
+
* });
|
|
644
|
+
*
|
|
645
|
+
* // Later, after payment processing
|
|
646
|
+
* builder
|
|
647
|
+
* .setContext('payment', { method: 'card', provider: 'stripe' })
|
|
648
|
+
* .setTiming('payment_latency_ms', paymentStart);
|
|
649
|
+
*
|
|
650
|
+
* if (paymentError) {
|
|
651
|
+
* builder.setError({
|
|
652
|
+
* type: 'PaymentError',
|
|
653
|
+
* code: paymentError.code,
|
|
654
|
+
* message: paymentError.message,
|
|
655
|
+
* stripe_decline_code: paymentError.declineCode,
|
|
656
|
+
* });
|
|
657
|
+
* }
|
|
658
|
+
* ```
|
|
659
|
+
*
|
|
660
|
+
* @category Builder
|
|
661
|
+
*/
|
|
662
|
+
declare class WideEventBuilder {
|
|
663
|
+
private event;
|
|
664
|
+
/**
|
|
665
|
+
* Creates a new builder wrapping the given event.
|
|
666
|
+
*
|
|
667
|
+
* @param event - The wide event to enrich
|
|
668
|
+
*/
|
|
669
|
+
constructor(event: WideEvent);
|
|
670
|
+
/**
|
|
671
|
+
* Returns the underlying event object for direct access.
|
|
672
|
+
*
|
|
673
|
+
* @returns The wrapped WideEvent
|
|
674
|
+
*
|
|
675
|
+
* @example
|
|
676
|
+
* ```typescript
|
|
677
|
+
* const event = builder.getEvent();
|
|
678
|
+
* console.log(event.user_id);
|
|
679
|
+
* ```
|
|
680
|
+
*/
|
|
681
|
+
getEvent(): WideEvent;
|
|
682
|
+
/**
|
|
683
|
+
* Sets any key-value pair on the event.
|
|
684
|
+
*
|
|
685
|
+
* @param key - Property name
|
|
686
|
+
* @param value - Property value (any type)
|
|
687
|
+
* @returns `this` for chaining
|
|
688
|
+
*
|
|
689
|
+
* @example
|
|
690
|
+
* ```typescript
|
|
691
|
+
* builder
|
|
692
|
+
* .set('order_id', 'ord_123')
|
|
693
|
+
* .set('llm_model', 'gpt-4')
|
|
694
|
+
* .set('tokens_used', 1500);
|
|
695
|
+
* ```
|
|
696
|
+
*/
|
|
697
|
+
set(key: string, value: unknown): this;
|
|
698
|
+
/**
|
|
699
|
+
* Sets a named context object on the event.
|
|
700
|
+
*
|
|
701
|
+
* @remarks
|
|
702
|
+
* This is the primary method for adding structured business context.
|
|
703
|
+
* Each context is a nested object that groups related properties.
|
|
704
|
+
*
|
|
705
|
+
* @param name - Context name (e.g., 'user', 'cart', 'payment')
|
|
706
|
+
* @param data - Context data as key-value pairs
|
|
707
|
+
* @returns `this` for chaining
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```typescript
|
|
711
|
+
* builder
|
|
712
|
+
* .setContext('user', {
|
|
713
|
+
* id: 'user_456',
|
|
714
|
+
* subscription: 'premium',
|
|
715
|
+
* account_age_days: 847,
|
|
716
|
+
* })
|
|
717
|
+
* .setContext('cart', {
|
|
718
|
+
* id: 'cart_xyz',
|
|
719
|
+
* item_count: 3,
|
|
720
|
+
* total_cents: 15999,
|
|
721
|
+
* })
|
|
722
|
+
* .setContext('payment', {
|
|
723
|
+
* method: 'card',
|
|
724
|
+
* provider: 'stripe',
|
|
725
|
+
* });
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
setContext(name: string, data: Record<string, unknown>): this;
|
|
729
|
+
/**
|
|
730
|
+
* Merges additional fields into an existing context object.
|
|
731
|
+
*
|
|
732
|
+
* @remarks
|
|
733
|
+
* Useful for progressively building context throughout the request.
|
|
734
|
+
* If the context doesn't exist, it will be created.
|
|
735
|
+
*
|
|
736
|
+
* @param name - Context name to merge into
|
|
737
|
+
* @param data - Additional data to merge
|
|
738
|
+
* @returns `this` for chaining
|
|
739
|
+
*
|
|
740
|
+
* @example
|
|
741
|
+
* ```typescript
|
|
742
|
+
* // Initial payment context
|
|
743
|
+
* builder.setContext('payment', { method: 'card', provider: 'stripe' });
|
|
744
|
+
*
|
|
745
|
+
* // After payment completes, add timing
|
|
746
|
+
* builder.mergeContext('payment', {
|
|
747
|
+
* latency_ms: Date.now() - paymentStart,
|
|
748
|
+
* attempt: 1,
|
|
749
|
+
* transaction_id: 'txn_123',
|
|
750
|
+
* });
|
|
751
|
+
*
|
|
752
|
+
* // Result: { method, provider, latency_ms, attempt, transaction_id }
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
755
|
+
mergeContext(name: string, data: Record<string, unknown>): this;
|
|
756
|
+
/**
|
|
757
|
+
* Sets the user ID on the event.
|
|
758
|
+
*
|
|
759
|
+
* @remarks
|
|
760
|
+
* This sets the top-level `user_id` field, which is commonly used
|
|
761
|
+
* for filtering and user-centric analytics. For richer user context,
|
|
762
|
+
* use `setContext('user', {...})` instead or in addition.
|
|
763
|
+
*
|
|
764
|
+
* @param userId - The user identifier
|
|
765
|
+
* @returns `this` for chaining
|
|
766
|
+
*
|
|
767
|
+
* @example
|
|
768
|
+
* ```typescript
|
|
769
|
+
* builder.setUser('usr_123');
|
|
770
|
+
*
|
|
771
|
+
* // For richer context, also set a user object:
|
|
772
|
+
* builder.setContext('user', {
|
|
773
|
+
* id: 'usr_123',
|
|
774
|
+
* plan: 'premium',
|
|
775
|
+
* ltv_cents: 50000,
|
|
776
|
+
* });
|
|
777
|
+
* ```
|
|
778
|
+
*/
|
|
779
|
+
setUser(userId: string): this;
|
|
780
|
+
/**
|
|
781
|
+
* Captures an error with structured details.
|
|
782
|
+
*
|
|
783
|
+
* @remarks
|
|
784
|
+
* Automatically sets `outcome` to 'error'. Accepts either a native
|
|
785
|
+
* Error object or a custom error object with additional fields.
|
|
786
|
+
*
|
|
787
|
+
* @param err - Error object or custom error details
|
|
788
|
+
* @returns `this` for chaining
|
|
789
|
+
*
|
|
790
|
+
* @example Native Error
|
|
791
|
+
* ```typescript
|
|
792
|
+
* try {
|
|
793
|
+
* await riskyOperation();
|
|
794
|
+
* } catch (err) {
|
|
795
|
+
* builder.setError(err);
|
|
796
|
+
* }
|
|
797
|
+
* ```
|
|
798
|
+
*
|
|
799
|
+
* @example Custom Error with Context
|
|
800
|
+
* ```typescript
|
|
801
|
+
* builder.setError({
|
|
802
|
+
* type: 'PaymentError',
|
|
803
|
+
* message: 'Card declined by issuer',
|
|
804
|
+
* code: 'card_declined',
|
|
805
|
+
* stripe_decline_code: 'insufficient_funds',
|
|
806
|
+
* card_brand: 'visa',
|
|
807
|
+
* card_last4: '4242',
|
|
808
|
+
* });
|
|
809
|
+
* ```
|
|
810
|
+
*/
|
|
811
|
+
setError(err: Error | {
|
|
812
|
+
type?: string;
|
|
813
|
+
message: string;
|
|
814
|
+
code?: string;
|
|
815
|
+
stack?: string;
|
|
816
|
+
[key: string]: unknown;
|
|
817
|
+
}): this;
|
|
818
|
+
/**
|
|
819
|
+
* Sets the HTTP status code and outcome.
|
|
820
|
+
*
|
|
821
|
+
* @remarks
|
|
822
|
+
* Automatically sets `outcome` based on the status code:
|
|
823
|
+
* - `< 400` → 'success'
|
|
824
|
+
* - `>= 400` → 'error'
|
|
825
|
+
*
|
|
826
|
+
* @param code - HTTP status code
|
|
827
|
+
* @returns `this` for chaining
|
|
828
|
+
*
|
|
829
|
+
* @example
|
|
830
|
+
* ```typescript
|
|
831
|
+
* builder.setStatus(404); // outcome = 'error'
|
|
832
|
+
* builder.setStatus(200); // outcome = 'success'
|
|
833
|
+
* ```
|
|
834
|
+
*/
|
|
835
|
+
setStatus(code: number): this;
|
|
836
|
+
/**
|
|
837
|
+
* Records timing for a specific operation.
|
|
838
|
+
*
|
|
839
|
+
* @remarks
|
|
840
|
+
* A convenience method for calculating and setting duration values.
|
|
841
|
+
* The value is calculated as `Date.now() - startTime`.
|
|
842
|
+
*
|
|
843
|
+
* @param key - Property name for the timing (e.g., 'db_latency_ms')
|
|
844
|
+
* @param startTime - Start timestamp from `Date.now()`
|
|
845
|
+
* @returns `this` for chaining
|
|
846
|
+
*
|
|
847
|
+
* @example
|
|
848
|
+
* ```typescript
|
|
849
|
+
* const dbStart = Date.now();
|
|
850
|
+
* const result = await db.query('SELECT ...');
|
|
851
|
+
* builder.setTiming('db_latency_ms', dbStart);
|
|
852
|
+
*
|
|
853
|
+
* const paymentStart = Date.now();
|
|
854
|
+
* await processPayment();
|
|
855
|
+
* builder.setTiming('payment_latency_ms', paymentStart);
|
|
856
|
+
* ```
|
|
857
|
+
*/
|
|
858
|
+
setTiming(key: string, startTime: number): this;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* @packageDocumentation
|
|
863
|
+
*
|
|
864
|
+
* # FullEvent Node.js SDK
|
|
865
|
+
*
|
|
866
|
+
* The official Node.js SDK for FullEvent - the wide event analytics platform.
|
|
867
|
+
*
|
|
868
|
+
* ## Installation
|
|
869
|
+
*
|
|
870
|
+
* ```bash
|
|
871
|
+
* npm install @fullevent/node-sdk
|
|
872
|
+
* ```
|
|
873
|
+
*
|
|
874
|
+
* ## Quick Start
|
|
875
|
+
*
|
|
876
|
+
* ### Direct Event Ingestion
|
|
877
|
+
*
|
|
878
|
+
* ```typescript
|
|
879
|
+
* import { FullEvent } from '@fullevent/node-sdk';
|
|
880
|
+
*
|
|
881
|
+
* const client = new FullEvent({
|
|
882
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
883
|
+
* });
|
|
884
|
+
*
|
|
885
|
+
* await client.ingest('user.signup', { plan: 'pro' });
|
|
886
|
+
* ```
|
|
887
|
+
*
|
|
888
|
+
* ### Wide Event Middleware (Recommended)
|
|
889
|
+
*
|
|
890
|
+
* ```typescript
|
|
891
|
+
* import { Hono } from 'hono';
|
|
892
|
+
* import { wideLogger, WideEventVariables } from '@fullevent/node-sdk';
|
|
893
|
+
*
|
|
894
|
+
* const app = new Hono<{ Variables: WideEventVariables }>();
|
|
895
|
+
*
|
|
896
|
+
* app.use(wideLogger({
|
|
897
|
+
* apiKey: process.env.FULLEVENT_API_KEY!,
|
|
898
|
+
* service: 'my-api',
|
|
899
|
+
* }));
|
|
900
|
+
*
|
|
901
|
+
* app.post('/checkout', async (c) => {
|
|
902
|
+
* const event = c.get('wideEvent');
|
|
903
|
+
* event.user = { id: user.id, plan: user.plan };
|
|
904
|
+
* event.cart = { total_cents: cart.total, items: cart.items.length };
|
|
905
|
+
* return c.json({ success: true });
|
|
906
|
+
* });
|
|
907
|
+
* ```
|
|
908
|
+
*
|
|
909
|
+
* @module @fullevent/node-sdk
|
|
910
|
+
*/
|
|
911
|
+
|
|
912
|
+
/**
|
|
913
|
+
* A Wide Event captures the complete context of a request in a single,
|
|
914
|
+
* self-describing record.
|
|
915
|
+
*
|
|
916
|
+
* @remarks
|
|
917
|
+
* Instead of emitting many small logs, you build one rich event throughout
|
|
918
|
+
* the request lifecycle and emit it at the end. This makes debugging and
|
|
919
|
+
* analytics significantly easier.
|
|
920
|
+
*
|
|
921
|
+
* ## The Wide Event Pattern
|
|
922
|
+
*
|
|
923
|
+
* 1. **Initialize**: Middleware creates the event with request context
|
|
924
|
+
* 2. **Enrich**: Handlers add business context throughout the request
|
|
925
|
+
* 3. **Emit**: Middleware sends the complete event when the request ends
|
|
926
|
+
*
|
|
927
|
+
* ## Auto-Captured Fields
|
|
928
|
+
*
|
|
929
|
+
* The middleware automatically captures:
|
|
930
|
+
* - `request_id`, `trace_id` - For distributed tracing
|
|
931
|
+
* - `timestamp` - When the request started
|
|
932
|
+
* - `method`, `path` - HTTP method and path
|
|
933
|
+
* - `status_code` - HTTP response status
|
|
934
|
+
* - `duration_ms` - Total request duration
|
|
935
|
+
* - `outcome` - 'success' or 'error'
|
|
936
|
+
* - `service`, `environment`, `region` - Infrastructure context
|
|
937
|
+
*
|
|
938
|
+
* ## Your Business Context
|
|
939
|
+
*
|
|
940
|
+
* Add any fields your application needs:
|
|
941
|
+
*
|
|
942
|
+
* ```typescript
|
|
943
|
+
* event.user = { id: 'usr_123', plan: 'premium', ltv_cents: 50000 };
|
|
944
|
+
* event.cart = { id: 'cart_xyz', items: 3, total_cents: 15999 };
|
|
945
|
+
* event.payment = { provider: 'stripe', method: 'card', latency_ms: 234 };
|
|
946
|
+
* event.feature_flags = { new_checkout: true };
|
|
947
|
+
* event.experiment = { name: 'pricing_v2', variant: 'control' };
|
|
948
|
+
* ```
|
|
949
|
+
*
|
|
950
|
+
* @example Basic Wide Event
|
|
951
|
+
* ```typescript
|
|
952
|
+
* const event: WideEvent = {
|
|
953
|
+
* // Auto-captured by middleware
|
|
954
|
+
* request_id: 'req_abc123',
|
|
955
|
+
* timestamp: '2024-01-15T10:23:45.612Z',
|
|
956
|
+
* method: 'POST',
|
|
957
|
+
* path: '/api/checkout',
|
|
958
|
+
* service: 'checkout-api',
|
|
959
|
+
* status_code: 200,
|
|
960
|
+
* duration_ms: 847,
|
|
961
|
+
* outcome: 'success',
|
|
962
|
+
*
|
|
963
|
+
* // Your business context
|
|
964
|
+
* user: { id: 'usr_456', plan: 'premium' },
|
|
965
|
+
* cart: { total_cents: 15999, items: 3 },
|
|
966
|
+
* payment: { provider: 'stripe', latency_ms: 234 },
|
|
967
|
+
* };
|
|
968
|
+
* ```
|
|
969
|
+
*
|
|
970
|
+
* @category Types
|
|
971
|
+
*/
|
|
972
|
+
interface WideEvent {
|
|
973
|
+
/**
|
|
974
|
+
* Unique identifier for this request.
|
|
975
|
+
*
|
|
976
|
+
* @remarks
|
|
977
|
+
* Auto-generated or extracted from `x-request-id` / `x-fullevent-trace-id` headers.
|
|
978
|
+
*/
|
|
979
|
+
request_id?: string;
|
|
980
|
+
/**
|
|
981
|
+
* Trace ID for distributed tracing.
|
|
982
|
+
*
|
|
983
|
+
* @remarks
|
|
984
|
+
* Propagated across service boundaries via the `x-fullevent-trace-id` header.
|
|
985
|
+
* Same as `request_id` by default.
|
|
986
|
+
*
|
|
987
|
+
* @see {@link https://fullevent.io/docs/distributed-tracing | Distributed Tracing Guide}
|
|
988
|
+
*/
|
|
989
|
+
trace_id?: string;
|
|
990
|
+
/**
|
|
991
|
+
* ISO timestamp when the request started.
|
|
992
|
+
*/
|
|
993
|
+
timestamp: string;
|
|
994
|
+
/**
|
|
995
|
+
* HTTP method (GET, POST, PUT, DELETE, etc.)
|
|
996
|
+
*/
|
|
997
|
+
method: string;
|
|
998
|
+
/**
|
|
999
|
+
* Request path (e.g., `/api/checkout`)
|
|
1000
|
+
*/
|
|
1001
|
+
path: string;
|
|
1002
|
+
/**
|
|
1003
|
+
* HTTP status code.
|
|
1004
|
+
*
|
|
1005
|
+
* @remarks
|
|
1006
|
+
* Auto-captured from the response. Used for error rate calculations.
|
|
1007
|
+
*/
|
|
1008
|
+
status_code?: number;
|
|
1009
|
+
/**
|
|
1010
|
+
* Request duration in milliseconds.
|
|
1011
|
+
*
|
|
1012
|
+
* @remarks
|
|
1013
|
+
* Auto-captured by middleware in the `finally` block.
|
|
1014
|
+
*/
|
|
1015
|
+
duration_ms?: number;
|
|
1016
|
+
/**
|
|
1017
|
+
* Request outcome: 'success' or 'error'.
|
|
1018
|
+
*
|
|
1019
|
+
* @remarks
|
|
1020
|
+
* Auto-set based on `status_code` (>= 400 = error).
|
|
1021
|
+
* Can be overridden manually.
|
|
1022
|
+
*/
|
|
1023
|
+
outcome?: 'success' | 'error';
|
|
1024
|
+
/**
|
|
1025
|
+
* Service name (e.g., 'checkout-api', 'user-service').
|
|
1026
|
+
*
|
|
1027
|
+
* @remarks
|
|
1028
|
+
* Set via middleware config. Used for filtering and grouping.
|
|
1029
|
+
*/
|
|
1030
|
+
service: string;
|
|
1031
|
+
/**
|
|
1032
|
+
* Deployment region (e.g., 'us-east-1', 'eu-west-1').
|
|
1033
|
+
*/
|
|
1034
|
+
region?: string;
|
|
1035
|
+
/**
|
|
1036
|
+
* Environment (e.g., 'production', 'staging', 'development').
|
|
1037
|
+
*
|
|
1038
|
+
* @remarks
|
|
1039
|
+
* Defaults to `NODE_ENV` if not specified.
|
|
1040
|
+
*/
|
|
1041
|
+
environment?: string;
|
|
1042
|
+
/**
|
|
1043
|
+
* User identifier.
|
|
1044
|
+
*
|
|
1045
|
+
* @remarks
|
|
1046
|
+
* The most commonly enriched field. For richer user context,
|
|
1047
|
+
* add a `user` object with additional properties.
|
|
1048
|
+
*/
|
|
1049
|
+
user_id?: string;
|
|
1050
|
+
/**
|
|
1051
|
+
* Structured error information.
|
|
1052
|
+
*
|
|
1053
|
+
* @remarks
|
|
1054
|
+
* Auto-populated when an exception is thrown. Can also be set manually
|
|
1055
|
+
* for handled errors (e.g., payment failures).
|
|
1056
|
+
*
|
|
1057
|
+
* @example
|
|
1058
|
+
* ```typescript
|
|
1059
|
+
* event.error = {
|
|
1060
|
+
* type: 'PaymentError',
|
|
1061
|
+
* code: 'card_declined',
|
|
1062
|
+
* message: 'Your card was declined',
|
|
1063
|
+
* stripe_decline_code: 'insufficient_funds',
|
|
1064
|
+
* };
|
|
1065
|
+
* ```
|
|
1066
|
+
*/
|
|
1067
|
+
error?: {
|
|
1068
|
+
/** Error class/type name (e.g., 'TypeError', 'PaymentError') */
|
|
1069
|
+
type: string;
|
|
1070
|
+
/** Human-readable error message */
|
|
1071
|
+
message: string;
|
|
1072
|
+
/** Stack trace (auto-captured for thrown errors) */
|
|
1073
|
+
stack?: string;
|
|
1074
|
+
/** Error code (e.g., 'ECONNREFUSED', 'card_declined') */
|
|
1075
|
+
code?: string;
|
|
1076
|
+
/** Additional error context */
|
|
1077
|
+
[key: string]: unknown;
|
|
1078
|
+
};
|
|
1079
|
+
/**
|
|
1080
|
+
* Dynamic business context.
|
|
1081
|
+
*
|
|
1082
|
+
* @remarks
|
|
1083
|
+
* Add any fields your application needs. Common patterns:
|
|
1084
|
+
*
|
|
1085
|
+
* - `user` - User context (id, plan, ltv, etc.)
|
|
1086
|
+
* - `cart` - Shopping cart (id, items, total, coupon)
|
|
1087
|
+
* - `payment` - Payment details (provider, method, latency)
|
|
1088
|
+
* - `order` - Order details (id, status, items)
|
|
1089
|
+
* - `feature_flags` - Feature flag states
|
|
1090
|
+
* - `experiment` - A/B test assignments
|
|
1091
|
+
* - `llm` - LLM usage (model, tokens, latency)
|
|
1092
|
+
*/
|
|
1093
|
+
[key: string]: unknown;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
export { FullEvent, type FullEventConfig, type HttpRequestProperties, type SamplingConfig, type WideEvent, WideEventBuilder, type WideEventVariables, type WideLoggerConfig, expressWideLogger, wideLogger };
|