Skip to main content
APM is deliberately conservative about what it collects. Two pieces of detail are useful while you are investigating something and risky to leave on forever, so each is a switch that is off by default and can be turned on for a time-boxed window. Code location is different: it is about your code rather than your data, so it is on by default and stays on until you turn it off.

What is collected by default

Without any of these switches:
  • SQL is normalized before it leaves your server. where id = 42 is captured as where id = ?, and the bind values are discarded in-process — they are never transmitted or stored.
  • Redis and cache keys are masked to their shape — user:9f31:profile becomes user:?:profile.
  • Spans do carry the code that started them (see Code location); switching it off removes the location, the function name and the stack from every span.
Operations are grouped by their normalized shape either way, so turning a switch on or off never splits an operation’s history in the Performance analytics.

Statement text is stored only for accounts that opt in

The SDK sends the normalized statement and the caller stack with each span, but ApiTraffic stores and shows them only for accounts with statement text enabled. For every other account they are removed before the request is stored, and removed again whenever a request is read, so the request page, shared links, embeds, workflows, the API and the MCP tools all show the operation, its fingerprint and its code location without the query text. This also applies to the statement as issued and its bind values from Query parameters: that capture only shows anything for an account with statement text enabled. Operators can switch statement text off for every account at once. Requests stored before this rule had text attached; it is withheld on read in the same way. Opting out is final for the text captured until then: when an account turns statement text off, the moment is recorded, and text captured before it (plus a two-minute grace for servers that had not yet seen the change) is never shown again, even if the account later opts back in. Span reports over a window that reaches back before that moment show only the statement text captured since.

Turning capture on for a bucket

1

Open the bucket

Go to Bucket Settings and select the APM Capture tab.
2

Enable what you need

Turn on Collect SQL statements with their parameters and/or Collect concrete Redis and cache keys. Collect the code location that started each operation is already on, with a Stack trace depth of 10 frames.
3

Choose an auto-disable window

Under Auto-Disable, pick 15 minutes, 1 hour, 4 hours, 24 hours, or Until I turn it off. The page then shows the exact time capture stops. The window restarts each time you save, and applies to the parameter and key switches only — never to code location.
4

Save

Connected servers pick the change up immediately over the realtime channel — no restart and no deploy. Reproduce the problem, then let the window expire.
Use these with care. Parameters and concrete keys routinely contain personal data, identifiers, tokens and secrets, and whatever is collected is stored with the request and shown in the waterfall. Your account redactions still apply, and captured values are the first thing dropped when a span exceeds its size budget — but the safest posture is a short window, deliberately opened.

How the window is enforced

The expiry is applied in two independent places, so capture stops on time even if a server never reloads its settings and even if nobody returns to the dashboard:
  • the API stops reporting the switches as enabled on the SDK settings payload once the window passes, and
  • each SDK arms its own timer and returns capture to the defaults at that exact moment.

Turning capture on in the SDK

The same switches exist as SDK options — captureStatementParams, captureRedisKeys, captureCallSite and captureStackDepth, or their API_TRAFFIC_* environment variables. For the two privacy switches the effective setting is local OR bucket: a bucket switch turns capture on for servers that have not enabled it locally, and a locally enabled switch is not turned off when a bucket window expires. Code location and its depth are owned by the bucket unless the application sets them explicitly. Set captureCallSite: false (or captureStackDepth: 1) in code or the environment and that wins everywhere; leave them alone and the dashboard is in charge, including switching capture off. Prefer the bucket settings for production — they are reversible and do not need a deploy.

Code location

A span carries callSite (for example src/services/orders.ts:142:9), callSiteFn, and callStack — the callers above the call site, innermost first — shown in the span details as Code location, Function and Stack trace. The stack is taken when the operation is initiated, because a driver callback runs far from the caller. Frames in Node internals, node_modules and the ApiTraffic packages are skipped, so the depth is spent on the chain through your own code: the route handler that led to the query, not the driver that ran it. Paths are relative to your application root, and transpiled projects report the built file unless source maps are deployed. Frames are read through V8’s structured stack API rather than by formatting and parsing a stack string, which is what makes ten frames affordable as a default: measured per span, ~12 µs for ten frames against ~16 µs for the single-frame string walk this replaced. The cost follows how deep the stack actually is, not the depth you ask for — an operation issued through an ORM under an instrumentation patch has far more library frames to walk past, and costs nearer ~30 µs. Lower the depth if you are counting microseconds on a very hot path — 1 keeps the call site alone — or switch it off entirely, in which case no stack is walked at all rather than walked and discarded. If a span exceeds its metadata budget the outermost frames are dropped first, so the call site always survives. The location is also stored on the span row, so Code Location is available as a grouping in Performance → Operations and not just in a single request. Where a git integration has correlated a deploy to the request, the location links to the file at the exact commit that was running — a permalink, never a branch, so it still points at the right line after the code has moved on.

Managing capture over the API

The switches are fields on the bucket, so they can be driven from CI or a script as well as the dashboard.
boolean
Allow spans to carry full SQL statements and their bind parameters.
boolean
Allow spans to carry concrete Redis and cache keys.
boolean
default:"true"
Whether spans carry the application file, line, function and caller chain that started the operation. false collects none of it.
number
default:"10"
How many application frames to keep per span, innermost first (1–50). 1 keeps the call site alone.
string
ISO 8601 time (UTC) at which the parameter and Redis key switches stop applying. null means they stay on until turned off. Code location is unaffected.
The effective values, after expiry has been applied, are what SDKs receive on their settings payload: