Observability¶
Anonymizer keeps local run measurement in the anonymizer.measurement package.
Measurement hooks record timings, counts, model-call summaries, and safety
metrics without changing anonymization behavior. Benchmark tools convert those
records into tables for latency, reliability, model usage, and quality analysis.
Measurement is separate from anonymous NVIDIA telemetry. Telemetry can report one product event per run or preview. Users can opt out as described in Telemetry and Privacy. Measurement records are local artifacts. They are written only when developer tooling or caller code activates a measurement session.
Model¶
Instrumentation is passive unless a MeasurementCollector is active in the
current context:
from anonymizer.measurement import MeasurementConfig, configured_measurement_session
measurement = MeasurementConfig(output_path="benchmark-runs/case/measurements.jsonl")
with configured_measurement_session(measurement):
result = anonymizer.run(config=config, data=data)
Instrumentation uses these entry points:
stage_timer(...)wraps pipeline phases and records elapsed time.record_run_metadata(...)records config, input, model, and runtime metadata once per run, without raw source values.record_record_metrics(...)records per-row counts and safety metrics from the trace DataFrame.record_ndd_workflow(...)records DataDesigner workflow summaries at theNddAdapterboundary.record_model_workflow(...)records benchmark-only direct model calls that do not use DataDesigner. Its optionalextra_fieldsmapping remains part of the local measurement artifact underlocal_fields. W&B ingress validates and drops that explicit object before constructing an outbound payload; unknown top-level fields remain schema errors.
The public API and CLI do not read measurement environment variables by default. Benchmark and developer tools opt into measurement explicitly.
Record Types¶
Measurement output is JSONL by default. Each row has a record_type and shared
run metadata.
| Record type | Meaning |
|---|---|
run |
One anonymization call: mode, strategy, input shape, config metadata, model aliases, runtime metadata. |
stage |
Pipeline phase timing, status, row counts, and row throughput. |
record |
Per-input-row counts, text-length buckets, entity counts, ground-truth comparison metrics when present, replacement coverage, leakage flags, and estimated LLM calls. |
ndd_workflow |
DataDesigner workflow summary: workflow name, model aliases, row counts, failures, elapsed time, usage summary, and throughput. |
model_workflow |
Direct model workflow summary for benchmark-only paths outside DataDesigner. |
dd_trace_coverage |
Trace coverage summary for DataDesigner columns when message tracing is enabled. |
Use tools/measurement/export_measurements.py to convert raw measurement JSONL
into Parquet, CSV, or JSONL tables.
Output and Sinks¶
MeasurementConfig controls output:
| Field | Purpose |
|---|---|
output_path |
Destination for measurement records. |
output_format |
jsonl or json; defaults to jsonl. |
record_level |
Include per-row record entries; defaults to True. |
streaming |
Write JSONL records as they are emitted instead of collecting them in memory. |
keep_records |
Keep emitted records in memory for caller access. |
run_id |
Optional stable run ID. |
run_tags |
Caller-supplied tags copied to every record. |
fail_on_write_error |
Raise output write/close failures when the run body succeeded. |
Streaming mode supports JSONL only. Use it for long benchmark suites where holding all measurement records in memory is unnecessary.
MeasurementConfig.from_env() can read ANONYMIZER_MEASUREMENT_* settings for
developer tooling. Product entry points do not call it automatically.
| Environment variable | Field |
|---|---|
ANONYMIZER_MEASUREMENT_OUTPUT_PATH |
output_path |
ANONYMIZER_MEASUREMENT_OUTPUT_FORMAT |
output_format |
ANONYMIZER_MEASUREMENT_RECORD_LEVEL |
record_level |
ANONYMIZER_MEASUREMENT_STREAMING |
streaming |
ANONYMIZER_MEASUREMENT_KEEP_RECORDS |
keep_records |
ANONYMIZER_MEASUREMENT_DD_TRACE |
dd_trace |
ANONYMIZER_MEASUREMENT_DD_TRACE_PATH |
dd_trace_path |
ANONYMIZER_MEASUREMENT_DD_TASK_TRACE_PATH |
dd_task_trace_path |
ANONYMIZER_MEASUREMENT_FAIL_ON_WRITE_ERROR |
fail_on_write_error |
ANONYMIZER_MEASUREMENT_RUN_ID |
run_id |
ANONYMIZER_MEASUREMENT_RUN_TAGS |
run_tags |
W&B Benchmark Logging¶
Benchmark runs can export sanitized measurement summaries to Weights & Biases (W&B). Only benchmark tooling starts W&B runs; the Anonymizer SDK and product CLI do not.
W&B benchmark logging is disabled by default. Enable it with
--wandb-mode offline or --wandb-mode online when running a benchmark suite:
uv run python tools/measurement/run_benchmarks.py suite.yaml --wandb-mode online
The runner uploads aggregate benchmark and measurement scalar fields by
default. --wandb-log-tables also uploads tables built from strict row models.
The native publisher parses its bounded JSONL snapshot once and does not use
Pandas for W&B tables. Strict outbound models cover run config, scalar metrics,
and each table row family. The W&B integration disables console, code, Git,
machine metadata, system statistics, requirements capture, and SDK error
reporting. Self-hosted remote endpoints require HTTPS; plain HTTP is accepted
only for loopback development endpoints. Online runs use W&B's local credential
files through the preserved home directory. The publisher removes
WANDB_API_KEY and other environment credentials before importing the SDK.
Outbound models exclude raw text, prompts, model responses, replacement maps,
entity payloads,
DataDesigner trace records, local paths, URLs, provider payloads, and suite
run_tags. Use W&B-specific CLI tags for metadata that should leave the
benchmark environment.
Suite, workload, and config identifiers, Git branch names, and W&B routing fields are visible metadata. Do not place customer data or other sensitive information in these values.
The runner stages W&B files under <benchmark-output>/.wandb-private with
owner-only permissions. Descriptor-relative traversal rejects symlinks and
untrusted writable directories. Root-owned, group-writable project directories
are trusted shared-storage ancestors, but the final benchmark output and W&B
staging directories must be owned by the current user. Offline runs retain this
directory for later sync.
The main goal is benchmark data in W&B. Workspaces, reports, project views, and panels are presentation layers. They can be edited in W&B, regenerated with the benchmark tooling, or replaced when a new benchmark question needs a different view.
Use tools/measurement/create_wandb_report.py --workspace to create a manual
W&B benchmark workspace for a project or benchmark run group. The workspace
organizes focused panels for benchmark summary, privacy, utility,
cost/throughput, sweep comparison, and sanitized measurement tables when
present. The same utility can still create W&B benchmark reports for one
benchmark run or a benchmark run group.
The report reader accepts historical v1 and current v2 metadata through closed run-view models. It uses suite, sweep-arm, or imported-config comparison axes according to the declared run kind and rejects mixed-kind groups. Renderers escape every dynamic Markdown context, reconstruct run URLs from validated W&B identifiers, and reject SDK URLs outside the configured origin or containing terminal control characters.
Use tools/measurement/sweep_benchmarks.py for parameter sweeps. It runs one
benchmark suite per sweep arm and publishes validated sweep identity and safe
parameter fields in W&B benchmark config. --create-workspace and
--create-report validate the remote group as one sweep before creating a
view. A report or workspace service failure is recorded separately on the
returned sweep result, preserves all completed arm results, and causes the CLI
to exit nonzero instead of classifying the outage as bad input.
See tools/measurement/README.md for the full command reference.
External Slurm cases use a per-case completion-seal.json. The producer writes
the seal atomically after the measurement writer closes. The seal records the
measurement digest, byte and record counts, run ID, case identity, Slurm
provenance, and producer commit. Seal creation and import share the same
completed-run invariant and require every record's reserved case tags to match
the seal identity. write_completion_seal.py owns the producer contract;
import_wandb_run.py captures and verifies the sealed JSONL before a strict W&B
publication. Root-owned, group-writable project directories are trusted
shared-storage ancestors for seal writes, but the final case directory must be
owned by the current user. Identical completed imports reuse a
destination-scoped run ID with resume="allow" and become no-ops. Changed
sealed content receives a different run ID.
Local and Slurm Benchmark Execution¶
Benchmark observability treats local execution and Slurm execution as backends
that produce the same measurement artifacts. The shared execution metadata helper
records sanitized context such as backend, hashed output directory, export
flags, DataDesigner trace flags, and selected Slurm job/array counters when
SLURM_* variables are present.
Slurm does not own measurement aggregation or W&B logging. A Slurm launcher may
run one or many benchmark cases, but benchmark Python should still combine
measurement JSONL, export tables, log sanitized W&B summaries, and finish W&B
runs through the benchmark tooling path. Do not add cluster-specific sbatch or
srun scripts to this repository for observability.
DataDesigner Message Traces¶
DataDesigner message traces are optional sidecar artifacts for model-call debugging:
measurement = MeasurementConfig(
output_path="benchmark-runs/case/measurements.jsonl",
dd_trace="last_message",
dd_trace_path="benchmark-runs/case/traces.jsonl",
)
last_message stores the final prompt message for each traced DataDesigner
model call. all_messages stores the full message list.
Message traces are separate from measurement records. They may contain raw input text, prompts, generated output, entity values, replacement values, secrets, and PII. Do not share them unless they have been reviewed or redacted.
Anonymizer requests standard LLM-column traces through DataDesigner native LLM
column trace side effects. That covers LLMTextColumnConfig and
LLMStructuredColumnConfig.
Model-backed CustomColumnConfig generator functions use a temporary
Anonymizer shim that instruments the per-run DataDesigner model registry and
returned model facades. This captures model calls that DataDesigner does not yet
expose through a public trace sink. Treat this as a brittle bridge over private
DataDesigner internals, not as a stable integration point.
When tracing is enabled, the measurement stream records a dd_trace_coverage
row with native, private-facade, and unsupported column counts so benchmark
analysis can see which trace path covered each workflow.
DataDesigner Task Traces¶
Scheduler task traces are a separate sidecar:
measurement = MeasurementConfig(
output_path="benchmark-runs/case/measurements.jsonl",
dd_task_trace_path="benchmark-runs/case/task-traces.jsonl",
)
Task traces capture DataDesigner scheduler timing metadata: workflow, column, row group, row index, task type, status, relative dispatch/slot-acquired/ completion offsets, queue wait time, execution time, total time, and whether an error was present. They do not store raw DataDesigner error strings because those strings can contain prompts, outputs, or source values.
Offsets are relative to the earliest positive dispatched_at timestamp in the
task-trace batch for that workflow. They make task overlap easier to inspect
without persisting host-specific wall-clock timestamps.
Safety Rules¶
Measurement records must not contain raw text, entity values, prompts, generated outputs, replacement maps, provider secrets, or API keys.
Use counts, labels, lengths, buckets, model aliases, status flags, elapsed time, token counts, request counts, and run-scoped HMACs instead. The collector hashes record identity with a per-run key. Record hashes can join artifacts from one run, but they are not stable identifiers across unrelated runs unless the caller supplies the same hash key deliberately.
When adding instrumentation:
- Put timing around stable phase boundaries, not every helper call.
- Record metadata at the boundary where the information is known.
- Keep raw debug payloads in explicit sidecars, never in measurement records.
- Prefer
run_tagsfor external run context such as source refs, CI IDs, topology labels, or experimental strategy. The benchmark runner ownssuite_id,case_id,workload_id,config_id, andrepetition. - Keep benchmark-only strategy switches in
tools/measurement, not product defaults.
Key Files¶
| File | Purpose |
|---|---|
src/anonymizer/measurement/ |
Collector, config, context managers, safe record builders, and trace sidecar hooks. |
src/anonymizer/measurement/fields.py |
Canonical scalar field groups shared with measurement exporters. |
src/anonymizer/interface/anonymizer.py |
Run-level and per-record measurement integration. |
src/anonymizer/engine/ndd/adapter.py |
DataDesigner workflow measurement, native message trace capture, and scheduler task trace capture. |
tools/measurement/run_benchmarks.py |
Benchmark suite runner that activates measurement sessions and writes per-case artifacts. |
tools/measurement/measurement_tools/execution.py |
Sanitized local/Slurm execution metadata shared by benchmark tools. |
tools/measurement/measurement_tools/wandb_completion.py |
Typed completion-seal construction, atomic writes, and digest verification. |
tools/measurement/measurement_tools/wandb_ingress.py |
Bounded descriptor-based capture and strict measurement parsing. |
tools/measurement/measurement_tools/wandb_metric_schema.py |
Shared W&B metric naming and scalar aggregation policy. |
tools/measurement/measurement_tools/wandb_report_models.py |
Closed v1/v2 report views and explicit comparison axes. |
tools/measurement/measurement_tools/wandb_setup.py |
Resolved W&B settings, environment isolation, SDK lifecycle, and staging. |
tools/measurement/create_wandb_report.py |
Typed W&B benchmark workspace and report builder. |
tools/measurement/import_wandb_run.py |
Strict stable import of one sealed external case. |
tools/measurement/sweep_benchmarks.py |
Parameter sweep runner that logs one W&B benchmark run per sweep arm. |
tools/measurement/README.md |
Detailed benchmark and analysis command reference. |