Skip to content

Traces, logs and sensitive data

What the node filters before storing — secrets, headers, query strings, IPs, SQL literals, hashed user ids — and what not to turn on in your instrumentation.

Markdown
On this page

Spans and logs can carry more than you meant to send: a token in a URL, a header copied by an instrumentation, an email in a log line. Belvador filters on your node before anything is stored, but the safest data is data your app never sends.

What your node filters before storing#

The node runs the same scrubber as for errors (see Privacy) over every resource, span, event, link and log record:

  • Secrets by name — attributes such as password, token, api_key, authorization or secret, at any depth, become [Filtered].

  • HTTP headers — header attributes (http.request.header.*, http.response.header.*) are dropped unless they are harmless: content-type, content-length, content-encoding, accept, accept-encoding, accept-language, user-agent, cache-control, x-request-id, traceparent.

  • URLs — user names and passwords are removed from url.full and similar attributes, and query parameters with sensitive names are filtered; url.query is filtered the same way.

  • IP addresses — client and peer addresses are masked (last part of IPv4 zeroed, IPv6 cut to its first 48 bits); public IPv4 addresses inside log bodies and other text are masked the same way, while private and loopback addresses stay readable.

  • User ids — user.id and enduser.id are replaced by a salted hash, so you can still count and group by user.

  • SQL — string and number literals in db.query.text (and the older db.statement) become ?.

  • Size — over-long values are cut and end with …[truncated]; the limits say where.

These follow the project's Data protection settings: if an owner turns a group off there, that kind of value is stored as sent.

What not to turn on#

OpenTelemetry instrumentations capture little by default. Leave these off unless you have a reason and have checked the data:

  • request and response headers (OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_*, OTEL_INSTRUMENTATION_HTTP_*_HEADERS and similar),

  • request and response bodies,

  • database parameter values,

  • GenAI prompt and completion content (OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT and similar),

  • the Node.js process resource detector, which copies the full command line into every span — the Node.js recipe leaves it out.

Log lines#

Log bodies are free text. The node filters secret-looking values in structured attributes and known token patterns, but it cannot know that a sentence contains a customer's address. Log identifiers, not personal data, and prefer structured fields (logger.info({ orderId }, "paid")) so filtering rules can see names.

Where it lives#

Spans and log records are stored only on your node and kept for the retention you set (see Sampling and cost). Belvador's edge handles each request in transit and, while your node is offline, keeps it encrypted to your node's key; Belvador's database receives only metadata such as service names, SDK names and counts.

Posts on this topic

All posts

Spotted something wrong or missing? Tell us: hello@belvador.dev