Skip to content

chore(repo): version packages - #467

Merged
HugoRCD merged 1 commit into
mainfrom
changeset-release/main
Aug 1, 2026
Merged

chore(repo): version packages#467
HugoRCD merged 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

evlog@2.23.0

Minor Changes

  • #473 f39ab30 Thanks @HugoRCD! - refactor: build each adapter's HTTP request once instead of twice — every HTTP adapter (axiom, better-stack, datadog, otlp, sentry, posthog in events mode) constructed its URL, headers and body in two places: the encode() passed to defineHttpDrain() and again inside its standalone sendBatchTo* helper. The two copies had already drifted, reporting the same failure under different names (axiom API error from the drain, Axiom API error from the helper), and Axiom's and Better Stack's encode() ignored the deprecated token / sourceToken aliases the helper honoured. Both paths now share one encoder per adapter and report failures identically. defineHttpDrain() accepts an optional label for the human-readable name used in error messages, and sendEncodedDrainRequest() is exported from evlog/toolkit so custom adapters can reuse their own encoder the same way

  • #481 d7f482a Thanks @HugoRCD! - feat(clickhouse): add the ClickHouse drain adapter (evlog/clickhouse) — createClickHouseDrain() inserts wide events over ClickHouse's HTTP interface in JSONEachRow format, working with a local instance, a self-managed cluster, and ClickHouse Cloud. The default evlog_events schema keeps typed columns for what you filter and aggregate on (timestamp, level, service, environment, request_id, trace_id, method, path, status, …) plus the complete event as JSON in data, so adding a field to your events never needs a migration; pass transform to target your own schema. Asynchronous inserts are enabled and not awaited by default (async_insert=1&wait_for_async_insert=0), so ClickHouse batches server-side instead of creating one MergeTree part per request and draining never blocks on disk writes. Credentials are sent as X-ClickHouse-User / X-ClickHouse-Key headers rather than query parameters, so they never reach system.query_log. Configured via CLICKHOUSE_ENDPOINT / CLICKHOUSE_USER / CLICKHOUSE_PASSWORD / CLICKHOUSE_DATABASE / CLICKHOUSE_TABLE or overrides, with sendToClickHouse / sendBatchToClickHouse for direct use. The adapter docs carry the matching CREATE TABLE.

  • #465 12852d3 Thanks @HugoRCD! - fix(datadog): lift event.traceId / event.spanId into a root dd block — Datadog's log-to-trace correlation only reads dd.trace_id / dd.span_id at the payload root, so the ids createDefaultEnrichers() already sets arrived nested under evlog and never correlated. The nested copy stays, so @evlog.* facets keep working, and resolveDatadogTraceContext is exported for custom drains

  • #468 ecc3ea6 Thanks @HugoRCD! - fix(core): key request scope, logger config and error identity to a versioned globalThis registry — evlog declares 18 optional peers, and pnpm/bun (isolated linker) hash resolved peers into store paths, so two workspaces that resolve ai or zod differently end up with physically distinct copies of the same evlog version. Each copy used to carry its own AsyncLocalStorage (so useLogger() threw inside another copy's withEvlog()), its own logger configuration (so events emitted through the second copy were silently undrained and unredacted), and its own EvlogError class (so instanceof downgraded structured errors to bare 500s). All three are now shared per major version. createLoggerStorage() takes an optional storage id, and EvlogError.isEvlogError() replaces instanceof for cross-copy checks

  • #471 4e12ebb Thanks @HugoRCD! - refactor: route evlog/nestjs, evlog/react-router and evlog/sveltekit through defineFrameworkIntegration() — the three integrations each rebuilt the same request extraction, crypto.randomUUID() fallback, attachForkToLogger() call and storage.run() wrapper by hand instead of using the helper Hono, Express, Elysia, Fastify and oRPC already share. Behaviour is unchanged, but they now inherit anything the helper gains (including waitUntil extraction) for free. A new pickBaseEvlogOptions() toolkit export becomes the single place listing the BaseEvlogOptions fields, replacing the copy in toMiddlewareOptions() and the hand-written field list in evlog/eve — which silently dropped waitUntil, and would have dropped every option added later

  • #476 35431c2 Thanks @HugoRCD! - feat(hono): export useLogger() and enable log.fork() — Hono was the only framework integration without useLogger(), so reaching the request logger from a service or repository meant threading the Hono Context down through every call. import { useLogger } from 'evlog/hono' now resolves the same logger c.get('log') returns, and c.get('log') is unchanged — it stays the idiomatic accessor inside route handlers. Attaching AsyncLocalStorage also enables log.fork() on Hono, for background work that emits its own wide event correlated by _parentRequestId.

    Cloudflare Workers: useLogger() is backed by AsyncLocalStorage, so evlog/hono now imports node:async_hooks. Workers deployments need the nodejs_compat (or nodejs_als) compatibility flag in wrangler.toml. If you cannot enable it, use evlog/workers, which stays free of node:async_hooks by design.

  • #480 1b0edb8 Thanks @HugoRCD! - feat(loki): add the Grafana Loki drain adapter (evlog/loki) — createLokiDrain() pushes wide events to Loki's push API, covering self-hosted single-tenant, multi-tenant (X-Scope-OrgID), and Grafana Cloud (instance ID + token as HTTP Basic). Each event is pushed as a JSON log line under a deliberately small label set — service, environment, level by default — so Loki's index stays cheap while everything else (requestId, path, custom fields) remains queryable with | json. Promote extra fields with labelFields, add deployment-wide labels with labels. Events sharing a label set are grouped into one stream and sorted by timestamp, since Loki rejects out-of-order entries. Configured via LOKI_ENDPOINT / LOKI_API_KEY / LOKI_USER / LOKI_TENANT_ID or overrides, with sendToLoki / sendBatchToLoki for direct use.

  • #474 c5e85b0 Thanks @HugoRCD! - refactor(next): run withEvlog() through the shared middleware pipeline — evlog/next reimplemented the whole request pipeline (route filtering, per-route service, tail sampling, emit, enrich, drain) instead of calling createMiddlewareLogger, so it silently drifted from every other integration. Two options declared on NextEvlogOptions never did anything: plugins was never applied, because Next built no plugin runner at all, and global sampling.keep tail conditions were never evaluated — Next only called the user's keep callback, and its tail context carried no duration, so duration-based keep rules could not match. Both now work. keep callbacks also receive ctx.duration, and error statuses are derived through the shared extractErrorStatus. Next's after() is wired as the pipeline's waitUntil, so drain work still runs after the response is sent; enrich now runs before the response returns, matching the documented waitUntil contract and every other integration — move latency-sensitive work into drain if you relied on enrich being deferred

  • #466 5d99391 Thanks @HugoRCD! - Make emit-time redaction programmable

    RedactConfig.replacement now accepts a function, so a replacement can be derived from the value it replaces instead of being a constant — a stable fingerprint keeps requests correlatable without exposing the credential:

    initLogger({
      redact: {
        patterns: [/\/public\/claim\/([A-Za-z0-9._-]{12,})/g],
        replacement: (_match, ctx) =>
          `/public/claim/[tok:${fingerprint(ctx.groups[0])}]`,
      },
    });

    RedactConfig.transform covers policies that cannot be expressed declaratively — conditional on a sibling field, tenant-scoped, or allowlist-shaped. It runs before the declarative stages, so it sees raw values and paths / builtins / patterns still apply to whatever it leaves behind.

    Both run where redaction already runs: after the event is built, before the console write and before any drain. Failures are caught and reported like drain failures — a replacement function that throws or returns a non-string falls back to [REDACTED] rather than emitting the raw value, and a throwing transform is skipped without stopping the event from being logged.

    Function-valued policy cannot survive the build-time config bridges, which serialize to JSON; the Nitro modules now warn instead of dropping it silently.

    Closes #463

  • #470 374abfd Thanks @HugoRCD! - fix(core): stop dropping waitUntil when a defineEvlog() config is passed to middleware — toMiddlewareOptions() copied every other BaseEvlogOptions field but silently omitted waitUntil, so defineEvlog({ waitUntil }) lost the serverless drain hook on its way to the framework integration and drains were awaited inline instead of being registered with the platform. evlog/hono now also picks up c.executionCtx.waitUntil on its own, so drains on Cloudflare Workers and Vercel Edge complete after the response is returned with no manual wiring; adapters without an ExecutionContext (Node, Bun, Deno) keep draining inline, and an explicit waitUntil option still wins

  • #472 2540aa5 Thanks @HugoRCD! - feat(workers): add withEvlog() so Cloudflare Workers get the full middleware pipeline — evlog/workers was the only integration that never ran createMiddlewareLogger, so include / exclude, per-route routes overrides, redact, enrich, keep tail sampling and plugins simply had no effect there. Wrap your fetch handler with withEvlog(handler, options) and the wide event is emitted for you when the handler returns, with the same option surface every other framework accepts; ctx.waitUntil is picked up from the third argument so drains outlive the response, streaming bodies defer the emit until they complete, and requestId now honours x-request-id before falling back to cf-ray. defineWorkerFetch() and createWorkersLogger() are unchanged and remain the manual-emit path. The entrypoint stays free of node:async_hooks, so it still runs without nodejs_compat

Patch Changes

  • #457 899464a Thanks @EmilGramDK! - fix(core): redact own enumerable fields only, so getter-only prototype accessors such as DOMException.code are never assigned to. A field that still refuses the write now warns instead of throwing, and redaction keeps covering the own fields of class instances.

  • #477 f5d7474 Thanks @HugoRCD! - fix(core): serialize Error instances passed to the client log.error()name, message and stack are non-enumerable, so an Error spread into a wide event contributed nothing and the call emitted an event with no error at all. The docs teach log.error(new Error(...)) for Next.js client components, and the type only accepted a tag pair or a plain object, so the pattern failed to type check as well. Errors now land under error with the same shape the server logger stores, including code, status, cause and friends

  • #478 f662848 Thanks @HugoRCD! - fix(elysia): defer the wide event until a streaming body closes — evlog/elysia emitted from onAfterResponse, which fires as soon as the response is handed off. For an SSE or chunked body that is long before the stream finishes, so anything the handler set mid-stream (AI token counts, tool calls, final status) was dropped with a post-emit [evlog] warning. Streaming responses are now claimed in mapResponse and their body wrapped, so the emit waits for the stream to close — the same behaviour Hono, oRPC, SvelteKit, React Router and Next already had (#321). Non-streaming responses are unaffected and still emit immediately.

  • #457 2c20be7 Thanks @EmilGramDK! - fix(core): record the same error twice without crashing. A handler that logs the error it then throws hands the same instance to log.error() and to the integration's finish({ error }); the second merge walked into the caller's own object and threw on any read-only field it carried.

  • #484 9e3bd96 Thanks @HugoRCD! - docs: move OTLP and HyperDX into the "Cloud or Self-Hosted" category — both self-host as readily as they run managed, so filing them under cloud/ alongside Axiom and Datadog was misleading. They join Loki and ClickHouse under hybrid/, and each page now splits its setup into explicit self-hosted and managed sections rather than mixing the two. The old /integrate/adapters/cloud/otlp and /integrate/adapters/cloud/hyperdx URLs 301 to the new locations.

@evlog/cli@0.3.1

Patch Changes

@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
evlog-docs Ready Ready Preview, v0 Aug 1, 2026 8:10pm
evlog-render-lab Ready Ready Preview Aug 1, 2026 8:10pm
evlog-telemetry Ready Ready Preview Aug 1, 2026 8:10pm
just-use-evlog Ready Ready Preview Aug 1, 2026 8:10pm

Request Review

@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 83cc3fc to 4630bd4 Compare August 1, 2026 11:27
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 4630bd4 to 875b0b3 Compare August 1, 2026 14:44
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 875b0b3 to 1750ef8 Compare August 1, 2026 15:04
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 1750ef8 to 66faaea Compare August 1, 2026 15:15
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 66faaea to 69167e7 Compare August 1, 2026 16:09
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 69167e7 to 911045e Compare August 1, 2026 16:13
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 6b70d29 to 721a06b Compare August 1, 2026 16:30
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 721a06b to 5aac33d Compare August 1, 2026 16:32
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 5aac33d to 62f7eae Compare August 1, 2026 16:59
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 62f7eae to 2e1acdf Compare August 1, 2026 17:45
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 2e1acdf to 6da112a Compare August 1, 2026 19:31
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 6da112a to fa642e2 Compare August 1, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

redact cannot express a computed replacement, so anything needing logic must be scrubbed before emit()

1 participant