Skip to content

feat(node): beforeSpanSend hook and per-span limits - #4584

Merged
turnipdabeets merged 27 commits into
feat/traces-node-mvpfrom
feat/traces-before-span-send
Sep 4, 2026
Merged

feat(node): beforeSpanSend hook and per-span limits#4584
turnipdabeets merged 27 commits into
feat/traces-node-mvpfrom
feat/traces-before-span-send

Conversation

@turnipdabeets

@turnipdabeets turnipdabeets commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Problem

Two gaps in what a finished span may carry, which only make sense together:

Nothing scrubs a span. Spans carry whatever attributes the application puts on them, and a service that instruments its HTTP layer ends up with headers, query strings and user fields on them. There was no way to strip any of it before it left the process, and no way to drop a span you don't want exported at all (health checks, noisy internal polling).

Nothing bounded a span. A loop calling span.addEvent() per iteration, or an instrumentation layer copying every request header onto a span, grows it without limit until the ingestion endpoint rejects the payload as too large — at which point the 413 path shrinks the batch to a single span, that span is still too big, and it is dropped entirely. You lose the whole span rather than the excess.

Implements the Gating and beforeSpanSend and Span limits requirements of the traces capability spec.

Changes

new PostHog('phc_...', {
  traces: {
    serviceName: 'checkout-api',
    maxAttributesPerSpan: 128,     // default
    maxEventsPerSpan: 128,         // default
    maxAttributeValueLength: 8192, // default
    beforeSpanSend: (span) => {
      if (span.attributes['http.route'] === '/health') return null
      delete span.attributes['http.request.header.authorization']
      return span
    },
  },
})

beforeSpanSend runs on every finished span before it is queued.

  • Return null to drop the span. Nothing is enqueued and no error surfaces.
  • Plain values, not the wire format. The hook reads userId: 42, not { intValue: "42" }. It runs after auto-context attributes are attached, so posthogDistinctId and sessionId are visible and scrubbable.
  • Identity fields are read-only. traceId, spanId and parentSpanId are typed readonly, and an assignment that slips past the type system is reverted with a debug warning — rewriting ids after children have already shipped corrupts parentage.
  • A throwing hook drops the span (fail-closed). The hook is the documented scrubbing point, so a broken scrubber must not leak an unscrubbed record. This matches PostHogLogs._runBeforeSend, which also catches and drops — the spec describes the logs hook as fail-open, but this SDK's implementation is not.
  • Arrays run left to right, and the first hook returning null stops the chain. Non-callable entries are ignored rather than called.
  • Synchronous. A returned promise is not awaited; the span is dropped and the type says so.

Per-span caps at OpenTelemetry's defaults.

  • Earliest wins. The first 128 attributes and events are kept; later ones are dropped silently.
  • The counts ship with the span as droppedAttributesCount / droppedEventsCount, so a truncated span is visibly truncated rather than quietly wrong. Both are omitted when nothing was dropped.
  • SDK-attached keys are exempt and never evicted. posthogDistinctId, sessionId, url.full, screen.name and app.state do not count toward the cap, so a span at the limit still links back to its person and session. The exemption is from the count only — a hook can still delete them, which is the point of a scrubbing hook.
  • Overwriting an existing key always succeeds. The cap counts distinct user keys, not writes.
  • The event cap is absolute. An exception event the SDK records spends an ordinary slot like any other, so a span that fills its events and then throws keeps its error status but not the exception detail. droppedEventsCount reports the loss. See The exception reserve, and why it isn't here below.

A per-value length bound, maxAttributeValueLength, default 8192.

  • The count caps alone don't bound a span: one multi-MB value takes it past the body limit on its own, and the too-large path then loses that span whole. OpenTelemetry leaves its equivalent unlimited; the spec requires a finite default.
  • The bound reaches every string the value contains, including strings nested inside arrays and objects — a value the caller nested is no smaller than one they didn't.
  • It applies to span attributes, event attributes, status messages and resource attributes alike.

exception.stacktrace on spans. recordException and a throwing withSpan callback now attach the stack alongside exception.type and exception.message. Stacks ship by default and carry your server's file paths — the changeset says so, and beforeSpanSend can remove them.

The caps re-apply after beforeSpanSend, which is why these ship together.

Why one PR

These were opened as #4584 and #4586, two branches off the same base. The spec requires "The caps SHALL be re-applied after beforeSpanSend" — and neither branch can satisfy that alone, because neither has both halves in its tree. Split, the best either could do was leave a note asking whichever merged second to remember.

The failure that requirement prevents is real and not theoretical: the hook writes to the plain record, not through the span's guarded writer, so a hook that enriches a span — adding a customer tier, a region, a git SHA, the second most obvious use after scrubbing — pushes it straight back past the cap, with no trim and no dropped count. It then 413s and the span is lost whole, which is exactly what the cap exists to prevent.

They also conflicted in six files, so there was never a version of this where the two could be reviewed independently.

Reviewer notes

  • The re-apply lives in applySpanLimits, called at the end of the hook chain. Earliest-set entries win, matching the span-side rule, SDK-attached keys stay exempt, and the counts add to whatever the span itself already dropped. A hook that only removes attributes cannot invent a dropped count.
  • PostHogSpan's end callback now passes the auto-attached keys alongside the record. This is internal — the public SpanRecord is deliberately unchanged, so the exempt-key set never becomes API surface.
  • Enforcement otherwise lives in PostHogSpan, not at encode time, so an over-cap span never occupies memory in the first place — the point is to bound growth, not to trim on the way out.
  • Gate order is spec-mandated: SDK disabled → opted out → beforeSpanSend. Only then does the queue-depth check run, so a dropped span never counts against the queue.
  • Auto-context keys are identified by what the SDK attached at span start, so a user who explicitly sets posthogDistinctId themselves gets the exempt treatment for that key.
  • The post-hook pass works on a copy of the record. Every write it makes would throw on a frozen one, and being fail-closed that would silently drop every span a defensive Object.freeze({ ...span }) scrubber returned.
  • The value walk carries the encoder's own budget — an ancestors WeakSet and a 10,000-node cap — not just a depth limit. Depth alone is not a bound when siblings share a subtree.
  • Span events are re-sanitized after the hook too, not just name / startTime / endTime. A hook that appends or rebuilds events bypasses the checks addEvent applies, so an event with no timestamp encoded as timeUnixNano: "NaN000NaN" and one scaled by 1e6 encoded as a 25-digit value. Neither throws in _encodeBatch, so the span shipped, the server rejected the request, and _flushInner's fatal branch spliced the whole batch — up to maxExportBatchSize unrelated spans lost.

What review changed

Two fresh-context reviewers went at the branch, one required to demonstrate every finding by running it. Each fix below is pinned by a test that fails when it is reverted.

  • The value walk could hang the event loop. truncateAttributeValue had a depth cap and nothing else, so a value whose children point back at their siblings cost fanout ** depth visits: two self-references measured 254 ms of synchronous work inside the caller's own setAttribute, three did not finish in two minutes. It now carries the same ancestors WeakSet and node budget as encodeAnyValue, which it was supposed to mirror. This was a regression against the base, where the raw value went straight to the guarded encoder.
  • A toJSON bypassed the bound entirely. The walk read own keys; the encoder prefers toJSON. A dayjs value, a Decimal, or an ORM document could put a megabyte on the wire. The walk now resolves toJSON the way the encoder does.
  • A frozen record dropped 100% of spans, debug-only. The post-hook pass now copies first. The previous test asserted the drop; it now asserts the export.
  • The constructor walked the prototype chain (for...in), so a polluted Object.prototype key became an attribute of every span, defeating the encoder's own propertyIsEnumerable guard.
  • A nested __proto__ key was lost and swapped the copy's prototype — the copy used assignment where the rest of the codebase uses defineProperty for exactly this.
  • Resource attributes were never length-bounded, though the spec applies the bound to "span attributes, event attributes, and resource attributes alike" — and resource attributes ride on every batch, not on one span.
  • Status messages were unbounded, including the one recordException set from the same string it had just truncated for the event.
  • A hook writing an unknown status.code encoded as an empty status object, silently losing an error the span really had. An invented droppedAttributesCount reached the wire uncoerced.
  • Each key was read twice per walk, running a getter a second time.

The exception reserve, and why it isn't here

Review found that a span already at maxEventsPerSpan which then throws keeps its error status but loses the exception event, stack included. This PR carried a fix for a while: four slots reserved past the cap, on the reading that the spec caps "user-supplied" content and an exception the SDK attaches on your behalf isn't user-supplied.

It has been removed, and the cap is now absolute.

Two rounds of review went into the reserve and it produced two bugs of its own — first a reserve that was really a smaller exclusive cap (twenty recordException calls on an empty span kept four), then eligibility granted by event name, so a caller's own addEvent('exception') could put 132 events past a documented 128. Fixing the second properly meant an internal provenance marker on the event record, which worked but added a third thing to carry.

Set against that: nobody can show the case occurs. It needs a single span holding 128 events and then throwing. Traces has not shipped, so there is no usage to appeal to.

The decisive asymmetry is that adding the reserve later is purely additive — no caller breaks when a cap grows — while shipping it now and removing it later is a behaviour change. And the case is measurable in production without it: a span that fills up and throws still exports status: error and a non-zero droppedEventsCount, so status = error AND droppedEventsCount > 0 finds exactly this population once traces is live. If it turns out to be real, the reserve comes back with numbers behind it.

Removing it deleted 95 lines and one whole class of duplication: the rule no longer has two independent implementations in the span writer and the post-hook re-apply, so they cannot drift. It also means maxEventsPerSpan matches the spec's stated number exactly, with no sdk-specs change needed to ship.

Span and event names remain unbounded. That is 4579's path and unchanged here.

Known residuals, each rated NIT and deferred deliberately:

  • A hook can still mutate a queued span through a nested value it kept a reference to. The walk returns the same reference when nothing needed shortening, so a hook that holds a nested object and edits it after returning reaches the wire. This is the window setAttribute has always had rather than something the hook introduces, but the "edit in place" documentation invites the assumption that returning ends it.

  • An array whose own slice throws escapes the length bound.

  • Integer-like attribute keys break "earliest-set wins" in the post-hook re-apply. Object.keys front-loads array-index keys, so a hook adding an attribute named "0" jumps the queue and can evict a real one. Fixing it properly means tracking insertion order in a Map rather than an object, which is a data-structure change for a case that needs an attribute literally named "0".

  • A span that fills its events and then throws loses the exception detail. Deliberate, as above: the cap is absolute and the loss is reported through droppedEventsCount. Raising maxEventsPerSpan is the workaround for a span that both records many events and can fail.

Second review round

Two more fresh-context reviewers went over the post-fix branch, one required to demonstrate every finding by running it. Both independently found the same two blocking defects, and both are now fixed and pinned by tests:

  • The exception reserve was a smaller exclusive cap, not a reserve. Fixed at the time, then removed entirely along with the reserve — see above.
  • A multi-megabyte string could still escape maxAttributeValueLength. The traversal budget was charged before the string leaf was bounded, and the walk had no per-container item cap where the encoder stops at 1,000. So { rows: [20k ints], html: 2MB string } spent the whole 10,000-node budget on elements the encoder never emits and shipped the sibling string whole — 2,000,000 characters against a bound of 8192, on default config with no hook. Strings are now bounded before the budget is consulted, only containers are charged, and arrays are walked to the encoder's own item cap. The same repro now yields 8192 characters and a 27 KB body.

Also fixed from that round:

  • A hook mutating status.code in place defeated the fallback, because the snapshot held a reference to the object the hook was editing — and in-place mutation is the style this PR's own doc example uses. The same bug applied to the dropped counters. Both are now snapshotted by value before the chain runs.
  • The post-hook copy is now an explicit field-by-field rebuild rather than a spread. A spread copies own properties only, so a hook returning a class instance that exposes events through a prototype getter lost every span to the fail-closed branch. Naming the fields also means nothing a hook attached beyond them can reach the wire, and the SDK's own dropped counters are taken from the span rather than from the hook's return value.
  • A hole or a non-object in events cost the whole span; it now costs that entry.
  • _writeAttribute bounded values before checking the cap, spending ~354 ms of a 389 ms setAttributes call walking values it was about to drop. The cap is checked first.
  • toJSON ran twice, and a value that answered differently the second time escaped the bound entirely. It now resolves once and the resolved form is what is stored.

Third review round

Two more independent reviewers: one hunting bugs, one looking only for accidental damage to already-shipped code.

One more blocking defect, fixed and pinned:

  • A single throwing nested getter disabled maxAttributeValueLength entirely. The walk read child properties inside the parent's try, so one throw abandoned the whole value and the catch returned it untruncated. On default config, { body: <5 MB string>, get lazyRelation() { throw } } shipped a 5,000,717-byte payload; the same value without the getter shipped 8,843. That is a lazy ORM relation or a disposed resource sitting next to a large field — the shape assignUserAttributes already guards at depth 0, but only at depth 0. Per-key reads are now guarded individually: a throwing accessor costs its own key, which gets the encoder's [Unserializable] marker, and its siblings are still bounded. Re-measured: 8,979 bytes.
    The test covering this asserted the value was left alone, so the bug was pinned as intended behaviour. It now asserts the sibling is bounded.

Also fixed:

  • A null in events cost the whole span, not one event: the sanitising pass ran before the guard meant to catch it. Each event is now read behind its own guard.
  • attributes was not repaired the way events was, so a hook setting it to null dropped the span.
  • A toJSON resolving to undefined consumed a cap slot while encoding to nothing, and an invalid Date vanished where it previously shipped "Invalid Date". A nullish result now keeps the original value.
  • A non-string status.message from a hook bypassed the length bound and was stringified at full length by the encoder.

No regressions to shipped code. Measured, not assumed: the posthog-js browser bundle is +0 bytes (un-minified bundles byte-identical; none of the traces symbols appear in either), packages/core/src/utils is untouched, describeError's new stack field reaches nothing outside traces (it is on no barrel), neither SpanRecord nor BeforeSpanSendFn collides with an existing export, and there is no import cycle. Full suites across 24 packages: ~13,370 passing, 0 failures. One @posthog/nuxt fixture fails identically on the base commit — upstream nuxt-nightly breakage, unrelated.

Fifth review round

A pass over the branch after merging #4579's latest base into it. One conflict, in traces/index.ts's ./span import: this branch's applySpanLimits and truncateAttributes kept, NOOP_SPAN dropped, because the base replaced that call site with inertSpan(options) so a pass-through parent's inbound context carries to the child. Everything else auto-merged.

positiveInteger now falls back to the default for a fractional knob rather than flooring it, so that residual is gone: maxAttributesPerSpan: 1.5 resolves to 128, not 1.

The span-limits changeset still promised "a small reserve for exception events" after the reserve was removed, which would have shipped a wrong entry in the published changelog for three packages. Corrected, and it now names the dropped counters, which are how a caller sees a truncated span.

Re-verified on the merged tree: packages/core 1530 pass / 1 skipped (64 suites), packages/node 995 pass (35 suites) plus the edge-runtime config, @posthog/types 3 pass, oxfmt and oxlint clean, public API references regenerate with no drift. Run as a real service against a local ingestion endpoint, reading the decoded OTLP off the wire — 45 assertions covering the hook (drop, scrub, forge, throw, frozen return, async return, prototype-getter return), the caps and their dropped counts, the join-key exemption under a real withContext, the value bound through nesting / toJSON / a cyclic value / a throwing sibling getter, bounded status messages and resource attributes, and an inbound distributed traceparent reaching the hook with its real ids.

Fourth review round

Two reviewers on the ground earlier rounds had not covered: lifecycle and concurrency, and the thing run as a real application.

Three fixes, all of them consequences of round three's own repairs:

  • A repaired record could export as junk instead of being dropped. Forcing attributes to {} when it was not an object meant an async hook — whose Promise is truthy and reads undefined for every field — exported a span named unknown carrying no attributes at all: no posthogDistinctId, no sessionId, joinable to nobody, and silently. Before that repair it threw and was a warned drop. A return value missing either collection is now dropped and counted, which is the fail-closed rule the rest of the hook contract already follows. This also covers attributes: null and an array, which would have encoded as { "0": … }.
  • Keeping the original value when toJSON resolved nullish let the walk bypass a redaction. The value fell through to the own-key walk, which produced a plain copy the encoder no longer recognises as self-describing — so class Redacted { toJSON() { return null } } put its internals on the wire at maxAttributeValueLength: 10 and redacted correctly at 100. A self-describing value is now left whole.
  • Coercing a hook's status.message could throw and cost the span. A { toString() { throw } } message exported nothing, where the encoder downstream only marks the field. The coercion is guarded.

Ran as a real Express service against production ingestion (cycle4-svc-1788369331, project 381971) with setupExpressRequestContext, a scrubbing hook, nested spans, a genuine HTTP hop and an error route — 17 spans across 4 traces read back out of the product. Parentage held across the hop on one trace id; posthogDistinctId and sessionId on 17/17 spans including downstream ones; the scrubbed header absent from all of them; zero /health spans from five requests; error spans at status_code: 2. The hook wrote traceId = '0'.repeat(32) on every span and every exported id is real — identity immutability demonstrated in production, not just in a unit test.

Spec conformance walked scenario by scenario: 24 checks over Span limits, Gating and beforeSpanSend, Configuration knobs and the exception-recording scenarios — 0 failures, with context manager form not applicable (Python-only).

Cost

Measured against the base over 200k spans, three repeats, medians: a plain span goes 478k/s → 403k/s (2.09 → 2.48 µs), a span with 20 attributes 249k/s → 151k/s (4.02 → 6.62 µs), and a configured hook costs about the same again. No heap regression.

Most of the attribute-heavy cost is not the new work. It was attributed rather than guessed: neutering truncation, the cap accounting, and the ancestors set each moved it by ~5k/s, while swapping the null-prototype attribute store for {} moved it to 195k/s — V8 puts null-prototype objects in dictionary mode. That store is the __proto__-pollution guard, so this is a deliberate trade, kept: the worst case is 6.6 µs per span, 0.66% of a core for a service producing a thousand spans a second.

Verification

packages/core 1461 pass (63 suites), packages/node 1034 pass (36 suites), oxfmt and oxlint clean, @posthog/types / @posthog/core / posthog-node build clean, public API references regenerate with no drift.

Checked end-to-end against a real project (381971) with the caps set low so the behaviour is visible — attributes 5, events 3, values 64 — and read back out of the product, not just off the wire:

  • GET /health dropped by the hook: absent from the payload and from the product.

  • http.request.header.authorization deleted by a hook that then froze what it returned: gone, span still exported, enriched.tier present.

  • The hook forged traceId to all zeros on every span; the exported ids are the real ones.

  • overflow: kept attr-0..attr-4 plus both join keys, droppedAttributesCount: 16 (15 user attributes plus the hook's own enrichment, trimmed by the post-hook re-apply), droppedEventsCount: 7.

  • long-values: a 5000-character string, the same string nested inside an array, a toJSON returning 5000 characters, a doubly self-referencing object and a 5000-character status message — all bounded to 64, nothing hung.

  • A 5000-character resourceAttributes value bounded to 64 on the batch resource.

  • retries, eight recordException calls with the event cap at three: three kept, droppedEventsCount: 5.

  • throwing, on a span that added ten events before it threw with the event cap at three: step-0..step-2 kept, droppedEventsCount: 8, status_code: 2, original error propagated unchanged. The exception event does not fit, which is the documented behaviour of an absolute cap.

    These two figures are recomputed against the implementation, not re-observed: the product read-back described in this section was run before the reserve was removed, so its retries and throwing spans reflect the reserve's behaviour. Everything else in the list is unaffected by that change and stands as recorded.

  • Both counters omitted on the spans that dropped nothing.

Carried over from #4579's review

Consent is now re-checked between span batches. A drain sends one batch per loop iteration and gates consent only before the first, so a user opting out while a batch was in flight left the batches behind it exporting posthogDistinctId and sessionId afterwards. _flushInner now re-checks isDisabled / optedOut at the top of every iteration and discards the rest of the queue. It is the existing discard block moved into one method and called from a second place, not a new mechanism. Two regression tests: a backlog built during an outage, then optOut() — and separately disable() — landing while the retried head batch is in flight, both verified to fail with the loop-body check removed.

Fixed here rather than in #4579 because that PR is approved and this one is stacked on it, so both ship in the same release. disable() was already covered before this: _sendOtlpBatch short-circuits on disabled and returns { kind: 'fatal' }, which the loop splices away without a request. The genuine hole was optOut(), which nothing downstream checked.

No changeset: the behaviour it corrects is inside the traces feature #4579 introduces, which has not shipped.

Release info Sub-libraries affected

Libraries affected

  • All of them
  • posthog-js (web)
  • posthog-js-lite (web lite)
  • posthog-node
  • posthog-react-native
  • @posthog/react-native-plugin
  • @posthog/react
  • @posthog/ai
  • @posthog/convex
  • @posthog/next
  • @posthog/nextjs-config
  • @posthog/nuxt
  • @posthog/openfeature-node-provider
  • @posthog/openfeature-web-provider
  • @posthog/rollup-plugin
  • @posthog/webpack-plugin
  • @posthog/types
  • @posthog/browser-common

@posthog/core is also bumped (minor); it has no checkbox above.

Checklist

  • Tests for new code
  • Accounted for the impact of any changes across different platforms
  • Accounted for backwards compatibility of any changes (no breaking changes!)
  • Took care not to unnecessarily increase the bundle size

All surface is additive on top of #4579, which has not shipped, so nothing here can break released code.

If releasing new changes

  • Ran pnpm changeset to generate a changeset file

Docs: PostHog/posthog.com#19837 covers this surface too — a Scrubbing and dropping spans section, a Span limits section, and the new configuration rows. It stays a draft until this and #4579 ship, and documents them as one release, since this PR merges into #4579's branch.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Built with Claude Code, directed by @turnipdabeets, from the merged traces capability spec in sdk-specs. The merge of #4586 into this PR, and the cap re-apply, came out of a review pass that checked the stack against that spec and found the requirement no single PR could satisfy.

@turnipdabeets turnipdabeets self-assigned this Aug 20, 2026
@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Size Change: +33.5 kB (+0.16%)

Total Size: 20.9 MB

📦 View Changed
Filename Size Change
packages/core/dist/traces/config.js 4.51 kB +1.06 kB (+30.83%) 🚨
packages/core/dist/traces/config.mjs 3.15 kB +1.06 kB (+50.84%) 🆘
packages/core/dist/traces/index.js 23.9 kB +7.24 kB (+43.55%) 🚨
packages/core/dist/traces/index.mjs 21.6 kB +7 kB (+47.92%) 🚨
packages/core/dist/traces/otlp.js 6.16 kB +429 B (+7.48%) 🔍
packages/core/dist/traces/otlp.mjs 3.98 kB +337 B (+9.26%) 🔍
packages/core/dist/traces/sanitize.js 3.59 kB +64 B (+1.81%)
packages/core/dist/traces/sanitize.mjs 1.88 kB +64 B (+3.53%)
packages/core/dist/traces/span.js 18.1 kB +8.37 kB (+85.87%) 🆘
packages/core/dist/traces/span.mjs 14.9 kB +7.6 kB (+103.87%) 🆘
packages/node/dist/client.js 61.9 kB +137 B (+0.22%)
packages/node/dist/client.mjs 58.3 kB +123 B (+0.21%)
ℹ️ View Unchanged
Filename Size
packages/ai/dist/adk/index.cjs 35.6 kB
packages/ai/dist/adk/index.mjs 35.4 kB
packages/ai/dist/anthropic/index.cjs 35.9 kB
packages/ai/dist/anthropic/index.mjs 34.5 kB
packages/ai/dist/gemini/index.cjs 33.5 kB
packages/ai/dist/gemini/index.mjs 33.3 kB
packages/ai/dist/index.cjs 50.2 kB
packages/ai/dist/index.mjs 50 kB
packages/ai/dist/langchain/index.cjs 36.7 kB
packages/ai/dist/langchain/index.mjs 36.6 kB
packages/ai/dist/langchain/middleware/index.cjs 42.8 kB
packages/ai/dist/langchain/middleware/index.mjs 42.5 kB
packages/ai/dist/openai-agents/index.cjs 29.5 kB
packages/ai/dist/openai-agents/index.mjs 29.4 kB
packages/ai/dist/openai/index.cjs 78.8 kB
packages/ai/dist/openai/index.mjs 78.2 kB
packages/ai/dist/otel/index.cjs 15.4 kB
packages/ai/dist/otel/index.mjs 15.2 kB
packages/ai/dist/vercel/index.cjs 40.9 kB
packages/ai/dist/vercel/index.mjs 40.8 kB
packages/browser-common/dist/client.js 585 B
packages/browser-common/dist/client.mjs 12 B
packages/browser-common/dist/config.js 1.52 kB
packages/browser-common/dist/config.mjs 216 B
packages/browser-common/dist/constants.js 1.75 kB
packages/browser-common/dist/constants.mjs 219 B
packages/browser-common/dist/disposable.js 1.72 kB
packages/browser-common/dist/disposable.mjs 386 B
packages/browser-common/dist/extension-runtime.js 3.17 kB
packages/browser-common/dist/extension-runtime.mjs 1.83 kB
packages/browser-common/dist/extension.js 585 B
packages/browser-common/dist/extension.mjs 12 B
packages/browser-common/dist/index.js 2.98 kB
packages/browser-common/dist/index.mjs 130 B
packages/browser-common/dist/persistence.js 585 B
packages/browser-common/dist/persistence.mjs 12 B
packages/browser-common/dist/pubsub.js 2.63 kB
packages/browser-common/dist/pubsub.mjs 1.35 kB
packages/browser-common/dist/token.js 585 B
packages/browser-common/dist/token.mjs 12 B
packages/browser-common/dist/types/compression.js 1.37 kB
packages/browser-common/dist/types/compression.mjs 93 B
packages/browser-common/dist/types/index.js 3.68 kB
packages/browser-common/dist/types/index.mjs 144 B
packages/browser-common/dist/types/network-recording.js 585 B
packages/browser-common/dist/types/network-recording.mjs 12 B
packages/browser-common/dist/types/remote-config.js 585 B
packages/browser-common/dist/types/remote-config.mjs 12 B
packages/browser-common/dist/types/surveys.js 4.61 kB
packages/browser-common/dist/types/surveys.mjs 2.17 kB
packages/browser-common/dist/utils/array-at-********.js 619 B
packages/browser-common/dist/utils/array-at-********.mjs 437 B
packages/browser-common/dist/utils/autocapture-utils.js 24.3 kB
packages/browser-common/dist/utils/autocapture-utils.mjs 18.6 kB
packages/browser-common/dist/utils/blocked-uas.js 2.2 kB
packages/browser-common/dist/utils/blocked-uas.mjs 598 B
packages/browser-common/dist/utils/cookie-utils.js 1.99 kB
packages/browser-common/dist/utils/cookie-utils.mjs 673 B
packages/browser-common/dist/utils/device-model-utils.js 2.08 kB
packages/browser-common/dist/utils/device-model-utils.mjs 678 B
packages/browser-common/dist/utils/element-utils.js 2.56 kB
packages/browser-common/dist/utils/element-utils.mjs 804 B
packages/browser-common/dist/utils/elements-chain-utils.js 2.86 kB
packages/browser-common/dist/utils/elements-chain-utils.mjs 1.23 kB
packages/browser-common/dist/utils/encode-utils.js 1.49 kB
packages/browser-common/dist/utils/encode-utils.mjs 205 B
packages/browser-common/dist/utils/event-utils.js 15.8 kB
packages/browser-common/dist/utils/event-utils.mjs 10 kB
packages/browser-common/dist/utils/general-utils.js 7.41 kB
packages/browser-common/dist/utils/general-utils.mjs 4.49 kB
packages/browser-common/dist/utils/globals.js 2.83 kB
packages/browser-common/dist/utils/globals.mjs 842 B
packages/browser-common/dist/utils/logger.js 3.5 kB
packages/browser-common/dist/utils/logger.mjs 1.61 kB
packages/browser-common/dist/utils/matcher-utils.js 2.94 kB
packages/browser-common/dist/utils/matcher-utils.mjs 1.33 kB
packages/browser-common/dist/utils/promise-utils.js 1.45 kB
packages/browser-common/dist/utils/promise-utils.mjs 169 B
packages/browser-common/dist/utils/property-utils.js 3.63 kB
packages/browser-common/dist/utils/property-utils.mjs 1.6 kB
packages/browser-common/dist/utils/prototype-utils.js 3.61 kB
packages/browser-common/dist/utils/prototype-utils.mjs 1.86 kB
packages/browser-common/dist/utils/regex-utils.js 1.55 kB
packages/browser-common/dist/utils/regex-utils.mjs 71 B
packages/browser-common/dist/utils/request-utils.js 6.83 kB
packages/browser-common/dist/utils/request-utils.mjs 4.19 kB
packages/browser-common/dist/utils/simple-event-emitter.js 1.86 kB
packages/browser-common/dist/utils/simple-event-emitter.mjs 553 B
packages/browser-common/dist/utils/stylesheet-loader.js 2.23 kB
packages/browser-common/dist/utils/stylesheet-loader.mjs 823 B
packages/browser-common/dist/utils/type-utils.js 1.68 kB
packages/browser-common/dist/utils/type-utils.mjs 258 B
packages/browser-common/dist/utils/url-targeting-utils.js 2.45 kB
packages/browser-common/dist/utils/url-targeting-utils.mjs 863 B
packages/browser-common/dist/utils/uuidv7.js 6.72 kB
packages/browser-common/dist/utils/uuidv7.mjs 5.14 kB
packages/browser-next/dist/analytics-********.js 1.68 kB
packages/browser-next/dist/analytics-********.mjs 219 B
packages/browser-next/dist/analytics-options.js 585 B
packages/browser-next/dist/analytics-options.mjs 12 B
packages/browser-next/dist/analytics.js 6.62 kB
packages/browser-next/dist/analytics.mjs 5.15 kB
packages/browser-next/dist/bot-filter.js 2.38 kB
packages/browser-next/dist/bot-filter.mjs 1.09 kB
packages/browser-next/dist/capture-v1.js 27.8 kB
packages/browser-next/dist/capture-v1.mjs 25.3 kB
packages/browser-next/dist/core.js 1.69 kB
packages/browser-next/dist/core.mjs 185 B
packages/browser-next/dist/extensions/registry.js 3.41 kB
packages/browser-next/dist/extensions/registry.mjs 2.11 kB
packages/browser-next/dist/id.js 2.25 kB
packages/browser-next/dist/id.mjs 983 B
packages/browser-next/dist/index.js 2.68 kB
packages/browser-next/dist/index.mjs 1.18 kB
packages/browser-next/dist/lane.js 18.1 kB
packages/browser-next/dist/lane.mjs 16.9 kB
packages/browser-next/dist/logger.js 1.87 kB
packages/browser-next/dist/logger.mjs 581 B
packages/browser-next/dist/posthog.js 33.2 kB
packages/browser-next/dist/posthog.mjs 30.9 kB
packages/browser-next/dist/rate-limiter.js 2.89 kB
packages/browser-next/dist/rate-limiter.mjs 1.58 kB
packages/browser-next/dist/request.js 4.61 kB
packages/browser-next/dist/request.mjs 3.21 kB
packages/browser-next/dist/state.js 24.9 kB
packages/browser-next/dist/state.mjs 23.2 kB
packages/browser-next/dist/types.js 585 B
packages/browser-next/dist/types.mjs 12 B
packages/browser-next/dist/version.js 1.31 kB
packages/browser-next/dist/version.mjs 45 B
packages/browser/dist/all-external-dependencies.js 362 kB
packages/browser/dist/array.full.es5.js 496 kB
packages/browser/dist/array.full.js 606 kB
packages/browser/dist/array.full.no-********.js 663 kB
packages/browser/dist/array.js 281 kB
packages/browser/dist/array.no-********.js 320 kB
packages/browser/dist/conversations.js 69 kB
packages/browser/dist/crisp-chat-integration.js 2.01 kB
packages/browser/dist/customizations.full.js 16.1 kB
packages/browser/dist/customizations.js 15.9 kB
packages/browser/dist/dead-clicks-autocapture.js 18.3 kB
packages/browser/dist/default-extensions.js 279 kB
packages/browser/dist/element-inference.js 5.6 kB
packages/browser/dist/exception-autocapture.js 13.6 kB
packages/browser/dist/extension-bundles.js 155 kB
packages/browser/dist/external-scripts-loader.js 3.58 kB
packages/browser/dist/intercom-integration.js 2.06 kB
packages/browser/dist/lazy-********.js 202 kB
packages/browser/dist/logs.js 5.82 kB
packages/browser/dist/main.js 286 kB
packages/browser/dist/module.full.js 608 kB
packages/browser/dist/module.full.no-********.js 666 kB
packages/browser/dist/module.js 285 kB
packages/browser/dist/module.no-********.js 324 kB
packages/browser/dist/module.slim.js 142 kB
packages/browser/dist/module.slim.no-********.js 157 kB
packages/browser/dist/posthog-********.js 202 kB
packages/browser/dist/product-tours-preview.js 82.4 kB
packages/browser/dist/product-tours.js 124 kB
packages/browser/dist/recorder-v2.js 126 kB
packages/browser/dist/recorder.js 126 kB
packages/browser/dist/rrweb-plugin-console-record.js 7.05 kB
packages/browser/dist/rrweb-types.js 2.33 kB
packages/browser/dist/rrweb.js 319 kB
packages/browser/dist/surveys-preview.js 81.3 kB
packages/browser/dist/surveys.js 102 kB
packages/browser/dist/tracing-headers.js 3.74 kB
packages/browser/dist/web-vitals-soft-navs.js 9.94 kB
packages/browser/dist/web-vitals-with-attribution-soft-navs.js 25.3 kB
packages/browser/dist/web-vitals-with-attribution.js 25.3 kB
packages/browser/dist/web-vitals.js 9.92 kB
packages/browser/react/dist/esm/index.js 22.1 kB
packages/browser/react/dist/esm/slim/index.js 18.5 kB
packages/browser/react/dist/esm/surveys/index.js 3.61 kB
packages/browser/react/dist/umd/index.js 26.4 kB
packages/browser/react/dist/umd/slim/index.js 22.3 kB
packages/browser/react/dist/umd/surveys/index.js 5.63 kB
packages/convex/dist/client/feature-flags/crypto.js 76 B
packages/convex/dist/client/feature-flags/evaluator.js 14.9 kB
packages/convex/dist/client/feature-flags/index.js 196 B
packages/convex/dist/client/feature-flags/match-********.js 5.08 kB
packages/convex/dist/client/feature-flags/types.js 44 B
packages/convex/dist/client/index.js 14.8 kB
packages/convex/dist/component/_generated/api.js 712 B
packages/convex/dist/component/_generated/component.js 212 B
packages/convex/dist/component/_generated/dataModel.js 230 B
packages/convex/dist/component/_generated/server.js 3.74 kB
packages/convex/dist/component/convex.config.js 1.66 kB
packages/convex/dist/component/crons.js 969 B
packages/convex/dist/component/lib.js 24.8 kB
packages/convex/dist/component/schema.js 1.17 kB
packages/convex/dist/component/version.js 67 B
packages/core/dist/cookie.js 5.44 kB
packages/core/dist/cookie.mjs 3.12 kB
packages/core/dist/error-tracking/chunk-ids.js 2.64 kB
packages/core/dist/error-tracking/chunk-ids.mjs 1.31 kB
packages/core/dist/error-tracking/coercers/dom-exception-coercer.js 2.4 kB
packages/core/dist/error-tracking/coercers/dom-exception-coercer.mjs 993 B
packages/core/dist/error-tracking/coercers/error-coercer.js 2.23 kB
packages/core/dist/error-tracking/coercers/error-coercer.mjs 888 B
packages/core/dist/error-tracking/coercers/error-event-coercer.js 2.45 kB
packages/core/dist/error-tracking/coercers/error-event-coercer.mjs 1.05 kB
packages/core/dist/error-tracking/coercers/event-coercer.js 1.92 kB
packages/core/dist/error-tracking/coercers/event-coercer.mjs 548 B
packages/core/dist/error-tracking/coercers/index.js 5.82 kB
packages/core/dist/error-tracking/coercers/index.mjs 326 B
packages/core/dist/error-tracking/coercers/object-coercer.js 4.13 kB
packages/core/dist/error-tracking/coercers/object-coercer.mjs 2.53 kB
packages/core/dist/error-tracking/coercers/primitive-coercer.js 1.76 kB
packages/core/dist/error-tracking/coercers/primitive-coercer.mjs 419 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.js 2.69 kB
packages/core/dist/error-tracking/coercers/promise-rejection-event.mjs 1.25 kB
packages/core/dist/error-tracking/coercers/string-coercer.js 2.11 kB
packages/core/dist/error-tracking/coercers/string-coercer.mjs 820 B
packages/core/dist/error-tracking/coercers/utils.js 2.16 kB
packages/core/dist/error-tracking/coercers/utils.mjs 716 B
packages/core/dist/error-tracking/error-properties-builder.js 5.66 kB
packages/core/dist/error-tracking/error-properties-builder.mjs 4.23 kB
packages/core/dist/error-tracking/exception-steps.js 6.1 kB
packages/core/dist/error-tracking/exception-steps.mjs 3.83 kB
packages/core/dist/error-tracking/index.js 4.62 kB
packages/core/dist/error-tracking/index.mjs 222 B
packages/core/dist/error-tracking/parsers/base.js 2.1 kB
packages/core/dist/error-tracking/parsers/base.mjs 627 B
packages/core/dist/error-tracking/parsers/chrome.js 2.83 kB
packages/core/dist/error-tracking/parsers/chrome.mjs 1.32 kB
packages/core/dist/error-tracking/parsers/gecko.js 2.57 kB
packages/core/dist/error-tracking/parsers/gecko.mjs 1.13 kB
packages/core/dist/error-tracking/parsers/index.js 4.85 kB
packages/core/dist/error-tracking/parsers/index.mjs 2.01 kB
packages/core/dist/error-tracking/parsers/node.js 4.31 kB
packages/core/dist/error-tracking/parsers/node.mjs 2.95 kB
packages/core/dist/error-tracking/parsers/opera.js 2.35 kB
packages/core/dist/error-tracking/parsers/opera.mjs 746 B
packages/core/dist/error-tracking/parsers/safari.js 1.98 kB
packages/core/dist/error-tracking/parsers/safari.mjs 574 B
packages/core/dist/error-tracking/parsers/winjs.js 1.82 kB
packages/core/dist/error-tracking/parsers/winjs.mjs 426 B
packages/core/dist/error-tracking/release.js 1.52 kB
packages/core/dist/error-tracking/release.mjs 203 B
packages/core/dist/error-tracking/types.js 1.42 kB
packages/core/dist/error-tracking/types.mjs 131 B
packages/core/dist/error-tracking/utils.js 1.9 kB
packages/core/dist/error-tracking/utils.mjs 604 B
packages/core/dist/eventemitter.js 1.88 kB
packages/core/dist/eventemitter.mjs 571 B
packages/core/dist/featureFlagLocalEvaluation.js 22.2 kB
packages/core/dist/featureFlagLocalEvaluation.mjs 19.6 kB
packages/core/dist/featureFlagUtils.js 8.57 kB
packages/core/dist/featureFlagUtils.mjs 5.48 kB
packages/core/dist/gzip.js 5.88 kB
packages/core/dist/gzip.mjs 3.87 kB
packages/core/dist/index.js 25 kB
packages/core/dist/index.mjs 1.93 kB
packages/core/dist/logs/index.js 10.9 kB
packages/core/dist/logs/index.mjs 9.16 kB
packages/core/dist/logs/logs-utils.js 6.69 kB
packages/core/dist/logs/logs-utils.mjs 4.51 kB
packages/core/dist/logs/types.js 585 B
packages/core/dist/logs/types.mjs 12 B
packages/core/dist/metrics/config.js 2.05 kB
packages/core/dist/metrics/config.mjs 735 B
packages/core/dist/metrics/index.js 14.5 kB
packages/core/dist/metrics/index.mjs 12 kB
packages/core/dist/metrics/metrics-utils.js 3.75 kB
packages/core/dist/metrics/metrics-utils.mjs 1.71 kB
packages/core/dist/metrics/types.js 585 B
packages/core/dist/metrics/types.mjs 12 B
packages/core/dist/posthog-core-stateless.js 47.4 kB
packages/core/dist/posthog-core-stateless.mjs 44 kB
packages/core/dist/posthog-core.js 49.6 kB
packages/core/dist/posthog-core.mjs 43.9 kB
packages/core/dist/surveys/activation.js 2.29 kB
packages/core/dist/surveys/activation.mjs 572 B
packages/core/dist/surveys/events.js 4.36 kB
packages/core/dist/surveys/events.mjs 2.05 kB
packages/core/dist/surveys/index.js 6.64 kB
packages/core/dist/surveys/index.mjs 798 B
packages/core/dist/surveys/keys.js 1.8 kB
packages/core/dist/surveys/keys.mjs 350 B
packages/core/dist/surveys/property-********.js 3.78 kB
packages/core/dist/surveys/property-********.mjs 2.14 kB
packages/core/dist/surveys/translations.js 9.18 kB
packages/core/dist/surveys/translations.mjs 6.83 kB
packages/core/dist/surveys/validation.js 3.15 kB
packages/core/dist/surveys/validation.mjs 1.51 kB
packages/core/dist/testing/index.js 2.76 kB
packages/core/dist/testing/index.mjs 79 B
packages/core/dist/testing/PostHogCoreTestClient.js 3.33 kB
packages/core/dist/testing/PostHogCoreTestClient.mjs 1.82 kB
packages/core/dist/testing/test-utils.js 2.9 kB
packages/core/dist/testing/test-utils.mjs 1.11 kB
packages/core/dist/traces/context.js 1.64 kB
packages/core/dist/traces/context.mjs 318 B
packages/core/dist/traces/ids.js 3.2 kB
packages/core/dist/traces/ids.mjs 1.52 kB
packages/core/dist/traces/traceparent.js 3.72 kB
packages/core/dist/traces/traceparent.mjs 1.84 kB
packages/core/dist/traces/types.js 585 B
packages/core/dist/traces/types.mjs 12 B
packages/core/dist/tracing-headers.js 3.48 kB
packages/core/dist/tracing-headers.mjs 2.08 kB
packages/core/dist/types.js 8.39 kB
packages/core/dist/types.mjs 5.23 kB
packages/core/dist/utils/bot-detection.js 3.38 kB
packages/core/dist/utils/bot-detection.mjs 1.96 kB
packages/core/dist/utils/browser-utils.js 1.57 kB
packages/core/dist/utils/browser-utils.mjs 182 B
packages/core/dist/utils/bucketed-rate-limiter.js 4.32 kB
packages/core/dist/utils/bucketed-rate-limiter.mjs 2.22 kB
packages/core/dist/utils/index.js 15.4 kB
packages/core/dist/utils/index.mjs 3.34 kB
packages/core/dist/utils/json-utils.js 7.44 kB
packages/core/dist/utils/json-utils.mjs 5.02 kB
packages/core/dist/utils/logger.js 2.68 kB
packages/core/dist/utils/logger.mjs 1.29 kB
packages/core/dist/utils/number-utils.js 3.42 kB
packages/core/dist/utils/number-utils.mjs 1.68 kB
packages/core/dist/utils/otlp-********.js 2.97 kB
packages/core/dist/utils/otlp-********.mjs 1.32 kB
packages/core/dist/utils/otlp-any-value.js 7.96 kB
packages/core/dist/utils/otlp-any-value.mjs 5.77 kB
packages/core/dist/utils/promise-queue.js 2.58 kB
packages/core/dist/utils/promise-queue.mjs 1.25 kB
packages/core/dist/utils/string-utils.js 3.83 kB
packages/core/dist/utils/string-utils.mjs 1.97 kB
packages/core/dist/utils/type-utils.js 7.52 kB
packages/core/dist/utils/type-utils.mjs 3.27 kB
packages/core/dist/utils/user-agent-utils.js 18.5 kB
packages/core/dist/utils/user-agent-utils.mjs 14.7 kB
packages/core/dist/vendor/uuidv7.js 8.36 kB
packages/core/dist/vendor/uuidv7.mjs 6.7 kB
packages/mcp/dist/extensions/analytics-parameters.js 6.63 kB
packages/mcp/dist/extensions/analytics-parameters.mjs 4.27 kB
packages/mcp/dist/extensions/capture.js 4.04 kB
packages/mcp/dist/extensions/capture.mjs 2.58 kB
packages/mcp/dist/extensions/client-********.js 6.33 kB
packages/mcp/dist/extensions/client-********.mjs 3.71 kB
packages/mcp/dist/extensions/compatibility.js 5.45 kB
packages/mcp/dist/extensions/compatibility.mjs 3.4 kB
packages/mcp/dist/extensions/constants.js 5.45 kB
packages/mcp/dist/extensions/constants.mjs 2.94 kB
packages/mcp/dist/extensions/context-parameters.js 2.85 kB
packages/mcp/dist/extensions/context-parameters.mjs 893 B
packages/mcp/dist/extensions/conversation-id.js 6.41 kB
packages/mcp/dist/extensions/conversation-id.mjs 3.58 kB
packages/mcp/dist/extensions/detect.js 3.87 kB
packages/mcp/dist/extensions/detect.mjs 1.49 kB
packages/mcp/dist/extensions/event-types.js 1.78 kB
packages/mcp/dist/extensions/event-types.mjs 459 B
packages/mcp/dist/extensions/exceptions.js 2.67 kB
packages/mcp/dist/extensions/exceptions.mjs 1.19 kB
packages/mcp/dist/extensions/headers.js 2.08 kB
packages/mcp/dist/extensions/headers.mjs 643 B
packages/mcp/dist/extensions/ids.js 2.11 kB
packages/mcp/dist/extensions/ids.mjs 637 B
packages/mcp/dist/extensions/instrument-********.js 5.02 kB
packages/mcp/dist/extensions/instrument-********.mjs 3.18 kB
packages/mcp/dist/extensions/instrument-highlevel.js 12.8 kB
packages/mcp/dist/extensions/instrument-highlevel.mjs 10.2 kB
packages/mcp/dist/extensions/instrumentation.js 27.9 kB
packages/mcp/dist/extensions/instrumentation.mjs 21.9 kB
packages/mcp/dist/extensions/intent.js 3.3 kB
packages/mcp/dist/extensions/intent.mjs 1.64 kB
packages/mcp/dist/extensions/internal.js 7.63 kB
packages/mcp/dist/extensions/internal.mjs 5.23 kB
packages/mcp/dist/extensions/lib-********.js 1.7 kB
packages/mcp/dist/extensions/lib-********.mjs 267 B
packages/mcp/dist/extensions/logger.js 1.81 kB
packages/mcp/dist/extensions/logger.mjs 380 B
packages/mcp/dist/extensions/mcp-********.js 4.78 kB
packages/mcp/dist/extensions/mcp-********.mjs 3.3 kB
packages/mcp/dist/extensions/mcp-sdk-compat.js 5.13 kB
packages/mcp/dist/extensions/mcp-sdk-compat.mjs 2.9 kB
packages/mcp/dist/extensions/model-parameters.js 3.58 kB
packages/mcp/dist/extensions/model-parameters.mjs 1.41 kB
packages/mcp/dist/extensions/output-instructions.js 6.21 kB
packages/mcp/dist/extensions/output-instructions.mjs 3.91 kB
packages/mcp/dist/extensions/posthog-events.js 11.8 kB
packages/mcp/dist/extensions/posthog-events.mjs 7.98 kB
packages/mcp/dist/extensions/posthog-mcp.js 7.04 kB
packages/mcp/dist/extensions/posthog-mcp.mjs 4.93 kB
packages/mcp/dist/extensions/request-headers.js 2.27 kB
packages/mcp/dist/extensions/request-headers.mjs 963 B
packages/mcp/dist/extensions/sanitization.js 4.59 kB
packages/mcp/dist/extensions/sanitization.mjs 2.86 kB
packages/mcp/dist/extensions/session-token.js 5.47 kB
packages/mcp/dist/extensions/session-token.mjs 3.6 kB
packages/mcp/dist/extensions/session.js 6.74 kB
packages/mcp/dist/extensions/session.mjs 4.12 kB
packages/mcp/dist/extensions/sink.js 4.47 kB
packages/mcp/dist/extensions/sink.mjs 2.67 kB
packages/mcp/dist/extensions/tools.js 3.61 kB
packages/mcp/dist/extensions/tools.mjs 1.63 kB
packages/mcp/dist/extensions/tracing-helpers.js 2.51 kB
packages/mcp/dist/extensions/tracing-helpers.mjs 772 B
packages/mcp/dist/extensions/transport-********.js 3 kB
packages/mcp/dist/extensions/transport-********.mjs 1.09 kB
packages/mcp/dist/extensions/truncation.js 11.6 kB
packages/mcp/dist/extensions/truncation.mjs 9.79 kB
packages/mcp/dist/index.js 8.88 kB
packages/mcp/dist/index.mjs 4.76 kB
packages/mcp/dist/types.js 585 B
packages/mcp/dist/types.mjs 12 B
packages/mcp/dist/version.js 1.31 kB
packages/mcp/dist/version.mjs 46 B
packages/next/dist/app/PostHogProvider.js 5.37 kB
packages/next/dist/client/ClientPostHogProvider.js 2.28 kB
packages/next/dist/client/hooks.js 172 B
packages/next/dist/client/PostHogPageView.js 4.23 kB
packages/next/dist/index.client.js 401 B
packages/next/dist/index.edge.js 570 B
packages/next/dist/index.js 554 B
packages/next/dist/index.react-server.js 420 B
packages/next/dist/middleware/postHogMiddleware.js 4.08 kB
packages/next/dist/pages.client.js 225 B
packages/next/dist/pages.edge.js 294 B
packages/next/dist/pages.js 347 B
packages/next/dist/pages/createPostHog.js 1.48 kB
packages/next/dist/pages/getServerSidePostHog.js 1.48 kB
packages/next/dist/pages/PostHogPageView.js 1.77 kB
packages/next/dist/pages/PostHogProvider.js 1.58 kB
packages/next/dist/server.edge.js 795 B
packages/next/dist/server/captureRequestError.js 5.26 kB
packages/next/dist/server/clientCache.edge.js 305 B
packages/next/dist/server/clientCache.js 1.54 kB
packages/next/dist/server/clientCache.node.js 305 B
packages/next/dist/server/createPostHog.js 1.44 kB
packages/next/dist/server/getPostHog.js 3.45 kB
packages/next/dist/server/onRequestError.js 1.39 kB
packages/next/dist/server/onRequestError.types.js 59 B
packages/next/dist/shared/browser.js 195 B
packages/next/dist/shared/config.js 2.23 kB
packages/next/dist/shared/constants.js 201 B
packages/next/dist/shared/cookie.js 540 B
packages/next/dist/shared/identity.js 2.56 kB
packages/next/dist/shared/tracing-headers.js 2.18 kB
packages/nextjs-config/dist/config.js 10.3 kB
packages/nextjs-config/dist/config.mjs 8.67 kB
packages/nextjs-config/dist/index.js 2.21 kB
packages/nextjs-config/dist/index.mjs 30 B
packages/nextjs-config/dist/strip-sourcemap-********.js 4.91 kB
packages/nextjs-config/dist/strip-sourcemap-********.mjs 2.96 kB
packages/nextjs-config/dist/utils.js 3.93 kB
packages/nextjs-config/dist/utils.mjs 1.72 kB
packages/node/dist/ai-capture/batching.js 2.71 kB
packages/node/dist/ai-capture/batching.mjs 1.21 kB
packages/node/dist/ai-capture/routing.js 1.96 kB
packages/node/dist/ai-capture/routing.mjs 264 B
packages/node/dist/capture-v1/config.js 1.59 kB
packages/node/dist/capture-v1/config.mjs 283 B
packages/node/dist/capture-v1/errors.js 1.99 kB
packages/node/dist/capture-v1/errors.mjs 694 B
packages/node/dist/capture-v1/routing.js 1.77 kB
packages/node/dist/capture-v1/routing.mjs 279 B
packages/node/dist/capture-v1/sender.js 11.5 kB
packages/node/dist/capture-v1/sender.mjs 9.94 kB
packages/node/dist/capture-v1/transform.js 5.22 kB
packages/node/dist/capture-v1/transform.mjs 3.65 kB
packages/node/dist/capture-v1/types.js 585 B
packages/node/dist/capture-v1/types.mjs 12 B
packages/node/dist/entrypoints/index.edge.js 3.66 kB
packages/node/dist/entrypoints/index.edge.mjs 720 B
packages/node/dist/entrypoints/index.node.js 6.45 kB
packages/node/dist/entrypoints/index.node.mjs 1.77 kB
packages/node/dist/entrypoints/nestjs.js 2.27 kB
packages/node/dist/entrypoints/nestjs.mjs 42 B
packages/node/dist/experimental.js 852 B
packages/node/dist/experimental.mjs 279 B
packages/node/dist/exports.js 6.3 kB
packages/node/dist/exports.mjs 388 B
packages/node/dist/extensions/context/context.js 2.22 kB
packages/node/dist/extensions/context/context.mjs 863 B
packages/node/dist/extensions/context/span-context.node.js 1.8 kB
packages/node/dist/extensions/context/span-context.node.mjs 355 B
packages/node/dist/extensions/context/types.js 585 B
packages/node/dist/extensions/context/types.mjs 12 B
packages/node/dist/extensions/error-tracking/autocapture.js 5.29 kB
packages/node/dist/extensions/error-tracking/autocapture.mjs 3.62 kB
packages/node/dist/extensions/error-tracking/index.js 4.48 kB
packages/node/dist/extensions/error-tracking/index.mjs 3.17 kB
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.js 11.7 kB
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs 9.64 kB
packages/node/dist/extensions/error-tracking/modifiers/module.node.js 2.87 kB
packages/node/dist/extensions/error-tracking/modifiers/module.node.mjs 1.45 kB
packages/node/dist/extensions/error-tracking/modifiers/relative-path.node.js 2.07 kB
packages/node/dist/extensions/error-tracking/modifiers/relative-path.node.mjs 624 B
packages/node/dist/extensions/express.js 5.07 kB
packages/node/dist/extensions/express.mjs 2.78 kB
packages/node/dist/extensions/feature-flags/cache.js 585 B
packages/node/dist/extensions/feature-flags/cache.mjs 12 B
packages/node/dist/extensions/feature-flags/crypto.js 1.37 kB
packages/node/dist/extensions/feature-flags/crypto.mjs 42 B
packages/node/dist/extensions/feature-flags/feature-flags.js 32.3 kB
packages/node/dist/extensions/feature-flags/feature-flags.mjs 29.8 kB
packages/node/dist/extensions/nestjs.js 5.71 kB
packages/node/dist/extensions/nestjs.mjs 3.42 kB
packages/node/dist/extensions/sentry-integration.js 4.99 kB
packages/node/dist/extensions/sentry-integration.mjs 3.37 kB
packages/node/dist/extensions/tracing-headers.js 3.41 kB
packages/node/dist/extensions/tracing-headers.mjs 1.53 kB
packages/node/dist/extensions/url-utils.js 2.32 kB
packages/node/dist/extensions/url-utils.mjs 785 B
packages/node/dist/feature-flag-evaluations.js 6.22 kB
packages/node/dist/feature-flag-evaluations.mjs 4.77 kB
packages/node/dist/gzip.node.js 1.83 kB
packages/node/dist/gzip.node.mjs 416 B
packages/node/dist/host-os.node.js 1.8 kB
packages/node/dist/host-os.node.mjs 349 B
packages/node/dist/storage-memory.js 1.61 kB
packages/node/dist/storage-memory.mjs 297 B
packages/node/dist/types.js 1.52 kB
packages/node/dist/types.mjs 224 B
packages/node/dist/version.js 1.31 kB
packages/node/dist/version.mjs 46 B
packages/nuxt/dist/module.mjs 5.92 kB
packages/nuxt/dist/runtime/composables/useFeatureFlagEnabled.js 566 B
packages/nuxt/dist/runtime/composables/useFeatureFlagPayload.js 698 B
packages/nuxt/dist/runtime/composables/useFeatureFlagVariantKey.js 591 B
packages/nuxt/dist/runtime/composables/usePostHog.js 128 B
packages/nuxt/dist/runtime/nitro-plugin-v2.js 480 B
packages/nuxt/dist/runtime/nitro-plugin-v3.js 574 B
packages/nuxt/dist/runtime/nitro-plugin.js 1.03 kB
packages/nuxt/dist/runtime/vue-plugin.js 1.13 kB
packages/openfeature-node-provider/dist/index.js 1.86 kB
packages/openfeature-node-provider/dist/index.mjs 122 B
packages/openfeature-node-provider/dist/mapping.js 5.42 kB
packages/openfeature-node-provider/dist/mapping.mjs 3.21 kB
packages/openfeature-node-provider/dist/provider.js 4.09 kB
packages/openfeature-node-provider/dist/provider.mjs 2.6 kB
packages/openfeature-web-provider/dist/index.js 1.84 kB
packages/openfeature-web-provider/dist/index.mjs 119 B
packages/openfeature-web-provider/dist/mapping.js 5.38 kB
packages/openfeature-web-provider/dist/mapping.mjs 3.18 kB
packages/openfeature-web-provider/dist/provider.js 4.51 kB
packages/openfeature-web-provider/dist/provider.mjs 3.06 kB
packages/plugin-utils/dist/chunk-ids.js 3.96 kB
packages/plugin-utils/dist/chunk-ids.mjs 2.11 kB
packages/plugin-utils/dist/cli.js 4.47 kB
packages/plugin-utils/dist/cli.mjs 2.72 kB
packages/plugin-utils/dist/config.js 3.6 kB
packages/plugin-utils/dist/config.mjs 2.25 kB
packages/plugin-utils/dist/index.js 4.5 kB
packages/plugin-utils/dist/index.mjs 197 B
packages/plugin-utils/dist/spawn-local.js 3.17 kB
packages/plugin-utils/dist/spawn-local.mjs 1.66 kB
packages/plugin-utils/dist/utils.js 3.36 kB
packages/plugin-utils/dist/utils.mjs 1.3 kB
packages/react-native/dist/autocapture.js 8.31 kB
packages/react-native/dist/error-tracking/index.js 9.97 kB
packages/react-native/dist/error-tracking/utils.js 2.58 kB
packages/react-native/dist/frameworks/wix-navigation.js 1.3 kB
packages/react-native/dist/hooks/useFeatureFlag.js 1.86 kB
packages/react-native/dist/hooks/useFeatureFlagResult.js 983 B
packages/react-native/dist/hooks/useFeatureFlags.js 941 B
packages/react-native/dist/hooks/useNavigationTracker.js 2.45 kB
packages/react-native/dist/hooks/usePostHog.js 544 B
packages/react-native/dist/hooks/utils.js 988 B
packages/react-native/dist/index.js 4.33 kB
packages/react-native/dist/logs-********.js 3.66 kB
packages/react-native/dist/native-deps.js 8.73 kB
packages/react-native/dist/optional/OptionalAsyncStorage.js 299 B
packages/react-native/dist/optional/OptionalExpoApplication.js 377 B
packages/react-native/dist/optional/OptionalExpoDevice.js 347 B
packages/react-native/dist/optional/OptionalExpoFileSystem.js 386 B
packages/react-native/dist/optional/OptionalExpoFileSystemLegacy.js 423 B
packages/react-native/dist/optional/OptionalExpoLocalization.js 383 B
packages/react-native/dist/optional/OptionalPlugin.js 1.06 kB
packages/react-native/dist/optional/OptionalReactNativeDeviceInfo.js 415 B
packages/react-native/dist/optional/OptionalReactNativeLocalize.js 303 B
packages/react-native/dist/optional/OptionalReactNativeNavigation.js 415 B
packages/react-native/dist/optional/OptionalReactNativeNavigationWix.js 443 B
packages/react-native/dist/optional/OptionalReactNativeSafeArea.js 644 B
packages/react-native/dist/optional/OptionalReactNativeSvg.js 872 B
packages/react-native/dist/posthog-rn.js 67.4 kB
packages/react-native/dist/PostHogContext.js 329 B
packages/react-native/dist/PostHogErrorBoundary.js 3.19 kB
packages/react-native/dist/PostHogMaskView.js 1.68 kB
packages/react-native/dist/PostHogProvider.js 6 kB
packages/react-native/dist/storage.js 5.76 kB
packages/react-native/dist/surveys/components/BottomSection.js 1.51 kB
packages/react-native/dist/surveys/components/Cancel.js 1.1 kB
packages/react-native/dist/surveys/components/ConfirmationMessage.js 1.76 kB
packages/react-native/dist/surveys/components/IntroMessage.js 1.65 kB
packages/react-native/dist/surveys/components/QuestionHeader.js 1.47 kB
packages/react-native/dist/surveys/components/QuestionTypes.js 14 kB
packages/react-native/dist/surveys/components/SurveyModal.js 7.24 kB
packages/react-native/dist/surveys/components/Surveys.js 6.58 kB
packages/react-native/dist/surveys/getActiveMatchingSurveys.js 2.69 kB
packages/react-native/dist/surveys/icons.js 10 kB
packages/react-native/dist/surveys/index.js 600 B
packages/react-native/dist/surveys/PostHogSurveyProvider.js 6.73 kB
packages/react-native/dist/surveys/safeStyleSheet.js 448 B
packages/react-native/dist/surveys/survey-translations.js 1.11 kB
packages/react-native/dist/surveys/surveys-utils.js 11.5 kB
packages/react-native/dist/surveys/useActivatedSurveys.js 3.68 kB
packages/react-native/dist/surveys/useSurveyStorage.js 2.48 kB
packages/react-native/dist/tooling/expoconfig.js 23.8 kB
packages/react-native/dist/tooling/metroconfig.js 2.32 kB
packages/react-native/dist/tooling/posthogMetroSerializer.js 7.74 kB
packages/react-native/dist/tooling/utils.js 4.2 kB
packages/react-native/dist/tooling/vendor/expo/expoconfig.js 70 B
packages/react-native/dist/tooling/vendor/metro/countLines.js 237 B
packages/react-native/dist/tooling/vendor/metro/utils.js 3.51 kB
packages/react-native/dist/types.js 70 B
packages/react-native/dist/utils.js 1.3 kB
packages/react-native/dist/version.js 130 B
packages/react/dist/esm/index.js 22.1 kB
packages/react/dist/esm/slim/index.js 18.5 kB
packages/react/dist/esm/surveys/index.js 3.61 kB
packages/react/dist/umd/index.js 26.4 kB
packages/react/dist/umd/slim/index.js 22.3 kB
packages/react/dist/umd/surveys/index.js 5.63 kB
packages/rollup-plugin/dist/index.js 10.2 kB
packages/rrweb/all/dist/rrweb-all.cjs 705 kB
packages/rrweb/all/dist/rrweb-all.js 705 kB
packages/rrweb/all/dist/rrweb-all.umd.cjs 709 kB
packages/rrweb/all/dist/rrweb-all.umd.min.cjs 328 kB
packages/rrweb/packer/dist/base-********.cjs 18.3 kB
packages/rrweb/packer/dist/base-********.js 18.2 kB
packages/rrweb/packer/dist/base-********.umd.cjs 18.7 kB
packages/rrweb/packer/dist/base-********.umd.min.cjs 9.5 kB
packages/rrweb/packer/dist/pack.cjs 347 B
packages/rrweb/packer/dist/pack.js 285 B
packages/rrweb/packer/dist/pack.umd.cjs 1.63 kB
packages/rrweb/packer/dist/pack.umd.min.cjs 1.11 kB
packages/rrweb/packer/dist/packer.cjs 257 B
packages/rrweb/packer/dist/packer.js 136 B
packages/rrweb/packer/dist/packer.umd.cjs 662 B
packages/rrweb/packer/dist/packer.umd.min.cjs 626 B
packages/rrweb/packer/dist/unpack.cjs 769 B
packages/rrweb/packer/dist/unpack.js 702 B
packages/rrweb/packer/dist/unpack.umd.cjs 1.17 kB
packages/rrweb/packer/dist/unpack.umd.min.cjs 955 B
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.cjs 37.6 kB
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.js 37.5 kB
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.umd.cjs 38 kB
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.umd.min.cjs 22.2 kB
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.cjs 34.3 kB
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.js 34.2 kB
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.umd.cjs 34.7 kB
packages/rrweb/plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.umd.min.cjs 20.5 kB
packages/rrweb/plugins/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.cjs 15.8 kB
packages/rrweb/plugins/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.js 15.7 kB
packages/rrweb/plugins/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.umd.cjs 16.3 kB
packages/rrweb/plugins/rrweb-plugin-console-record/dist/rrweb-plugin-console-record.umd.min.cjs 7.66 kB
packages/rrweb/plugins/rrweb-plugin-console-replay/dist/rrweb-plugin-console-replay.cjs 5.01 kB
packages/rrweb/plugins/rrweb-plugin-console-replay/dist/rrweb-plugin-console-replay.js 4.9 kB
packages/rrweb/plugins/rrweb-plugin-console-replay/dist/rrweb-plugin-console-replay.umd.cjs 5.44 kB
packages/rrweb/plugins/rrweb-plugin-console-replay/dist/rrweb-plugin-console-replay.umd.min.cjs 2.64 kB
packages/rrweb/plugins/rrweb-plugin-sequential-id-record/dist/rrweb-plugin-sequential-id-record.cjs 681 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-record/dist/rrweb-plugin-sequential-id-record.js 548 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-record/dist/rrweb-plugin-sequential-id-record.umd.cjs 1.12 kB
packages/rrweb/plugins/rrweb-plugin-sequential-id-record/dist/rrweb-plugin-sequential-id-record.umd.min.cjs 829 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-replay/dist/rrweb-plugin-sequential-id-replay.cjs 933 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-replay/dist/rrweb-plugin-sequential-id-replay.js 820 B
packages/rrweb/plugins/rrweb-plugin-sequential-id-replay/dist/rrweb-plugin-sequential-id-replay.umd.cjs 1.37 kB
packages/rrweb/plugins/rrweb-plugin-sequential-id-replay/dist/rrweb-plugin-sequential-id-replay.umd.min.cjs 968 B
packages/rrweb/record/dist/rrweb-record.cjs 234 kB
packages/rrweb/record/dist/rrweb-record.js 233 kB
packages/rrweb/record/dist/rrweb-record.umd.cjs 234 kB
packages/rrweb/record/dist/rrweb-record.umd.min.cjs 107 kB
packages/rrweb/replay/dist/rrweb-replay.cjs 476 kB
packages/rrweb/replay/dist/rrweb-replay.js 476 kB
packages/rrweb/replay/dist/rrweb-replay.umd.cjs 479 kB
packages/rrweb/replay/dist/rrweb-replay.umd.min.cjs 225 kB
packages/rrweb/rrdom-nodejs/dist/rrdom-nodejs.cjs 160 kB
packages/rrweb/rrdom-nodejs/dist/rrdom-nodejs.js 160 kB
packages/rrweb/rrdom-nodejs/dist/rrdom-nodejs.umd.cjs 162 kB
packages/rrweb/rrdom-nodejs/dist/rrdom-nodejs.umd.min.cjs 74.9 kB
packages/rrweb/rrdom/dist/rrdom.cjs 186 kB
packages/rrweb/rrdom/dist/rrdom.js 185 kB
packages/rrweb/rrdom/dist/rrdom.umd.cjs 187 kB
packages/rrweb/rrdom/dist/rrdom.umd.min.cjs 85.5 kB
packages/rrweb/rrweb-snapshot/dist/record.cjs 39 kB
packages/rrweb/rrweb-snapshot/dist/record.js 37.3 kB
packages/rrweb/rrweb-snapshot/dist/record.umd.cjs 83.2 kB
packages/rrweb/rrweb-snapshot/dist/record.umd.min.cjs 37.4 kB
packages/rrweb/rrweb-snapshot/dist/replay.cjs 149 kB
packages/rrweb/rrweb-snapshot/dist/replay.js 149 kB
packages/rrweb/rrweb-snapshot/dist/replay.umd.cjs 194 kB
packages/rrweb/rrweb-snapshot/dist/replay.umd.min.cjs 86.2 kB
packages/rrweb/rrweb-snapshot/dist/rrweb-********.cjs 3.95 kB
packages/rrweb/rrweb-snapshot/dist/rrweb-********.js 2.32 kB
packages/rrweb/rrweb-snapshot/dist/rrweb-********.umd.cjs 261 kB
packages/rrweb/rrweb-snapshot/dist/rrweb-********.umd.min.cjs 109 kB
packages/rrweb/rrweb-snapshot/dist/types-********.cjs 37.6 kB
packages/rrweb/rrweb-snapshot/dist/types-********.js 36.5 kB
packages/rrweb/rrweb-snapshot/dist/types-********.umd.cjs 39 kB
packages/rrweb/rrweb-snapshot/dist/types-********.umd.min.cjs 17.3 kB
packages/rrweb/rrweb/dist/rrweb.cjs 690 kB
packages/rrweb/rrweb/dist/rrweb.js 689 kB
packages/rrweb/rrweb/dist/rrweb.umd.cjs 690 kB
packages/rrweb/rrweb/dist/rrweb.umd.min.cjs 319 kB
packages/rrweb/types/dist/rrweb-types.cjs 5.75 kB
packages/rrweb/types/dist/rrweb-types.js 5.46 kB
packages/rrweb/types/dist/rrweb-types.umd.cjs 6.16 kB
packages/rrweb/types/dist/rrweb-types.umd.min.cjs 2.86 kB
packages/rrweb/utils/dist/rrweb-utils.cjs 7.76 kB
packages/rrweb/utils/dist/rrweb-utils.js 7.3 kB
packages/rrweb/utils/dist/rrweb-utils.umd.cjs 8.24 kB
packages/rrweb/utils/dist/rrweb-utils.umd.min.cjs 4.09 kB
packages/types/dist/capture-log.js 585 B
packages/types/dist/capture-log.mjs 12 B
packages/types/dist/capture-metric.js 1.47 kB
packages/types/dist/capture-metric.mjs 93 B
packages/types/dist/capture.js 585 B
packages/types/dist/capture.mjs 12 B
packages/types/dist/common.js 585 B
packages/types/dist/common.mjs 12 B
packages/types/dist/feature-flags.js 585 B
packages/types/dist/feature-flags.mjs 12 B
packages/types/dist/index.js 1.55 kB
packages/types/dist/index.mjs 75 B
packages/types/dist/posthog-config.js 585 B
packages/types/dist/posthog-config.mjs 12 B
packages/types/dist/posthog.js 585 B
packages/types/dist/posthog.mjs 12 B
packages/types/dist/request.js 585 B
packages/types/dist/request.mjs 12 B
packages/types/dist/segment.js 585 B
packages/types/dist/segment.mjs 12 B
packages/types/dist/session-recording.js 585 B
packages/types/dist/session-recording.mjs 12 B
packages/types/dist/survey.js 585 B
packages/types/dist/survey.mjs 12 B
packages/types/dist/toolbar.js 585 B
packages/types/dist/toolbar.mjs 12 B
packages/types/dist/traces.js 585 B
packages/types/dist/traces.mjs 12 B
packages/types/dist/tree-shakeable.js 585 B
packages/types/dist/tree-shakeable.mjs 12 B
packages/web/dist/index.cjs 8.87 kB
packages/web/dist/index.mjs 8.72 kB
packages/webpack-plugin/dist/config.js 2.38 kB
packages/webpack-plugin/dist/config.mjs 1.31 kB
packages/webpack-plugin/dist/index.js 9.29 kB
packages/webpack-plugin/dist/index.mjs 5.51 kB
tooling/changelog/dist/index.js 3.31 kB
tooling/rollup-utils/dist/index.js 1.17 kB

compressed-size-action

@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from 9d824fd to 2f1c9aa Compare August 21, 2026 12:45
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from 2f1c9aa to 2204f06 Compare August 24, 2026 11:25
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from babae47 to 1d01943 Compare August 28, 2026 18:49
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from 1d01943 to a6d394d Compare August 28, 2026 18:50
@turnipdabeets
turnipdabeets force-pushed the feat/traces-node-mvp branch 3 times, most recently from cc7b6d8 to ce6e01a Compare August 31, 2026 13:58
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from a6d394d to f7df34d Compare August 31, 2026 14:01
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from f7df34d to de9e7cd Compare August 31, 2026 14:13
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from de9e7cd to ea15b7f Compare August 31, 2026 18:01
@turnipdabeets turnipdabeets changed the title feat(node): add a beforeSpanSend hook feat(node): beforeSpanSend hook and per-span limits Aug 31, 2026
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from ea15b7f to 8bfae9e Compare August 31, 2026 18:08
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from 8bfae9e to f628066 Compare August 31, 2026 18:18
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from f628066 to 86bb18e Compare August 31, 2026 18:24
@turnipdabeets
turnipdabeets force-pushed the feat/traces-before-span-send branch from 86bb18e to eb8fda8 Compare August 31, 2026 18:45
@veria-ai

veria-ai Bot commented Sep 3, 2026

Copy link
Copy Markdown

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

orderedKeys tested `key in attributes`, which walks the prototype chain, so an
attribute named `constructor` or `toString` survived the hook deleting it and
read back as the inherited member. At the cap those ghosts took the slots: a
hook returning a scrubbed bag exported ["toString","valueOf"] and dropped the
one attribute it meant to keep.

Three more from the same review:

- The new name bound cut the SDK's own `exception` event name below a bound of
  9, so the reserve stopped recognising it and dropped the event it exists to
  keep. `eventNameBound` floors it, at both sanitize call sites.
- `_startFlush` installed its in-flight slot only after `_flushInner` had run
  its synchronous prefix, which this PR lengthened by bounding the resource
  attributes. A getter there that ends a span re-entered with no pass recorded
  and re-sent the head batch — 3070 times in a probe, not once. The pass now
  starts a microtask later, after the slot is installed.
- A `false` entry from `[featureEnabled && scrub]` no longer reports an inert
  redaction hook, and the maxAttributeValueLength doc lists what it now bounds.
…to HEAD

# Conflicts:
#	packages/core/src/traces/span.ts
The encoder drops a nullish value without charging its budget, so charging one
here made this walk the stricter of the two and broke the invariant the rest of
the walk relies on: a value with 10,000 null leaves ahead of a large string
exhausted this budget while the encoder still had room, and the string shipped
whole — 2 MB under a bound of 8, with no backstop on either side. Nullish leaves
are free again; the shared-subtree cost that charging fixed stays fixed.

Also from the same review:

- `_startFlush` samples the generation before the microtask, so a `reset()` in
  that window marks the pending pass stale rather than letting it drain the
  post-reset queue alongside the pass `reset()` started.
- `orderedKeys` uses `propertyIsEnumerable`, the predicate the encoder itself
  uses, so a key a hook hid by making it non-enumerable cannot take a cap slot.
- The `beforeSpanSend` filter reports only on a value meant to be a hook, so
  `[items.length && scrub]` and `[name && scrub]` are quiet too.
`_flushEventsAndSpans` combined the two flushes with `Promise.all`, which
rejects the moment the event flush does. A serverless host treats the returned
promise as the end of the invocation, so an event endpoint failing mid-request
let the platform freeze the handler with the span POST still open. `allSettled`
waits for both and still surfaces the events rejection to the caller.

`reset()` also discarded whatever was queued without a word, while the only
line the operator had seen was the export failure promising a retry on a flush
that will never come. It now names the count at `critical`, the one level
posthog-node does not gate behind `debug`.
turnipdabeets and others added 2 commits September 3, 2026 14:24
Budget parity was explained in four places; keep it in the function doc. Rewrite
the three changesets as one-line, outcome-first entries.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013ERsAtgPJqKF46yur8bm6K
A drain sends one batch per loop iteration, so the user could opt out
while a batch was in flight and the batches behind it would still export.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L8eFZB35NExUZyq5hGgh43

@dustinbyrne dustinbyrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for the three confirmed correctness issues called out inline. Each is reachable through the public tracing API and was reproduced against 8997a166:

  • stateful toJSON() can bypass maxAttributeValueLength;
  • incomplete hook return values can be exported as malformed spans;
  • fractional numeric options are floored instead of using their documented defaults.

The broader ownership looks sound: live spans enforce limits on write, limits are reapplied after hooks, queue/retry/consent remain in PostHogTraces, and cross-signal flushing remains in PostHogBackendClient.

I also called out one non-blocking chained-hook identity edge and one contract decision concerning the exception-event reserve.

Changeset provenance looks correct: the hook, limit, and stack-trace changesets belong to this PR; the other tracing changesets are inherited from #4579. The branch is currently stacked cleanly and does not need a rebase at the reviewed commit.

Agent-assisted review provenance: Dustin requested an independent review plus changeset and stacking checks without seeding suspected code defects. We discussed the resulting findings and architecture during the review. Dustin has been good to the agent.

Comment thread packages/core/src/traces/span.ts Outdated
Comment thread packages/core/src/traces/index.ts Outdated
Comment thread packages/core/src/traces/config.ts
Comment thread packages/core/src/traces/index.ts
Comment thread packages/types/src/traces.ts Outdated
@dustinbyrne
dustinbyrne dismissed their stale review September 4, 2026 05:19

Reclassifying this review as non-blocking feedback.

@marandaneto
marandaneto requested a review from a team September 4, 2026 07:39

@ioannisj ioannisj left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving to unblock one more review cycle but #4584 (comment) is my finding as well, so worth addressing

turnipdabeets and others added 8 commits September 4, 2026 08:00
Takes #4773's move of resolveTracesConfig into core. The beforeSpanSend
resolver and the three per-span limit knobs move with it; the logger
this PR threads through the resolver stays a core-internal type.
Keeping the object left the encoder to probe toJSON a second time, so a
serializer that answered null under the bound could answer with a megabyte
over it. Stores the string the encoder builds from the same result instead,
which leaves the wire unchanged and gives it nothing left to re-probe.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTHb6UUMhVJSWC2cWBzSxc
Flooring made maxAttributesPerSpan: 1.5 resolve to 1, capping a span an
order of magnitude below what the caller wrote and saying nothing. Every
numeric traces option now falls back the way the spec describes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTHb6UUMhVJSWC2cWBzSxc
Carrying attributes and events was the whole shape check, so a hook
returning only those two exported a span named unknown at a fallback time
with no join keys, silently. A record missing any field the public
SpanRecord requires is now a counted drop, as the rest of the hook
contract already is.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTHb6UUMhVJSWC2cWBzSxc
An earlier hook that forged an id and froze what it returned refused the
restoring writes, so the next hook in the chain sampled on the forged id.
Hands it a corrected view built from the record's own descriptors, which
keeps the prototype and the keys the hook returned.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTHb6UUMhVJSWC2cWBzSxc
The second call is the encoder's, so the guarantee is worth asserting past
the record.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTHb6UUMhVJSWC2cWBzSxc
The reserve is for what the SDK records on your behalf, so an event named
`exception` by the caller was claiming it too. Marks SDK-recorded events
with an internal symbol the hook cannot see and the wire cannot carry, and
keys both enforcement points on that. Removes eventNameBound with it: the
name no longer decides anything, so it no longer needs a floor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTHb6UUMhVJSWC2cWBzSxc
Drops the four reserved slots for exception events. The reserve bought a
case we cannot show occurs — a span holding 128 events that then throws —
at the cost of the most intricate code in this change, which had already
carried one bug. The cap now matches the spec's number exactly.

A span that fills its events and then throws keeps its error status and
reports the loss through droppedEventsCount, so the case is measurable
once traces ships and the reserve can be added back additively if it turns
out to matter.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTHb6UUMhVJSWC2cWBzSxc
turnipdabeets and others added 2 commits September 4, 2026 14:05
Resolves the import conflict in traces/index.ts: keeps this branch's
applySpanLimits and truncateAttributes, and drops NOOP_SPAN, which the
base replaced with inertSpan at the pass-through-parent site so an
inbound context carries to the child.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J1XjgPzJ4zbHBcYmEDymA2
The reserve was removed and the event cap is now absolute, but the
changeset still promised it. Also names the dropped counters, which are
how a caller sees that a span was truncated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J1XjgPzJ4zbHBcYmEDymA2
@turnipdabeets
turnipdabeets merged commit 9d10ad4 into feat/traces-node-mvp Sep 4, 2026
65 checks passed
@turnipdabeets
turnipdabeets deleted the feat/traces-before-span-send branch September 4, 2026 18:45
turnipdabeets added a commit that referenced this pull request Sep 4, 2026
Resolves three conflicts in the traces queue against #4584:

- `_startFlush` keeps the microtask defer and generation sampling, re-arming
  through the ratchet so a flush cannot pull a Retry-After wait forward.
- The two drop paths keep both resets: the consecutive-failure counter and the
  head batch's own budget.
- A batch of one refused for size is now reached from the SDK's own measurement
  as well as a 413, so the drop reason names neither.

Also corrects the body-cap comment #4584 adds: the caps bound a span's
attributes but not how many attributes its events carry, so a span is not
bounded overall.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YE1TyDWGyLwUXEX3ffy83K
turnipdabeets added a commit that referenced this pull request Sep 8, 2026
…tracing

#4584 folded into this branch, so `beforeSpanSend` and the caps go out in the
same minor as `startSpan`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWoFx4BctNmXnpnKS79Qgz
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.

4 participants