Skip to content

Commit f42d292

Browse files
authored
Add - formatting option for redacted values (#11383)
### Related * Follow-up of #11278. ### What This PR allows you to use the minus sign (`-`) formatting option in most `RecordBatch`-derived structs to get a string that has non-deterministic values redacted. Usage: ```rs let chunk = Chunk::new(/* ... */); println!("{chunk:-}"); ``` Using `#` instead of `-` would be an alternative, but I think it's better to reserve this for a more meaningful representation.
1 parent ecf8dd0 commit f42d292

File tree

11 files changed

+37
-90
lines changed

11 files changed

+37
-90
lines changed

CODE_STYLE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ Use debug-formatting (`{:?}`) when logging strings in logs and error messages. T
131131

132132
Use `re_error::format(err)` when displaying an error.
133133

134+
We make extensive use of snapshot testing. To work around non-deterministic values, such as TUIDs (time-prefixed unique IDs), many types (should) offer `std::fmt::Display` implementations with redactions that can be access via an overloaded `-` formatting option:
135+
136+
```rs
137+
println!("{:-}, value"); // The `-` option stands for redaction.
138+
```
139+
134140

135141
## C++
136142
We use `clang-format` to enforce most style choices (see [`.clang-format`](.clang-format)).

Cargo.lock

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8984,7 +8984,6 @@ dependencies = [
89848984
"mcap",
89858985
"prost-reflect",
89868986
"re_chunk",
8987-
"re_format_arrow",
89888987
"re_log",
89898988
"re_log_types",
89908989
"re_tracing",

crates/store/re_chunk/src/chunk.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ impl std::fmt::Display for Chunk {
12471247
re_log::error_once!("couldn't display Chunk: {err}");
12481248
std::fmt::Error
12491249
})?;
1250-
re_format_arrow::format_record_batch_with_width(&batch, f.width()).fmt(f)
1250+
re_format_arrow::format_record_batch_with_width(&batch, f.width(), f.sign_minus()).fmt(f)
12511251
}
12521252
}
12531253

crates/store/re_chunk/tests/formatting.rs

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,40 +55,11 @@ fn format_chunk() -> anyhow::Result<()> {
5555
Ok(())
5656
}
5757

58-
/// Wrapper struct to help with `insta` snapshot tests.
59-
struct ChunkRedacted(Chunk);
60-
61-
impl std::fmt::Display for ChunkRedacted {
62-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63-
let batch = self.0.to_record_batch().map_err(|err| {
64-
re_log::error_once!("couldn't display Chunk: {err}");
65-
std::fmt::Error
66-
})?;
67-
re_format_arrow::format_record_batch_opts(
68-
&batch,
69-
&re_format_arrow::RecordBatchFormatOpts {
70-
transposed: false,
71-
width: f.width(),
72-
include_metadata: true,
73-
include_column_metadata: true,
74-
trim_field_names: false,
75-
trim_metadata_keys: false,
76-
trim_metadata_values: false,
77-
redact_non_deterministic: true,
78-
},
79-
)
80-
.fmt(f)
81-
}
82-
}
83-
8458
#[test]
8559
fn format_chunk_redacted() -> anyhow::Result<()> {
8660
let chunk = create_chunk()?;
8761

88-
insta::assert_snapshot!(
89-
"format_chunk_redacted",
90-
format!("{:240}", ChunkRedacted(chunk))
91-
);
62+
insta::assert_snapshot!("format_chunk_redacted", format!("{:-240}", chunk));
9263

9364
Ok(())
9465
}
Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
---
22
source: crates/store/re_chunk/tests/formatting.rs
3-
expression: "format!(\"{:240}\", ChunkRedacted(chunk))"
3+
expression: "format!(\"{:-240}\", chunk)"
44
---
5-
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
6-
METADATA:
7-
* rerun:entity_path: /this/that
8-
* rerun:heap_size_bytes: [**REDACTED**]
9-
* rerun:id: [**REDACTED**]
10-
* sorbet:version: [**REDACTED**]
11-
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
12-
│ ┌──────────────────────────────────────────────┬────────────────────────────┬───────────────────────────────┬───────────────────────────────────────┬──────────────────────────────────────────┐ │
13-
│ │ rerun.controls.RowId frame_nr log_time my_index example.MyPoints:colors │ │
14-
│ │ ------ ------ --- │ │
15-
│ │ type: FixedSizeBinary[16] ┆ type: nullable i64 type: nullable Timestamp(ns) ┆ type: nullable List[nullable u64] type: nullable List[nullable u32] │ │
16-
│ │ ARROW:extension:metadata: ┆ rerun:index_name: frame_nrrerun:index_name: log_time rerun:component: my_index rerun:archetype: example.MyPoints │ │
17-
│ │ {"namespace":"row"} ┆ rerun:is_sorted: truererun:is_sorted: true rerun:component_type: example.MyIndex rerun:component: example.MyPoints:colors │ │
18-
│ │ ARROW:extension:name: rerun.datatypes.TUID rerun:kind: indexrerun:kind: index rerun:kind: data rerun:component_type: example.MyColor │ │
19-
│ │ rerun:is_sorted: true ┆ ┆ rerun:kind: data │ │
20-
│ │ rerun:kind: control ┆ ┆ │ │
21-
│ ╞══════════════════════════════════════════════╪════════════════════════════╪═══════════════════════════════╪═══════════════════════════════════════╪══════════════════════════════════════════╡ │
22-
│ │ row_[**REDACTED**] ┆ 1 2025-01-10T18:43:42.123456789 ┆ [0, 1, 2] ┆ [0, 1, 2] │ │
23-
│ └──────────────────────────────────────────────┴────────────────────────────┴───────────────────────────────┴───────────────────────────────────────┴──────────────────────────────────────────┘ │
24-
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
5+
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
6+
METADATA: │
7+
* entity_path: /this/that
8+
* heap_size_bytes: [**REDACTED**] │
9+
* id: [**REDACTED**] │
10+
* version: [**REDACTED**] │
11+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
12+
│ ┌──────────────────────────────────────────────┬──────────────────────┬───────────────────────────────┬───────────────────────────────────────────────────────────────────────┐ │
13+
│ │ RowId frame_nr log_time my_index example.MyPoints:colors │ │
14+
│ │ --------------- │ │
15+
│ │ type: FixedSizeBinary[16] ┆ type: nullable i64type: nullable Timestamp(ns) ┆ type: nullable List[nullable u64] ┆ type: nullable List[nullable u32] │ │
16+
│ │ ARROW:extension:metadata: ┆ index_name: frame_nrindex_name: log_time component: my_index archetype: example.MyPoints │ │
17+
│ │ {"namespace":"row"} ┆ is_sorted: trueis_sorted: true component_type: example.MyIndex component: example.MyPoints:colors │ │
18+
│ │ ARROW:extension:name: TUID kind: indexkind: index kind: data component_type: example.MyColor │ │
19+
│ │ is_sorted: true ┆ ┆ kind: data │ │
20+
│ │ kind: control ┆ ┆ │ │
21+
│ ╞══════════════════════════════════════════════╪══════════════════════╪═══════════════════════════════╪═══════════════════════════════════════════════════════════════════════╡ │
22+
│ │ row_[**REDACTED**] ┆ 12025-01-10T18:43:42.123456789 ┆ [0, 1, 2] ┆ [0, 1, 2] │ │
23+
│ └──────────────────────────────────────────────┴──────────────────────┴───────────────────────────────┴───────────────────────────────────────────────────────────────────────┘ │
24+
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

crates/store/re_dataframe/src/query.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1360,7 +1360,8 @@ mod tests {
13601360
#[inline]
13611361
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13621362
let width = 200;
1363-
re_format_arrow::format_record_batch_with_width(&self.0, Some(width)).fmt(f)
1363+
re_format_arrow::format_record_batch_with_width(&self.0, Some(width), f.sign_minus())
1364+
.fmt(f)
13641365
}
13651366
}
13661367

crates/store/re_format_arrow/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ impl Default for RecordBatchFormatOpts {
200200

201201
/// Nicely format this record batch in a way that fits the terminal.
202202
pub fn format_record_batch(batch: &arrow::array::RecordBatch) -> Table {
203-
format_record_batch_with_width(batch, None)
203+
format_record_batch_with_width(batch, None, false)
204204
}
205205

206206
/// Nicely format this record batch using the specified options.
@@ -223,6 +223,7 @@ pub fn format_record_batch_opts(
223223
pub fn format_record_batch_with_width(
224224
batch: &arrow::array::RecordBatch,
225225
width: Option<usize>,
226+
redact_non_deterministic: bool,
226227
) -> Table {
227228
format_dataframe_with_metadata(
228229
&batch.schema_ref().metadata.clone().into_iter().collect(), // HashMap -> BTreeMap
@@ -236,7 +237,7 @@ pub fn format_record_batch_with_width(
236237
trim_field_names: true,
237238
trim_metadata_keys: true,
238239
trim_metadata_values: true,
239-
redact_non_deterministic: false,
240+
redact_non_deterministic,
240241
},
241242
)
242243
}

crates/store/re_sorbet/src/chunk_batch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl ChunkBatch {
114114
impl std::fmt::Display for ChunkBatch {
115115
#[inline]
116116
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117-
re_format_arrow::format_record_batch_with_width(self, f.width()).fmt(f)
117+
re_format_arrow::format_record_batch_with_width(self, f.width(), f.sign_minus()).fmt(f)
118118
}
119119
}
120120

crates/store/re_sorbet/src/sorbet_batch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl SorbetBatch {
129129
impl std::fmt::Display for SorbetBatch {
130130
#[inline]
131131
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132-
re_format_arrow::format_record_batch_with_width(self, f.width()).fmt(f)
132+
re_format_arrow::format_record_batch_with_width(self, f.width(), f.sign_minus()).fmt(f)
133133
}
134134
}
135135

crates/utils/re_mcap/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,5 @@ serde_bytes.workspace = true
3333
thiserror.workspace = true
3434

3535
[dev-dependencies]
36-
re_format_arrow.workspace = true
37-
3836
insta = { workspace = true, features = ["filters", "redactions"] }
3937
prost-reflect = { workspace = true, features = ["text-format"] }

0 commit comments

Comments
 (0)