VEXLO_SPOOL_DIR, and access to the web UI.
Run the checks on the test service without an additional policy reduction. A restrictive
service policy can suppress the records or logs expected by these checks.
Python SDK covers installation and queue configuration.
Verify field, message and log capture
Use a separate test shell and clear capture settings inherited from earlier experiments:VEXLO_SPOOL_DIR set to the test relay’s queue. The comparisons start from the SDK’s
defaults; each run below changes only the setting it names. Do this in the test shell, not
the environment running your production service.
Save the following as capture_check.py. It passes a synthetic credential under the argument
name token, then includes that same value in formatted exception and log text. The script’s
--logs option sets the SDK’s capture_logs argument; it is not a Vexlo binary option.
case_id; use that ID to find the
new trace in the UI’s home search. Open the record call, select Input, Error or
Logs, and choose fetch full value where available. Inspect full values as well as
previews before drawing a conclusion about what was captured.
Every run retains its
case_id tag and reports builtins.ValueError on the attempt. With
message capture off, the captured stack remains available. Turning off value capture removes
that error detail but preserves the error class in the call record. Turning off Vexlo log
capture does not suppress the application’s own logging output.
Withhold values by field name
redact_keys matches whole string keys in bound arguments and nested dictionaries. It also
applies to declared and runtime tags. Passing a list replaces the defaults; to add a name,
use redact_keys=[*vexlo.DEFAULT_REDACT_KEYS, "email"] in init().
Each configured name matches as written, plus its lowercase, uppercase and capitalized
spellings.
authorization covers Authorization and AUTHORIZATION. api_key does not cover
apiKey, Api_Key, Api-Key or X-Api-Key; password does not cover user_password.
Add the actual spellings your application receives.
The rule examines names, not value contents. It cannot identify a credential returned under
an unrelated name, inside an already formatted string, or in an unnamed positional argument.
A matched dictionary value is not walked; object adapters can execute conversion code before
that dictionary exists.
Tags are indexed in clear text. A name cannot appear in both tag_keys and redact_keys:
init() rejects that conflict. A runtime tag() pair with a redacted name is dropped and
increments diagnostics().redacted_tags.
Control exception messages and logs
capture_error_message=False, or VEXLO_CAPTURE_ERROR_MESSAGE=0, withholds the entire message
and avoids calling str(exc) for capture. The exception class and stack remain recorded when
value capture is enabled. Stack frames contain the file name, line number and function name;
they omit the source line and directory prefix.
capture_logs=True installs one handler on the root logger without changing logging levels
or the application’s existing handlers. If application logging filters a record or stops its
propagation before the root handler, Vexlo does not capture it. Logs belong to the innermost
recorded call: a marked
child receives its own logs. Captured messages use getMessage(), so formatting can execute
application code. Name rules cannot filter the text that formatting produces.
Log capture is bounded at 100 entries per attempt, 4 KiB per formatted message and 16 KiB per
logs value. See Python API for all bounds.
Control custom-object conversion
Adapters convert dataclass fields, namedtuple_asdict() results and Pydantic-style
model_dump() results into captured fields. They are on by default. Those reads and methods
are application code: they can perform work or access lazily loaded state. A failed conversion
falls back to the type name and increments diagnostics().adapter_errors.
Set adapters=False, or VEXLO_ADAPTERS=0, to disable conversions. Unrecognized objects then
record their type name instead of fields. Save this as adapter_example.py to compare field
capture with type-only capture:
model_dump() once and captured label. The second made no conversion
call and recorded the object’s type. The value-walk deadline does not interrupt a slow
conversion. Disabling adapters does not disable exception-message or log formatting.
Disable input, output and error values
capture_values=False, or VEXLO_CAPTURE_VALUES=0, skips their value-capture walk. Relevant
slots report not_captured. Function names, call relationships, timing and error classes
remain available. Tags and captured logs are separate paths and remain enabled if configured.
Without captured input, inferred retry matching has no fingerprint. Use
@vexlo.step(retries=True) for declared grouping when value capture is disabled.
Use sampling for volume control
Sampling controls retention of captured value bytes, not the capture work itself. A sampled-out value still carries a preview and capture metadata. Failed attempts retain their captured values at every sample rate, subject to capture controls and delivery limits. Disabling value capture and setting the sample rate to zero therefore have different effects. Using the same check, compare a successful and failed root at a zero sample rate:sampled_out. The failed run retains a full error value containing its credential.
Neither sampling nor name matching is a filter for arbitrary text. Sampling also leaves the
input capture used for inferred retry grouping intact.
A capture state describes the capture decision, not a guarantee about readable bytes now.
Read the value response before
interpreting availability.
Service policy
The SDK combines local configuration with a service policy refreshed by the local writer. Localinit() values are ceilings: policy can reduce capture but cannot enable a setting
disabled there. The administrative interface and the SDK reader support different fields:
The SDK checks for policy changes at most once a second. Missing or unreadable files, invalid
JSON, a missing or malformed
updated_at, or a policy older than 300 seconds restore the
initialization settings. They do not preserve the last remote restriction. A valid policy
with enabled: false suppressed recording in the captured check; missing, stale and malformed
policies restored local capture. A policy byte limit of 32 did not constrain the captured
input to 32 bytes.
Put required data-handling restrictions in application configuration. Remote policy is a
runtime reduction, not a durable privacy lock. Calls already in progress can finish using
the configuration selected at entry. Policy changes also do not remove previously captured
data. See Configuration for policy administration
and Retention for stored data.