ForgeOpsTracker.StrictPrivacy (forge_ops_tracker v0.17.0)

Copy Markdown View Source

Strict privacy (Configuration.t/0's strict_privacy) is for apps that can't let personal or health data leave their own servers: an event carries only structured facts (the error's type, its stack frames, release, environment, server, which route it happened in), never free text a person could have typed. The rules, and the vectors every client's tests check against, are in this repo's sdks/STRICT_PRIVACY.md; the server applies the same rules again on arrival (app/services/strict_privacy.rb) when the project's own Strict privacy setting is on.

Summary

Functions

An error event's payload (ForgeOpsTracker.EventBuilder.build/7's shape) reduced to what strict privacy sends: "message" is "" and "message_fingerprint" is added; breadcrumbs, endpoint, SQL statement and source context are dropped; a raw-path "transaction_name" loses its ids (see transaction_name/1); context and tags keep only allowed_fields keys with plain values (left out when nothing is left); the user keeps only its id.

The first 32 hex characters of the SHA-256 of normalize_message/1's UTF-8 bytes: lets ForgeOps group errors whose messages differ only in ids, without the message being sent.

The message with hex object ids, UUIDs and standalone numbers replaced, in that order: "0x" plus 4 or more hex digits becomes "0x", a UUID becomes "<uuid>" and a run of digits becomes "<n>", the last two only where no ASCII word character touches them.

A path with its query and fragment dropped and every segment that holds an ASCII digit, or is longer than 40 characters, replaced by ":id": "/patients/42/notes?q=x" is "/patients/:id/notes". An empty result is "/".

One finished span under strict privacy: its name per span_name/1, and its data reduced to "db.statement" and "db.system" (left out when neither is there).

A span's name under strict privacy: an outbound call keeps its method and host ("GET https://api.example.com/patients/42?x=1" is "GET api.example.com"), a request named by its path loses the ids in it ("GET /patients/42/notes" is "GET /patients/:id/notes"), so does a bare path ("/patients/42" is "/patients/:id"), and any other name ("OrdersController#create") is kept.

A transaction name under strict privacy: a route or a controller action is kept, but a raw path loses its ids, by the same rule as span_name/1. A blank name is returned as it is.

Functions

event(payload, allowed_fields)

@spec event(map(), [String.t()]) :: map()

An error event's payload (ForgeOpsTracker.EventBuilder.build/7's shape) reduced to what strict privacy sends: "message" is "" and "message_fingerprint" is added; breadcrumbs, endpoint, SQL statement and source context are dropped; a raw-path "transaction_name" loses its ids (see transaction_name/1); context and tags keep only allowed_fields keys with plain values (left out when nothing is left); the user keeps only its id.

message_fingerprint(message)

@spec message_fingerprint(String.t() | nil) :: String.t()

The first 32 hex characters of the SHA-256 of normalize_message/1's UTF-8 bytes: lets ForgeOps group errors whose messages differ only in ids, without the message being sent.

normalize_message(message)

@spec normalize_message(String.t() | nil) :: String.t()

The message with hex object ids, UUIDs and standalone numbers replaced, in that order: "0x" plus 4 or more hex digits becomes "0x", a UUID becomes "<uuid>" and a run of digits becomes "<n>", the last two only where no ASCII word character touches them.

path_without_ids(path)

@spec path_without_ids(String.t() | nil) :: String.t()

A path with its query and fragment dropped and every segment that holds an ASCII digit, or is longer than 40 characters, replaced by ":id": "/patients/42/notes?q=x" is "/patients/:id/notes". An empty result is "/".

span(span)

@spec span(map()) :: map()

One finished span under strict privacy: its name per span_name/1, and its data reduced to "db.statement" and "db.system" (left out when neither is there).

span_name(name)

@spec span_name(String.t()) :: String.t()

A span's name under strict privacy: an outbound call keeps its method and host ("GET https://api.example.com/patients/42?x=1" is "GET api.example.com"), a request named by its path loses the ids in it ("GET /patients/42/notes" is "GET /patients/:id/notes"), so does a bare path ("/patients/42" is "/patients/:id"), and any other name ("OrdersController#create") is kept.

transaction_name(name)

@spec transaction_name(String.t() | nil) :: String.t() | nil

A transaction name under strict privacy: a route or a controller action is kept, but a raw path loses its ids, by the same rule as span_name/1. A blank name is returned as it is.