evlog 1.5.0 → 1.7.0

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 (102) hide show
  1. package/README.md +112 -0
  2. package/dist/_utils-DZA9nou3.mjs +23 -0
  3. package/dist/_utils-DZA9nou3.mjs.map +1 -0
  4. package/dist/adapters/axiom.d.mts +16 -15
  5. package/dist/adapters/axiom.d.mts.map +1 -0
  6. package/dist/adapters/axiom.mjs +96 -57
  7. package/dist/adapters/axiom.mjs.map +1 -0
  8. package/dist/adapters/better-stack.d.mts +62 -0
  9. package/dist/adapters/better-stack.d.mts.map +1 -0
  10. package/dist/adapters/better-stack.mjs +109 -0
  11. package/dist/adapters/better-stack.mjs.map +1 -0
  12. package/dist/adapters/otlp.d.mts +31 -30
  13. package/dist/adapters/otlp.d.mts.map +1 -0
  14. package/dist/adapters/otlp.mjs +198 -184
  15. package/dist/adapters/otlp.mjs.map +1 -0
  16. package/dist/adapters/posthog.d.mts +20 -19
  17. package/dist/adapters/posthog.d.mts.map +1 -0
  18. package/dist/adapters/posthog.mjs +110 -69
  19. package/dist/adapters/posthog.mjs.map +1 -0
  20. package/dist/adapters/sentry.d.mts +79 -0
  21. package/dist/adapters/sentry.d.mts.map +1 -0
  22. package/dist/adapters/sentry.mjs +233 -0
  23. package/dist/adapters/sentry.mjs.map +1 -0
  24. package/dist/enrichers.d.mts +74 -0
  25. package/dist/enrichers.d.mts.map +1 -0
  26. package/dist/enrichers.mjs +172 -0
  27. package/dist/enrichers.mjs.map +1 -0
  28. package/dist/error.d.mts +24 -22
  29. package/dist/error.d.mts.map +1 -0
  30. package/dist/error.mjs +107 -76
  31. package/dist/error.mjs.map +1 -0
  32. package/dist/index.d.mts +6 -5
  33. package/dist/index.mjs +6 -6
  34. package/dist/logger.d.mts +5 -3
  35. package/dist/logger.d.mts.map +1 -0
  36. package/dist/logger.mjs +204 -173
  37. package/dist/logger.mjs.map +1 -0
  38. package/dist/nitro/errorHandler.d.mts +4 -2
  39. package/dist/nitro/errorHandler.d.mts.map +1 -0
  40. package/dist/nitro/errorHandler.mjs +49 -38
  41. package/dist/nitro/errorHandler.mjs.map +1 -0
  42. package/dist/nitro/plugin.d.mts +4 -2
  43. package/dist/nitro/plugin.d.mts.map +1 -0
  44. package/dist/nitro/plugin.mjs +155 -137
  45. package/dist/nitro/plugin.mjs.map +1 -0
  46. package/dist/nuxt/module.d.mts +149 -122
  47. package/dist/nuxt/module.d.mts.map +1 -0
  48. package/dist/nuxt/module.mjs +66 -65
  49. package/dist/nuxt/module.mjs.map +1 -0
  50. package/dist/pipeline.d.mts +46 -0
  51. package/dist/pipeline.d.mts.map +1 -0
  52. package/dist/pipeline.mjs +122 -0
  53. package/dist/pipeline.mjs.map +1 -0
  54. package/dist/runtime/client/log.d.mts +7 -5
  55. package/dist/runtime/client/log.d.mts.map +1 -0
  56. package/dist/runtime/client/log.mjs +57 -62
  57. package/dist/runtime/client/log.mjs.map +1 -0
  58. package/dist/runtime/client/plugin.d.mts +3 -1
  59. package/dist/runtime/client/plugin.d.mts.map +1 -0
  60. package/dist/runtime/client/plugin.mjs +13 -12
  61. package/dist/runtime/client/plugin.mjs.map +1 -0
  62. package/dist/runtime/server/routes/_evlog/ingest.post.d.mts +4 -2
  63. package/dist/runtime/server/routes/_evlog/ingest.post.d.mts.map +1 -0
  64. package/dist/runtime/server/routes/_evlog/ingest.post.mjs +113 -77
  65. package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -0
  66. package/dist/runtime/server/useLogger.d.mts +14 -3
  67. package/dist/runtime/server/useLogger.d.mts.map +1 -0
  68. package/dist/runtime/server/useLogger.mjs +39 -10
  69. package/dist/runtime/server/useLogger.mjs.map +1 -0
  70. package/dist/runtime/utils/parseError.d.mts +5 -3
  71. package/dist/runtime/utils/parseError.d.mts.map +1 -0
  72. package/dist/runtime/utils/parseError.mjs +25 -26
  73. package/dist/runtime/utils/parseError.mjs.map +1 -0
  74. package/dist/types.d.mts +348 -246
  75. package/dist/types.d.mts.map +1 -0
  76. package/dist/types.mjs +1 -1
  77. package/dist/utils.d.mts +19 -14
  78. package/dist/utils.d.mts.map +1 -0
  79. package/dist/utils.mjs +59 -50
  80. package/dist/utils.mjs.map +1 -0
  81. package/dist/workers.d.mts +10 -9
  82. package/dist/workers.d.mts.map +1 -0
  83. package/dist/workers.mjs +68 -40
  84. package/dist/workers.mjs.map +1 -0
  85. package/package.json +37 -9
  86. package/dist/adapters/axiom.d.ts +0 -62
  87. package/dist/adapters/otlp.d.ts +0 -83
  88. package/dist/adapters/posthog.d.ts +0 -72
  89. package/dist/error.d.ts +0 -63
  90. package/dist/index.d.ts +0 -5
  91. package/dist/logger.d.ts +0 -40
  92. package/dist/nitro/errorHandler.d.ts +0 -13
  93. package/dist/nitro/plugin.d.ts +0 -5
  94. package/dist/nuxt/module.d.ts +0 -125
  95. package/dist/runtime/client/log.d.ts +0 -10
  96. package/dist/runtime/client/plugin.d.ts +0 -3
  97. package/dist/runtime/server/routes/_evlog/ingest.post.d.ts +0 -5
  98. package/dist/runtime/server/useLogger.d.ts +0 -28
  99. package/dist/runtime/utils/parseError.d.ts +0 -5
  100. package/dist/types.d.ts +0 -364
  101. package/dist/utils.d.ts +0 -29
  102. package/dist/workers.d.ts +0 -45
package/dist/types.d.ts DELETED
@@ -1,364 +0,0 @@
1
- declare module 'nitropack/types' {
2
- interface NitroRuntimeHooks {
3
- /**
4
- * Tail sampling hook - called before emitting a log.
5
- * Set `ctx.shouldKeep = true` to force-keep the log regardless of head sampling.
6
- *
7
- * @example
8
- * ```ts
9
- * nitroApp.hooks.hook('evlog:emit:keep', (ctx) => {
10
- * if (ctx.context.user?.premium) {
11
- * ctx.shouldKeep = true
12
- * }
13
- * })
14
- * ```
15
- */
16
- 'evlog:emit:keep': (ctx: TailSamplingContext) => void | Promise<void>;
17
- /**
18
- * Drain hook - called after emitting a log (fire-and-forget).
19
- * Use this to send logs to external services like Axiom, Loki, or custom endpoints.
20
- * Errors are logged but never block the request.
21
- *
22
- * @example
23
- * ```ts
24
- * nitroApp.hooks.hook('evlog:drain', async (ctx) => {
25
- * await fetch('https://api.axiom.co/v1/datasets/logs/ingest', {
26
- * method: 'POST',
27
- * headers: { Authorization: `Bearer ${process.env.AXIOM_TOKEN}` },
28
- * body: JSON.stringify([ctx.event])
29
- * })
30
- * })
31
- * ```
32
- */
33
- 'evlog:drain': (ctx: DrainContext) => void | Promise<void>;
34
- }
35
- }
36
- /**
37
- * Transport configuration for sending client logs to the server
38
- */
39
- interface TransportConfig {
40
- /**
41
- * Enable sending logs to the server API
42
- * @default false
43
- */
44
- enabled?: boolean;
45
- /**
46
- * API endpoint for log ingestion
47
- * @default '/api/_evlog/ingest'
48
- */
49
- endpoint?: string;
50
- }
51
- /**
52
- * Payload sent from client to server for log ingestion
53
- */
54
- interface IngestPayload {
55
- timestamp: string;
56
- level: 'info' | 'error' | 'warn' | 'debug';
57
- [key: string]: unknown;
58
- }
59
- /**
60
- * Sampling rates per log level (0-100 percentage)
61
- */
62
- interface SamplingRates {
63
- /** Percentage of info logs to keep (0-100). Default: 100 */
64
- info?: number;
65
- /** Percentage of warn logs to keep (0-100). Default: 100 */
66
- warn?: number;
67
- /** Percentage of debug logs to keep (0-100). Default: 100 */
68
- debug?: number;
69
- /** Percentage of error logs to keep (0-100). Default: 100 */
70
- error?: number;
71
- }
72
- /**
73
- * Tail sampling condition for forcing log retention based on request outcome.
74
- * All conditions use >= comparison (e.g., status: 400 means status >= 400).
75
- */
76
- interface TailSamplingCondition {
77
- /** Keep if HTTP status >= this value (e.g., 400 for all errors) */
78
- status?: number;
79
- /** Keep if request duration >= this value in milliseconds */
80
- duration?: number;
81
- /** Keep if path matches this glob pattern (e.g., '/api/critical/**') */
82
- path?: string;
83
- }
84
- /**
85
- * Context passed to tail sampling evaluation and hooks.
86
- * Contains request outcome information for sampling decisions.
87
- */
88
- interface TailSamplingContext {
89
- /** HTTP response status code */
90
- status?: number;
91
- /** Request duration in milliseconds (raw number) */
92
- duration?: number;
93
- /** Request path */
94
- path?: string;
95
- /** HTTP method */
96
- method?: string;
97
- /** Full accumulated context from the request logger */
98
- context: Record<string, unknown>;
99
- /**
100
- * Set to true in evlog:emit:keep hook to force keep this log.
101
- * Multiple hooks can set this - if any sets it to true, the log is kept.
102
- */
103
- shouldKeep?: boolean;
104
- }
105
- /**
106
- * Context passed to the evlog:drain hook.
107
- * Contains the complete wide event and request metadata for external transport.
108
- */
109
- interface DrainContext {
110
- /** The complete wide event to drain */
111
- event: WideEvent;
112
- /** Request metadata (if available) */
113
- request?: {
114
- method?: string;
115
- path?: string;
116
- requestId?: string;
117
- };
118
- /** HTTP headers from the original request (useful for correlation with external services) */
119
- headers?: Record<string, string>;
120
- }
121
- /**
122
- * Sampling configuration for filtering logs
123
- */
124
- interface SamplingConfig {
125
- /**
126
- * Sampling rates per log level (head sampling).
127
- * Values are percentages from 0 to 100.
128
- * Default: 100 for all levels (log everything).
129
- * Error defaults to 100 even if not specified.
130
- *
131
- * @example
132
- * ```ts
133
- * sampling: {
134
- * rates: {
135
- * info: 10, // Keep 10% of info logs
136
- * warn: 50, // Keep 50% of warning logs
137
- * debug: 5, // Keep 5% of debug logs
138
- * error: 100, // Always keep errors (default)
139
- * }
140
- * }
141
- * ```
142
- */
143
- rates?: SamplingRates;
144
- /**
145
- * Tail sampling conditions for forcing log retention (OR logic).
146
- * If ANY condition matches, the log is kept regardless of head sampling.
147
- * Use the `evlog:emit:keep` Nitro hook for custom conditions.
148
- *
149
- * @example
150
- * ```ts
151
- * sampling: {
152
- * rates: { info: 10 }, // Head sampling: keep 10% of info logs
153
- * keep: [
154
- * { status: 400 }, // Always keep if status >= 400
155
- * { duration: 1000 }, // Always keep if duration >= 1000ms
156
- * { path: '/api/critical/**' }, // Always keep critical paths
157
- * ]
158
- * }
159
- * ```
160
- */
161
- keep?: TailSamplingCondition[];
162
- }
163
- /**
164
- * Route-based service configuration
165
- */
166
- interface RouteConfig {
167
- /** Service name to use for routes matching this pattern */
168
- service: string;
169
- }
170
- /**
171
- * Environment context automatically included in every log event
172
- */
173
- interface EnvironmentContext {
174
- /** Service name (auto-detected from package.json or configurable) */
175
- service: string;
176
- /** Environment: 'development', 'production', 'test', etc. */
177
- environment: 'development' | 'production' | 'test' | string;
178
- /** Application version (auto-detected from package.json) */
179
- version?: string;
180
- /** Git commit hash (auto-detected from CI/CD env vars) */
181
- commitHash?: string;
182
- /** Deployment region (auto-detected from cloud provider env vars) */
183
- region?: string;
184
- }
185
- /**
186
- * Logger configuration options
187
- */
188
- interface LoggerConfig {
189
- /** Environment context overrides */
190
- env?: Partial<EnvironmentContext>;
191
- /** Enable pretty printing (auto-detected: true in dev, false in prod) */
192
- pretty?: boolean;
193
- /** Sampling configuration for filtering logs */
194
- sampling?: SamplingConfig;
195
- /**
196
- * When pretty is disabled, emit JSON strings (default) or raw objects.
197
- * Set to false for environments like Cloudflare Workers that expect objects.
198
- * @default true
199
- */
200
- stringify?: boolean;
201
- }
202
- /**
203
- * Base structure for all wide events
204
- */
205
- interface BaseWideEvent {
206
- timestamp: string;
207
- level: 'info' | 'error' | 'warn' | 'debug';
208
- service: string;
209
- environment: string;
210
- version?: string;
211
- commitHash?: string;
212
- region?: string;
213
- }
214
- /**
215
- * Wide event with arbitrary additional fields
216
- */
217
- type WideEvent = BaseWideEvent & Record<string, unknown>;
218
- /**
219
- * Request-scoped logger for building wide events
220
- *
221
- * @example
222
- * ```ts
223
- * const logger = useLogger(event)
224
- * logger.set({ user: { id: '123' } })
225
- * logger.set({ cart: { items: 3 } })
226
- * // emit() is called automatically by the plugin
227
- * ```
228
- */
229
- interface RequestLogger {
230
- /**
231
- * Add context to the wide event (deep merge via defu)
232
- */
233
- set: <T extends Record<string, unknown>>(context: T) => void;
234
- /**
235
- * Log an error and capture its details
236
- */
237
- error: (error: Error | string, context?: Record<string, unknown>) => void;
238
- /**
239
- * Emit the final wide event with all accumulated context.
240
- * Returns the emitted WideEvent, or null if the log was sampled out.
241
- */
242
- emit: (overrides?: Record<string, unknown>) => WideEvent | null;
243
- /**
244
- * Get the current accumulated context
245
- */
246
- getContext: () => Record<string, unknown>;
247
- }
248
- /**
249
- * Log level type
250
- */
251
- type LogLevel = 'info' | 'error' | 'warn' | 'debug';
252
- /**
253
- * Simple logging API - as easy as console.log
254
- *
255
- * @example
256
- * ```ts
257
- * log.info('auth', 'User logged in')
258
- * log.error({ action: 'payment', error: 'failed' })
259
- * ```
260
- */
261
- interface Log {
262
- /**
263
- * Log an info message or wide event
264
- * @example log.info('auth', 'User logged in')
265
- * @example log.info({ action: 'login', userId: '123' })
266
- */
267
- info(tag: string, message: string): void;
268
- info(event: Record<string, unknown>): void;
269
- /**
270
- * Log an error message or wide event
271
- * @example log.error('payment', 'Payment failed')
272
- * @example log.error({ action: 'payment', error: 'declined' })
273
- */
274
- error(tag: string, message: string): void;
275
- error(event: Record<string, unknown>): void;
276
- /**
277
- * Log a warning message or wide event
278
- * @example log.warn('api', 'Rate limit approaching')
279
- * @example log.warn({ action: 'api', remaining: 10 })
280
- */
281
- warn(tag: string, message: string): void;
282
- warn(event: Record<string, unknown>): void;
283
- /**
284
- * Log a debug message or wide event
285
- * @example log.debug('cache', 'Cache miss')
286
- * @example log.debug({ action: 'cache', key: 'user_123' })
287
- */
288
- debug(tag: string, message: string): void;
289
- debug(event: Record<string, unknown>): void;
290
- }
291
- /**
292
- * Error options for creating structured errors
293
- */
294
- interface ErrorOptions {
295
- /** What actually happened */
296
- message: string;
297
- /** HTTP status code (default: 500) */
298
- status?: number;
299
- /** Why this error occurred */
300
- why?: string;
301
- /** How to fix this issue */
302
- fix?: string;
303
- /** Link to documentation or more information */
304
- link?: string;
305
- /** The original error that caused this */
306
- cause?: Error;
307
- }
308
- /**
309
- * Options for creating a request logger
310
- */
311
- interface RequestLoggerOptions {
312
- method?: string;
313
- path?: string;
314
- requestId?: string;
315
- }
316
- /**
317
- * H3 event context with evlog logger attached
318
- */
319
- interface H3EventContext {
320
- log?: RequestLogger;
321
- requestId?: string;
322
- status?: number;
323
- /** Internal: start time for duration calculation in tail sampling */
324
- _evlogStartTime?: number;
325
- /** Internal: flag to prevent double emission on errors */
326
- _evlogEmitted?: boolean;
327
- [key: string]: unknown;
328
- }
329
- /**
330
- * Server event type for Nitro/h3 handlers
331
- */
332
- interface ServerEvent {
333
- method: string;
334
- path: string;
335
- context: H3EventContext & {
336
- /** Cloudflare Workers context (available when deployed to CF Workers) */
337
- cloudflare?: {
338
- context: {
339
- waitUntil: (promise: Promise<unknown>) => void;
340
- };
341
- };
342
- /** Vercel Edge context (available when deployed to Vercel Edge) */
343
- waitUntil?: (promise: Promise<unknown>) => void;
344
- };
345
- node?: {
346
- res?: {
347
- statusCode?: number;
348
- };
349
- };
350
- response?: Response;
351
- }
352
- /**
353
- * Parsed evlog error with all fields at the top level
354
- */
355
- interface ParsedError {
356
- message: string;
357
- status: number;
358
- why?: string;
359
- fix?: string;
360
- link?: string;
361
- raw: unknown;
362
- }
363
-
364
- export type { BaseWideEvent, DrainContext, EnvironmentContext, ErrorOptions, H3EventContext, IngestPayload, Log, LogLevel, LoggerConfig, ParsedError, RequestLogger, RequestLoggerOptions, RouteConfig, SamplingConfig, SamplingRates, ServerEvent, TailSamplingCondition, TailSamplingContext, TransportConfig, WideEvent };
package/dist/utils.d.ts DELETED
@@ -1,29 +0,0 @@
1
- import { EnvironmentContext, LogLevel } from './types.js';
2
-
3
- declare function formatDuration(ms: number): string;
4
- declare function isServer(): boolean;
5
- declare function isClient(): boolean;
6
- declare function isDev(): boolean;
7
- declare function detectEnvironment(): Partial<EnvironmentContext>;
8
- declare function getConsoleMethod(level: LogLevel): LogLevel;
9
- declare const colors: {
10
- readonly reset: "\u001B[0m";
11
- readonly bold: "\u001B[1m";
12
- readonly dim: "\u001B[2m";
13
- readonly red: "\u001B[31m";
14
- readonly green: "\u001B[32m";
15
- readonly yellow: "\u001B[33m";
16
- readonly blue: "\u001B[34m";
17
- readonly magenta: "\u001B[35m";
18
- readonly cyan: "\u001B[36m";
19
- readonly white: "\u001B[37m";
20
- readonly gray: "\u001B[90m";
21
- };
22
- declare function getLevelColor(level: string): string;
23
- /**
24
- * Match a path against a glob pattern.
25
- * Supports * (any chars except /) and ** (any chars including /).
26
- */
27
- declare function matchesPattern(path: string, pattern: string): boolean;
28
-
29
- export { colors, detectEnvironment, formatDuration, getConsoleMethod, getLevelColor, isClient, isDev, isServer, matchesPattern };
package/dist/workers.d.ts DELETED
@@ -1,45 +0,0 @@
1
- import { RequestLogger, LoggerConfig } from './types.js';
2
-
3
- /**
4
- * Options for createWorkersLogger
5
- */
6
- interface WorkersLoggerOptions {
7
- /** Override the request ID (default: cf-ray header) */
8
- requestId?: string;
9
- /** Headers to include in logs (default: none) */
10
- headers?: string[];
11
- }
12
- /**
13
- * Initialize evlog for Cloudflare Workers.
14
- * Call once at module scope.
15
- *
16
- * @example
17
- * ```ts
18
- * initWorkersLogger({
19
- * env: { service: 'my-api' },
20
- * })
21
- * ```
22
- */
23
- declare function initWorkersLogger(options?: LoggerConfig): void;
24
- /**
25
- * Create a request-scoped logger for Cloudflare Workers.
26
- * Auto-extracts cf-ray, request.cf context, method, and path.
27
- *
28
- * @example
29
- * ```ts
30
- * export default {
31
- * async fetch(request: Request) {
32
- * const log = createWorkersLogger(request)
33
- *
34
- * log.set({ user: { id: '123' } })
35
- * log.emit({ status: 200 })
36
- *
37
- * return new Response('ok')
38
- * }
39
- * }
40
- * ```
41
- */
42
- declare function createWorkersLogger(request: Request, options?: WorkersLoggerOptions): RequestLogger;
43
-
44
- export { createWorkersLogger, initWorkersLogger };
45
- export type { WorkersLoggerOptions };