Privacy
Consent decides whether a record is collected; the privacy rules decide what is in it. They run before a record is queued - in the browser script and in the .NET pipeline alike - so secrets in URLs, e-mail addresses in error messages and card numbers in logs are gone before anything leaves the device or the process. The defaults are on; most apps only ever add to them.
See it happen
Each button below makes a real request, or throws a real error, carrying something that must not be recorded. Open a record in the feed to see what was actually exported: the server received the original URL, the telemetry did not.
| The page used | The telemetry carries |
|---|---|
/api/demo/echo?token=secret&[email protected]&q=ok | .../api/demo/echo?token=REDACTED&email=REDACTED&q=ok |
/api/demo/[email protected]&from=203.0.113.7 | .../api/demo/echo?q=[email]&from=[ip] |
/api/demo/echo#access_token=abc123&token_type=bearer | .../api/demo/echo |
Payment failed for [email protected] with card 4111 1111 1111 1111 | Payment failed for [email] with card [card] |
Nothing yet - press a button, then open the record and read its url.full or exception.message.
Query parameters
The values of the parameters in RedactQueryParameters are replaced with REDACTED in
every URL attribute (url.full, page.referrer, ...), matched case-insensitively and
after URL decoding. The parameter stays, so a dashboard can still tell the requests apart. The default list:
StripQueryString (off) drops the query entirely, for apps whose query strings are mostly
personal. StripFragment (on) drops the #... part, because OAuth implicit and hybrid
flows return tokens there; with it off, parameters in the fragment are redacted like the query's.
builder.Services.AddBitBelemetryServices(options =>
{
// Add your own parameter names to the defaults.
options.Privacy.RedactQueryParameters.Add("customerId");
options.Privacy.RedactQueryParameters.Add("invite");
options.Privacy.StripQueryString = false; // the default; true drops every query string
options.Privacy.StripFragment = true; // the default
});Pattern scrubbing
With ScrubPatterns (on) these patterns are replaced wherever free text can carry them - log
bodies, exception messages and stack traces, span status messages and URLs. In the browser every string
attribute is scrubbed (the session and user ids excepted); on the .NET side, the URL attributes,
exception.message, exception.stacktrace, url.query and the log body.
| Pattern | Becomes | Notes |
|---|---|---|
| E-mail addresses | [email] | name@domain.tld |
| JSON Web Tokens | [jwt] | Three base64url segments starting with eyJ |
| Bearer tokens | Bearer [token] | Bearer followed by a token, case-insensitive |
| Payment card numbers | [card] | 13 to 19 digits, optionally grouped with spaces or dashes, and only when the Luhn checksum holds - so order numbers and timestamps survive |
| IPv4 addresses | [ip] | Except after Version=, so .NET assembly versions in stack traces stay readable, and except the host of a URL and server.address: they name the server that was called, not the user |
Scrubbing is a safety net, not a design: a value you know is personal should never be logged in the first place, and structured attributes you control are better removed by name (below) than by pattern.
Blocked attributes and the user agent
BlockedAttributes removes attributes by exact key from every record and span event, on both
sides: the browser script gets the list in its configuration, and the .NET pipeline applies it to its own
logs and spans, IBelemetry calls, and browser records relayed to it. Use a
processor on the .NET side for anything more selective.
CollectUserAgent (on) puts the browser's user agent string in the browser resource as
user_agent.original. Turn it off to keep only the coarse browser.* attributes
(language, platform, mobile, brands). On Azure Monitor, MaskIp (on) keeps the ingestion service
from deriving a location from the client IP; Belemetry never records the client IP itself.
builder.Services.AddBitBelemetryServices(options =>
{
options.Privacy.ScrubPatterns = true; // the default
options.Privacy.BlockedAttributes.Add("client.address"); // exact keys, browser and .NET
options.Privacy.CollectUserAgent = false; // drop user_agent.original
});API
BelemetryPrivacyOptions
Class
Data-minimization rules applied to every record, on both the browser and the .NET side, before it is queued.
| Name | Type and default | Description |
|---|---|---|
RedactQueryParameters |
List<string>= ["token", "code", "password", "pwd", "secret", "key", "apikey", "api_key", "auth", "authorization", "session", "sid", "sig", "signature", "email", "access_token", "id_token", "refresh_token"] |
Query-string parameters (case-insensitive) whose values are replaced with REDACTED in every URL attribute. |
StripQueryString |
bool= false |
Whether to drop query strings from URLs entirely. Defaults to false. |
StripFragment |
bool= true |
Whether to drop URL fragments (which may carry OAuth tokens). Defaults to true. |
ScrubPatterns |
bool= true |
Whether messages, stack traces and URLs are scrubbed of e-mail addresses, JWTs, bearer tokens, card numbers (Luhn-checked) and IPv4 addresses. Defaults to true. |
CollectUserAgent |
bool= true |
Whether the browser's user agent string is part of the browser resource. Defaults to true. |
BlockedAttributes |
List<string>= [] |
Attribute keys removed from every record (exact match). |