evlog 1.8.0 → 1.10.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.
- package/README.md +258 -64
- package/dist/{_severity-CXfyvxQi.mjs → _severity-D_IU9-90.mjs} +1 -1
- package/dist/{_severity-CXfyvxQi.mjs.map → _severity-D_IU9-90.mjs.map} +1 -1
- package/dist/adapters/otlp.mjs +1 -1
- package/dist/adapters/sentry.mjs +1 -1
- package/dist/next/client.d.mts +55 -0
- package/dist/next/client.d.mts.map +1 -0
- package/dist/next/client.mjs +44 -0
- package/dist/next/client.mjs.map +1 -0
- package/dist/next/index.d.mts +169 -0
- package/dist/next/index.d.mts.map +1 -0
- package/dist/next/index.mjs +280 -0
- package/dist/next/index.mjs.map +1 -0
- package/dist/nitro/errorHandler.mjs +1 -1
- package/dist/nitro/module.d.mts +1 -1
- package/dist/nitro/plugin.mjs +2 -1
- package/dist/nitro/plugin.mjs.map +1 -1
- package/dist/nitro/v3/errorHandler.mjs +1 -1
- package/dist/nitro/v3/index.d.mts +1 -1
- package/dist/nitro/v3/module.d.mts +1 -1
- package/dist/nitro/v3/plugin.mjs +2 -1
- package/dist/nitro/v3/plugin.mjs.map +1 -1
- package/dist/{nitro-D81NBVPi.d.mts → nitro-CrFBjY1Y.d.mts} +1 -1
- package/dist/nitro-CrFBjY1Y.d.mts.map +1 -0
- package/dist/nitro-Da8tEfJ3.mjs +39 -0
- package/dist/nitro-Da8tEfJ3.mjs.map +1 -0
- package/dist/nuxt/module.d.mts +6 -0
- package/dist/nuxt/module.d.mts.map +1 -1
- package/dist/nuxt/module.mjs +8 -2
- package/dist/nuxt/module.mjs.map +1 -1
- package/dist/{nitro-D57TWGyN.mjs → routes-BNbrnm14.mjs} +3 -37
- package/dist/routes-BNbrnm14.mjs.map +1 -0
- package/package.json +26 -4
- package/dist/nitro-D57TWGyN.mjs.map +0 -1
- package/dist/nitro-D81NBVPi.d.mts.map +0 -1
package/README.md
CHANGED
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
[](https://npm.chart.dev/evlog)
|
|
5
5
|
[](https://github.com/HugoRCD/evlog/actions/workflows/ci.yml)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
|
-
[](https://nuxt.com/)
|
|
8
7
|
[](https://evlog.dev)
|
|
9
8
|
[](https://github.com/HugoRCD/evlog/blob/main/LICENSE)
|
|
10
9
|
|
|
11
10
|
**Your logs are lying to you.**
|
|
12
11
|
|
|
13
|
-
A single request generates 10+ log lines. When production breaks at 3am, you're grep-ing through noise, praying you'll find signal. Your errors say "Something went wrong"
|
|
12
|
+
A single request generates 10+ log lines. When production breaks at 3am, you're grep-ing through noise, praying you'll find signal. Your errors say "Something went wrong" -- thanks, very helpful.
|
|
14
13
|
|
|
15
14
|
**evlog fixes this.** One log per request. All context included. Errors that explain themselves.
|
|
16
15
|
|
|
@@ -21,13 +20,13 @@ A single request generates 10+ log lines. When production breaks at 3am, you're
|
|
|
21
20
|
```typescript
|
|
22
21
|
// server/api/checkout.post.ts
|
|
23
22
|
|
|
24
|
-
//
|
|
23
|
+
// Scattered logs - impossible to debug
|
|
25
24
|
console.log('Request received')
|
|
26
25
|
console.log('User:', user.id)
|
|
27
26
|
console.log('Cart loaded')
|
|
28
27
|
console.log('Payment failed') // Good luck finding this at 3am
|
|
29
28
|
|
|
30
|
-
throw new Error('Something went wrong')
|
|
29
|
+
throw new Error('Something went wrong')
|
|
31
30
|
```
|
|
32
31
|
|
|
33
32
|
### The Solution
|
|
@@ -36,7 +35,7 @@ throw new Error('Something went wrong') // 🤷♂️
|
|
|
36
35
|
// server/api/checkout.post.ts
|
|
37
36
|
import { useLogger } from 'evlog'
|
|
38
37
|
|
|
39
|
-
//
|
|
38
|
+
// One comprehensive event per request
|
|
40
39
|
export default defineEventHandler(async (event) => {
|
|
41
40
|
const log = useLogger(event) // Auto-injected by evlog
|
|
42
41
|
|
|
@@ -176,18 +175,43 @@ The wide event emitted at the end contains **everything**:
|
|
|
176
175
|
|
|
177
176
|
Works with **any framework powered by Nitro**: Nuxt, Analog, Vinxi, SolidStart, TanStack Start, and more.
|
|
178
177
|
|
|
178
|
+
### Nitro v3
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// nitro.config.ts
|
|
182
|
+
import { defineConfig } from 'nitro'
|
|
183
|
+
import evlog from 'evlog/nitro/v3'
|
|
184
|
+
|
|
185
|
+
export default defineConfig({
|
|
186
|
+
modules: [
|
|
187
|
+
evlog({ env: { service: 'my-api' } })
|
|
188
|
+
],
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Nitro v2
|
|
193
|
+
|
|
179
194
|
```typescript
|
|
180
195
|
// nitro.config.ts
|
|
196
|
+
import { defineNitroConfig } from 'nitropack/config'
|
|
197
|
+
import evlog from 'evlog/nitro'
|
|
198
|
+
|
|
181
199
|
export default defineNitroConfig({
|
|
182
|
-
|
|
200
|
+
modules: [
|
|
201
|
+
evlog({ env: { service: 'my-api' } })
|
|
202
|
+
],
|
|
183
203
|
})
|
|
184
204
|
```
|
|
185
205
|
|
|
186
|
-
|
|
206
|
+
Then use `useLogger` in any route. Import from `evlog/nitro/v3` (v3) or `evlog/nitro` (v2):
|
|
187
207
|
|
|
188
208
|
```typescript
|
|
189
209
|
// routes/api/documents/[id]/export.post.ts
|
|
190
|
-
import { useLogger
|
|
210
|
+
// Nitro v3: import { defineHandler } from 'nitro/h3' + import { useLogger } from 'evlog/nitro/v3'
|
|
211
|
+
// Nitro v2: import { defineEventHandler } from 'h3' + import { useLogger } from 'evlog/nitro'
|
|
212
|
+
import { defineEventHandler } from 'h3'
|
|
213
|
+
import { useLogger } from 'evlog/nitro'
|
|
214
|
+
import { createError } from 'evlog'
|
|
191
215
|
|
|
192
216
|
export default defineEventHandler(async (event) => {
|
|
193
217
|
const log = useLogger(event)
|
|
@@ -248,47 +272,6 @@ Output when the export completes:
|
|
|
248
272
|
}
|
|
249
273
|
```
|
|
250
274
|
|
|
251
|
-
## Structured Errors
|
|
252
|
-
|
|
253
|
-
Errors should tell you **what** happened, **why**, and **how to fix it**.
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
// server/api/repos/sync.post.ts
|
|
257
|
-
import { useLogger, createError } from 'evlog'
|
|
258
|
-
|
|
259
|
-
export default defineEventHandler(async (event) => {
|
|
260
|
-
const log = useLogger(event)
|
|
261
|
-
|
|
262
|
-
log.set({ repo: { owner: 'acme', name: 'my-project' } })
|
|
263
|
-
|
|
264
|
-
try {
|
|
265
|
-
const result = await syncWithGitHub()
|
|
266
|
-
log.set({ sync: { commits: result.commits, files: result.files } })
|
|
267
|
-
return result
|
|
268
|
-
} catch (error) {
|
|
269
|
-
log.error(error, { step: 'github-sync' })
|
|
270
|
-
|
|
271
|
-
throw createError({
|
|
272
|
-
message: 'Failed to sync repository',
|
|
273
|
-
status: 503,
|
|
274
|
-
why: 'GitHub API rate limit exceeded',
|
|
275
|
-
fix: 'Wait 1 hour or use a different token',
|
|
276
|
-
link: 'https://docs.github.com/en/rest/rate-limit',
|
|
277
|
-
cause: error,
|
|
278
|
-
})
|
|
279
|
-
}
|
|
280
|
-
})
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
Console output (development):
|
|
284
|
-
|
|
285
|
-
```
|
|
286
|
-
Error: Failed to sync repository
|
|
287
|
-
Why: GitHub API rate limit exceeded
|
|
288
|
-
Fix: Wait 1 hour or use a different token
|
|
289
|
-
More info: https://docs.github.com/en/rest/rate-limit
|
|
290
|
-
```
|
|
291
|
-
|
|
292
275
|
## Standalone TypeScript
|
|
293
276
|
|
|
294
277
|
For scripts, workers, or any TypeScript project:
|
|
@@ -390,6 +373,130 @@ Notes:
|
|
|
390
373
|
- `request.cf` is included (colo, country, asn) unless disabled
|
|
391
374
|
- Use `headerAllowlist` to avoid logging sensitive headers
|
|
392
375
|
|
|
376
|
+
## Hono
|
|
377
|
+
|
|
378
|
+
Use the standalone API to create one wide event per request from a Hono middleware.
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// src/index.ts
|
|
382
|
+
import { serve } from '@hono/node-server'
|
|
383
|
+
import { Hono } from 'hono'
|
|
384
|
+
import { createRequestLogger, initLogger } from 'evlog'
|
|
385
|
+
|
|
386
|
+
initLogger({
|
|
387
|
+
env: { service: 'hono-api' },
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
const app = new Hono()
|
|
391
|
+
|
|
392
|
+
app.use('*', async (c, next) => {
|
|
393
|
+
const startedAt = Date.now()
|
|
394
|
+
const log = createRequestLogger({ method: c.req.method, path: c.req.path })
|
|
395
|
+
|
|
396
|
+
try {
|
|
397
|
+
await next()
|
|
398
|
+
} catch (error) {
|
|
399
|
+
log.error(error as Error)
|
|
400
|
+
throw error
|
|
401
|
+
} finally {
|
|
402
|
+
log.emit({
|
|
403
|
+
status: c.res.status,
|
|
404
|
+
duration: Date.now() - startedAt,
|
|
405
|
+
})
|
|
406
|
+
}
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
app.get('/health', (c) => c.json({ ok: true }))
|
|
410
|
+
|
|
411
|
+
serve({ fetch: app.fetch, port: 3000 })
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
See the full [hono example](https://github.com/HugoRCD/evlog/tree/main/examples/hono) for a complete working project.
|
|
415
|
+
|
|
416
|
+
## Browser
|
|
417
|
+
|
|
418
|
+
Use the `log` API on the client side for structured browser logging:
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
import { log } from 'evlog/browser'
|
|
422
|
+
|
|
423
|
+
log.info('checkout', 'User initiated checkout')
|
|
424
|
+
log.error({ action: 'payment', error: 'validation_failed' })
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
In Nuxt, `log` is auto-imported -- no import needed in Vue components:
|
|
428
|
+
|
|
429
|
+
```vue
|
|
430
|
+
<script setup>
|
|
431
|
+
log.info('checkout', 'User initiated checkout')
|
|
432
|
+
</script>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Client logs output to the browser console with colored tags in development.
|
|
436
|
+
|
|
437
|
+
### Client Transport
|
|
438
|
+
|
|
439
|
+
To send client logs to the server for centralized logging, enable the transport:
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
// nuxt.config.ts
|
|
443
|
+
export default defineNuxtConfig({
|
|
444
|
+
modules: ['evlog/nuxt'],
|
|
445
|
+
evlog: {
|
|
446
|
+
transport: {
|
|
447
|
+
enabled: true, // Send client logs to server
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
})
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
When enabled:
|
|
454
|
+
1. Client logs are sent to `/api/_evlog/ingest` via POST
|
|
455
|
+
2. Server enriches with environment context (service, version, etc.)
|
|
456
|
+
3. `evlog:drain` hook is called with `source: 'client'`
|
|
457
|
+
4. External services receive the log
|
|
458
|
+
|
|
459
|
+
## Structured Errors
|
|
460
|
+
|
|
461
|
+
Errors should tell you **what** happened, **why**, and **how to fix it**.
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
// server/api/repos/sync.post.ts
|
|
465
|
+
import { useLogger, createError } from 'evlog'
|
|
466
|
+
|
|
467
|
+
export default defineEventHandler(async (event) => {
|
|
468
|
+
const log = useLogger(event)
|
|
469
|
+
|
|
470
|
+
log.set({ repo: { owner: 'acme', name: 'my-project' } })
|
|
471
|
+
|
|
472
|
+
try {
|
|
473
|
+
const result = await syncWithGitHub()
|
|
474
|
+
log.set({ sync: { commits: result.commits, files: result.files } })
|
|
475
|
+
return result
|
|
476
|
+
} catch (error) {
|
|
477
|
+
log.error(error, { step: 'github-sync' })
|
|
478
|
+
|
|
479
|
+
throw createError({
|
|
480
|
+
message: 'Failed to sync repository',
|
|
481
|
+
status: 503,
|
|
482
|
+
why: 'GitHub API rate limit exceeded',
|
|
483
|
+
fix: 'Wait 1 hour or use a different token',
|
|
484
|
+
link: 'https://docs.github.com/en/rest/rate-limit',
|
|
485
|
+
cause: error,
|
|
486
|
+
})
|
|
487
|
+
}
|
|
488
|
+
})
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Console output (development):
|
|
492
|
+
|
|
493
|
+
```
|
|
494
|
+
Error: Failed to sync repository
|
|
495
|
+
Why: GitHub API rate limit exceeded
|
|
496
|
+
Fix: Wait 1 hour or use a different token
|
|
497
|
+
More info: https://docs.github.com/en/rest/rate-limit
|
|
498
|
+
```
|
|
499
|
+
|
|
393
500
|
## Enrichment Hook
|
|
394
501
|
|
|
395
502
|
Use the `evlog:enrich` hook to add derived context after emit, before drain.
|
|
@@ -428,6 +535,58 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
428
535
|
})
|
|
429
536
|
```
|
|
430
537
|
|
|
538
|
+
Each enricher adds a specific field to the event:
|
|
539
|
+
|
|
540
|
+
| Enricher | Event Field | Shape |
|
|
541
|
+
|----------|-------------|-------|
|
|
542
|
+
| `createUserAgentEnricher()` | `event.userAgent` | `{ raw, browser?: { name, version? }, os?: { name, version? }, device?: { type } }` |
|
|
543
|
+
| `createGeoEnricher()` | `event.geo` | `{ country?, region?, regionCode?, city?, latitude?, longitude? }` |
|
|
544
|
+
| `createRequestSizeEnricher()` | `event.requestSize` | `{ requestBytes?, responseBytes? }` |
|
|
545
|
+
| `createTraceContextEnricher()` | `event.traceContext` + `event.traceId` + `event.spanId` | `{ traceparent?, tracestate?, traceId?, spanId? }` |
|
|
546
|
+
|
|
547
|
+
All enrichers accept an optional `{ overwrite?: boolean }` option. By default (`overwrite: false`), user-provided data on the event takes precedence over enricher-computed values. Set `overwrite: true` to always replace existing fields.
|
|
548
|
+
|
|
549
|
+
> **Cloudflare geo note:** Only `cf-ipcountry` is a real Cloudflare HTTP header. The `cf-region`, `cf-city`, `cf-latitude`, `cf-longitude` headers are NOT standard -- they are properties of `request.cf`. For full geo data on Cloudflare, write a custom enricher that reads `request.cf`, or use a Workers middleware to forward `cf` properties as custom headers.
|
|
550
|
+
|
|
551
|
+
### Custom Enrichers
|
|
552
|
+
|
|
553
|
+
The `evlog:enrich` hook receives an `EnrichContext` with these fields:
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
interface EnrichContext {
|
|
557
|
+
event: WideEvent // The emitted wide event (mutable -- modify it directly)
|
|
558
|
+
request?: { // Request metadata
|
|
559
|
+
method?: string
|
|
560
|
+
path?: string
|
|
561
|
+
requestId?: string
|
|
562
|
+
}
|
|
563
|
+
headers?: Record<string, string> // Safe HTTP headers (sensitive headers filtered)
|
|
564
|
+
response?: { // Response metadata
|
|
565
|
+
status?: number
|
|
566
|
+
headers?: Record<string, string>
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
Example custom enricher:
|
|
572
|
+
|
|
573
|
+
```typescript
|
|
574
|
+
// server/plugins/evlog-enrich.ts
|
|
575
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
576
|
+
nitroApp.hooks.hook('evlog:enrich', (ctx) => {
|
|
577
|
+
// Add deployment metadata
|
|
578
|
+
ctx.event.deploymentId = process.env.DEPLOYMENT_ID
|
|
579
|
+
ctx.event.region = process.env.FLY_REGION
|
|
580
|
+
|
|
581
|
+
// Extract data from headers
|
|
582
|
+
const tenantId = ctx.headers?.['x-tenant-id']
|
|
583
|
+
if (tenantId) {
|
|
584
|
+
ctx.event.tenantId = tenantId
|
|
585
|
+
}
|
|
586
|
+
})
|
|
587
|
+
})
|
|
588
|
+
```
|
|
589
|
+
|
|
431
590
|
## Adapters
|
|
432
591
|
|
|
433
592
|
Send your logs to external observability platforms with built-in adapters.
|
|
@@ -469,6 +628,24 @@ Set environment variables:
|
|
|
469
628
|
NUXT_OTLP_ENDPOINT=http://localhost:4318
|
|
470
629
|
```
|
|
471
630
|
|
|
631
|
+
### PostHog
|
|
632
|
+
|
|
633
|
+
```typescript
|
|
634
|
+
// server/plugins/evlog-drain.ts
|
|
635
|
+
import { createPostHogDrain } from 'evlog/posthog'
|
|
636
|
+
|
|
637
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
638
|
+
nitroApp.hooks.hook('evlog:drain', createPostHogDrain())
|
|
639
|
+
})
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
Set environment variables:
|
|
643
|
+
|
|
644
|
+
```bash
|
|
645
|
+
NUXT_POSTHOG_API_KEY=phc_your-key
|
|
646
|
+
NUXT_POSTHOG_HOST=https://us.i.posthog.com # Optional: for EU or self-hosted
|
|
647
|
+
```
|
|
648
|
+
|
|
472
649
|
### Sentry
|
|
473
650
|
|
|
474
651
|
```typescript
|
|
@@ -486,6 +663,23 @@ Set environment variables:
|
|
|
486
663
|
NUXT_SENTRY_DSN=https://public@o0.ingest.sentry.io/123
|
|
487
664
|
```
|
|
488
665
|
|
|
666
|
+
### Better Stack
|
|
667
|
+
|
|
668
|
+
```typescript
|
|
669
|
+
// server/plugins/evlog-drain.ts
|
|
670
|
+
import { createBetterStackDrain } from 'evlog/better-stack'
|
|
671
|
+
|
|
672
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
673
|
+
nitroApp.hooks.hook('evlog:drain', createBetterStackDrain())
|
|
674
|
+
})
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
Set environment variables:
|
|
678
|
+
|
|
679
|
+
```bash
|
|
680
|
+
NUXT_BETTER_STACK_SOURCE_TOKEN=your-source-token
|
|
681
|
+
```
|
|
682
|
+
|
|
489
683
|
### Multiple Destinations
|
|
490
684
|
|
|
491
685
|
Send logs to multiple services:
|
|
@@ -571,15 +765,15 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
571
765
|
| `retry.initialDelayMs` | `1000` | Base delay for first retry |
|
|
572
766
|
| `retry.maxDelayMs` | `30000` | Upper bound for any retry delay |
|
|
573
767
|
| `maxBufferSize` | `1000` | Max buffered events before dropping oldest |
|
|
574
|
-
| `onDropped` |
|
|
768
|
+
| `onDropped` | -- | Callback when events are dropped |
|
|
575
769
|
|
|
576
770
|
### Returned drain function
|
|
577
771
|
|
|
578
772
|
The function returned by `pipeline(drain)` is hook-compatible and exposes:
|
|
579
773
|
|
|
580
|
-
- **`drain(ctx)`**
|
|
581
|
-
- **`drain.flush()`**
|
|
582
|
-
- **`drain.pending`**
|
|
774
|
+
- **`drain(ctx)`** -- Push a single event into the buffer
|
|
775
|
+
- **`drain.flush()`** -- Force-flush all buffered events (call on server shutdown)
|
|
776
|
+
- **`drain.pending`** -- Number of events currently buffered
|
|
583
777
|
|
|
584
778
|
## API Reference
|
|
585
779
|
|
|
@@ -589,7 +783,7 @@ Initialize the logger. Required for standalone usage, automatic with Nuxt/Nitro
|
|
|
589
783
|
|
|
590
784
|
```typescript
|
|
591
785
|
initLogger({
|
|
592
|
-
enabled: boolean //
|
|
786
|
+
enabled: boolean // Optional. Enable/disable all logging (default: true)
|
|
593
787
|
env: {
|
|
594
788
|
service: string // Service name
|
|
595
789
|
environment: string // 'production' | 'development' | 'test'
|
|
@@ -680,9 +874,9 @@ In development, evlog uses a compact tree format:
|
|
|
680
874
|
|
|
681
875
|
```
|
|
682
876
|
16:45:31.060 INFO [my-app] GET /api/checkout 200 in 234ms
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
877
|
+
|- user: id=123 plan=premium
|
|
878
|
+
|- cart: items=3 total=9999
|
|
879
|
+
+- payment: id=pay_xyz method=card
|
|
686
880
|
```
|
|
687
881
|
|
|
688
882
|
In production (`pretty: false`), logs are emitted as JSON for machine parsing.
|
|
@@ -793,16 +987,16 @@ try {
|
|
|
793
987
|
|
|
794
988
|
## Framework Support
|
|
795
989
|
|
|
796
|
-
evlog works with any framework powered by [Nitro](https://nitro.unjs.io/):
|
|
797
|
-
|
|
798
990
|
| Framework | Integration |
|
|
799
991
|
|-----------|-------------|
|
|
800
992
|
| **Nuxt** | `modules: ['evlog/nuxt']` |
|
|
801
|
-
| **
|
|
802
|
-
| **
|
|
803
|
-
| **
|
|
804
|
-
| **
|
|
805
|
-
| **
|
|
993
|
+
| **Next.js** | `createEvlog()` factory with `import { createEvlog } from 'evlog/next'` ([example](./examples/nextjs)) |
|
|
994
|
+
| **Nitro v3** | `modules: [evlog()]` with `import evlog from 'evlog/nitro/v3'` |
|
|
995
|
+
| **Nitro v2** | `modules: [evlog()]` with `import evlog from 'evlog/nitro'` |
|
|
996
|
+
| **Analog** | Nitro v2 module setup |
|
|
997
|
+
| **Vinxi** | Nitro v2 module setup |
|
|
998
|
+
| **SolidStart** | Nitro v2 module setup ([example](./examples/solidstart)) |
|
|
999
|
+
| **TanStack Start** | Nitro v2 module setup |
|
|
806
1000
|
|
|
807
1001
|
## Agent Skills
|
|
808
1002
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_severity-
|
|
1
|
+
{"version":3,"file":"_severity-D_IU9-90.mjs","names":[],"sources":["../src/adapters/_severity.ts"],"sourcesContent":["import type { LogLevel } from '../types'\n\nexport const OTEL_SEVERITY_NUMBER: Record<LogLevel, number> = {\n debug: 5,\n info: 9,\n warn: 13,\n error: 17,\n}\n\nexport const OTEL_SEVERITY_TEXT: Record<LogLevel, string> = {\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARN',\n error: 'ERROR',\n}\n"],"mappings":";AAEA,MAAa,uBAAiD;CAC5D,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,MAAa,qBAA+C;CAC1D,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR"}
|
package/dist/adapters/otlp.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as defineDrain, r as resolveAdapterConfig, t as httpPost } from "../_http-DVDwNag0.mjs";
|
|
2
|
-
import { n as OTEL_SEVERITY_TEXT, t as OTEL_SEVERITY_NUMBER } from "../_severity-
|
|
2
|
+
import { n as OTEL_SEVERITY_TEXT, t as OTEL_SEVERITY_NUMBER } from "../_severity-D_IU9-90.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/adapters/otlp.ts
|
|
5
5
|
const OTLP_FIELDS = [
|
package/dist/adapters/sentry.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as defineDrain, r as resolveAdapterConfig, t as httpPost } from "../_http-DVDwNag0.mjs";
|
|
2
|
-
import { t as OTEL_SEVERITY_NUMBER } from "../_severity-
|
|
2
|
+
import { t as OTEL_SEVERITY_NUMBER } from "../_severity-D_IU9-90.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/adapters/sentry.ts
|
|
5
5
|
const SENTRY_FIELDS = [
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { TransportConfig } from "../types.mjs";
|
|
2
|
+
import { clearIdentity, log as _clientLog, setIdentity } from "../runtime/client/log.mjs";
|
|
3
|
+
import * as react from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/next/client.d.ts
|
|
6
|
+
interface EvlogProviderProps {
|
|
7
|
+
/**
|
|
8
|
+
* Service name for client-side logs.
|
|
9
|
+
* @default 'client'
|
|
10
|
+
*/
|
|
11
|
+
service?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Enable pretty printing in the browser console.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
pretty?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Transport configuration for sending client logs to the server.
|
|
19
|
+
*/
|
|
20
|
+
transport?: TransportConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Enable or disable client-side logging.
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
enabled?: boolean;
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* React provider that initializes evlog client-side logging.
|
|
30
|
+
* Place this in your root layout to enable client logging throughout your app.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* // app/layout.tsx
|
|
35
|
+
* import { EvlogProvider } from 'evlog/next/client'
|
|
36
|
+
*
|
|
37
|
+
* export default function Layout({ children }) {
|
|
38
|
+
* return (
|
|
39
|
+
* <EvlogProvider service="my-app" transport={{ enabled: true }}>
|
|
40
|
+
* {children}
|
|
41
|
+
* </EvlogProvider>
|
|
42
|
+
* )
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare function EvlogProvider({
|
|
47
|
+
service,
|
|
48
|
+
pretty,
|
|
49
|
+
transport,
|
|
50
|
+
enabled,
|
|
51
|
+
children
|
|
52
|
+
}: EvlogProviderProps): react.ReactNode;
|
|
53
|
+
//#endregion
|
|
54
|
+
export { EvlogProvider, EvlogProviderProps, clearIdentity, _clientLog as log, setIdentity };
|
|
55
|
+
//# sourceMappingURL=client.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.mts","names":[],"sources":["../../src/next/client.ts"],"mappings":";;;;;UAQiB,kBAAA;;;AAAjB;;EAKE,OAAA;EAmByB;;;;EAbzB,MAAA;EAWA;;;EANA,SAAA,GAAY,eAAA;EAQa;;AAsB3B;;EAxBE,OAAA;EAEA,QAAA,EAAU,KAAA,CAAM,SAAA;AAAA;;;;;;;;;;;;;;;;;;;iBAsBF,aAAA,CAAA;EAAgB,OAAA;EAAS,MAAA;EAAQ,SAAA;EAAW,OAAA;EAAS;AAAA,GAAY,kBAAA,GAAkB,KAAA,CAAA,SAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { clearIdentity, initLog, log as _clientLog, setIdentity } from "../runtime/client/log.mjs";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
|
|
6
|
+
//#region src/next/client.ts
|
|
7
|
+
/**
|
|
8
|
+
* React provider that initializes evlog client-side logging.
|
|
9
|
+
* Place this in your root layout to enable client logging throughout your app.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* // app/layout.tsx
|
|
14
|
+
* import { EvlogProvider } from 'evlog/next/client'
|
|
15
|
+
*
|
|
16
|
+
* export default function Layout({ children }) {
|
|
17
|
+
* return (
|
|
18
|
+
* <EvlogProvider service="my-app" transport={{ enabled: true }}>
|
|
19
|
+
* {children}
|
|
20
|
+
* </EvlogProvider>
|
|
21
|
+
* )
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
function EvlogProvider({ service, pretty, transport, enabled, children }) {
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
initLog({
|
|
28
|
+
enabled,
|
|
29
|
+
pretty,
|
|
30
|
+
service,
|
|
31
|
+
transport
|
|
32
|
+
});
|
|
33
|
+
}, [
|
|
34
|
+
enabled,
|
|
35
|
+
pretty,
|
|
36
|
+
service,
|
|
37
|
+
transport
|
|
38
|
+
]);
|
|
39
|
+
return children;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { EvlogProvider, clearIdentity, _clientLog as log, setIdentity };
|
|
44
|
+
//# sourceMappingURL=client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.mjs","names":[],"sources":["../../src/next/client.ts"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\nimport type { TransportConfig } from '../types'\nimport { initLog, log, setIdentity, clearIdentity } from '../runtime/client/log'\n\nexport { log, setIdentity, clearIdentity } from '../runtime/client/log'\n\nexport interface EvlogProviderProps {\n /**\n * Service name for client-side logs.\n * @default 'client'\n */\n service?: string\n\n /**\n * Enable pretty printing in the browser console.\n * @default true\n */\n pretty?: boolean\n\n /**\n * Transport configuration for sending client logs to the server.\n */\n transport?: TransportConfig\n\n /**\n * Enable or disable client-side logging.\n * @default true\n */\n enabled?: boolean\n\n children: React.ReactNode\n}\n\n/**\n * React provider that initializes evlog client-side logging.\n * Place this in your root layout to enable client logging throughout your app.\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { EvlogProvider } from 'evlog/next/client'\n *\n * export default function Layout({ children }) {\n * return (\n * <EvlogProvider service=\"my-app\" transport={{ enabled: true }}>\n * {children}\n * </EvlogProvider>\n * )\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function EvlogProvider({ service, pretty, transport, enabled, children }: EvlogProviderProps) {\n useEffect(() => {\n initLog({\n enabled,\n pretty,\n service,\n transport,\n })\n }, [enabled, pretty, service, transport])\n\n return children\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAsDA,SAAgB,cAAc,EAAE,SAAS,QAAQ,WAAW,SAAS,YAAgC;AACnG,iBAAgB;AACd,UAAQ;GACN;GACA;GACA;GACA;GACD,CAAC;IACD;EAAC;EAAS;EAAQ;EAAS;EAAU,CAAC;AAEzC,QAAO"}
|