Skip to content

Commit

Permalink
Keep track of the RRD protocol version and display it where relevant (r…
Browse files Browse the repository at this point in the history
…erun-io#6324)

This augments `StoreInfo` with an in-memory only (!) `store_version`
field.
Our `Decoder` and `StreamDecoder` have been patched to fill out this
field using the RRD version present in the stream's header.

This version is now visible in the UI, using the CLI, and in the
analytics.

Viewer:

![image](https://github.com/rerun-io/rerun/assets/2910679/c7b7f211-1a16-41d4-b43a-d8c661819122)

CLI:

![image](https://github.com/rerun-io/rerun/assets/2910679/df15efa9-e2a0-42b8-b17a-b2c10dc7a46d)

Analytics:

![image](https://github.com/rerun-io/rerun/assets/2910679/b9cf5745-2eb1-4f8a-8a4c-2db9cb874c0b)


- Fixes rerun-io#6280
  • Loading branch information
teh-cmc authored May 14, 2024
1 parent 178ef60 commit c19a08f
Show file tree
Hide file tree
Showing 28 changed files with 280 additions and 78 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4153,6 +4153,9 @@ dependencies = [
[[package]]
name = "re_build_info"
version = "0.16.0-alpha.4"
dependencies = [
"serde",
]

[[package]]
name = "re_build_tools"
Expand Down Expand Up @@ -4189,6 +4192,7 @@ dependencies = [
"once_cell",
"parking_lot",
"rayon",
"re_build_info",
"re_build_tools",
"re_log",
"re_log_encoding",
Expand Down Expand Up @@ -4318,6 +4322,7 @@ dependencies = [
"nohash-hasher",
"parking_lot",
"rand",
"re_build_info",
"re_data_store",
"re_format",
"re_int_histogram",
Expand Down Expand Up @@ -4429,6 +4434,7 @@ dependencies = [
"num-derive",
"num-traits",
"re_arrow2",
"re_build_info",
"re_format",
"re_format_arrow",
"re_log",
Expand Down Expand Up @@ -4614,6 +4620,7 @@ dependencies = [
"crossbeam",
"document-features",
"rand",
"re_build_info",
"re_log",
"re_log_encoding",
"re_log_types",
Expand Down
32 changes: 24 additions & 8 deletions crates/re_analytics/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ pub struct StoreInfo {
/// Where data is being logged.
pub store_source: String,

/// The Rerun version that was used to encode the RRD data.
pub store_version: String,

// Various versions of the host environment.
pub rust_version: Option<String>,
pub llvm_version: Option<String>,
Expand Down Expand Up @@ -225,16 +228,29 @@ impl Properties for OpenRecording {
event.insert("app_env", app_env);

if let Some(store_info) = store_info {
event.insert("application_id", store_info.application_id);
event.insert("recording_id", store_info.recording_id);
event.insert("store_source", store_info.store_source);
event.insert_opt("rust_version", store_info.rust_version);
event.insert_opt("llvm_version", store_info.llvm_version);
event.insert_opt("python_version", store_info.python_version);
event.insert("is_official_example", store_info.is_official_example);
let StoreInfo {
application_id,
recording_id,
store_source,
store_version,
rust_version,
llvm_version,
python_version,
is_official_example,
app_id_starts_with_rerun_example,
} = store_info;

event.insert("application_id", application_id);
event.insert("recording_id", recording_id);
event.insert("store_source", store_source);
event.insert("store_version", store_version);
event.insert_opt("rust_version", rust_version);
event.insert_opt("llvm_version", llvm_version);
event.insert_opt("python_version", python_version);
event.insert("is_official_example", is_official_example);
event.insert(
"app_id_starts_with_rerun_example",
store_info.app_id_starts_with_rerun_example,
app_id_starts_with_rerun_example,
);
}

Expand Down
13 changes: 13 additions & 0 deletions crates/re_build_info/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,16 @@ workspace = true

[package.metadata.docs.rs]
all-features = true


[features]
default = []

## Enable (de)serialization using serde.
serde = ["dep:serde"]


[dependencies]

# Optional dependencies:
serde = { workspace = true, optional = true, features = ["derive", "rc"] }
6 changes: 6 additions & 0 deletions crates/re_build_info/src/crate_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,20 @@ mod meta {
/// - `01NNNNNN` -> `-rc.N`
/// - `00000000` -> none of the above
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct CrateVersion {
pub major: u8,
pub minor: u8,
pub patch: u8,
pub meta: Option<Meta>,
}

impl CrateVersion {
pub const LOCAL: Self = Self::parse(env!("CARGO_PKG_VERSION"));
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Meta {
Rc(u8),
Alpha(u8),
Expand Down
1 change: 1 addition & 0 deletions crates/re_data_loader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ default = []


[dependencies]
re_build_info.workspace = true
re_log_encoding = { workspace = true, features = ["decoder"] }
re_log_types.workspace = true
re_log.workspace = true
Expand Down
9 changes: 8 additions & 1 deletion crates/re_data_loader/src/load_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ pub(crate) fn prepare_store_info(
let app_id = re_log_types::ApplicationId(path.display().to_string());
let store_source = re_log_types::StoreSource::File { file_source };

let is_rrd = crate::SUPPORTED_RERUN_EXTENSIONS.contains(&extension(path).as_str());
let ext = extension(path);
let is_rrd = crate::SUPPORTED_RERUN_EXTENSIONS.contains(&ext.as_str());

(!is_rrd).then(|| {
LogMsg::SetStoreInfo(SetStoreInfo {
Expand All @@ -113,6 +114,12 @@ pub(crate) fn prepare_store_info(
is_official_example: false,
started: re_log_types::Time::now(),
store_source,
// NOTE: If this is a natively supported file, it will go through one of the
// builtin dataloaders, i.e. the local version.
// Otherwise, it will go through an arbitrary external loader, at which point we
// have no certainty what the version is.
store_version: crate::is_supported_file_extension(ext.as_str())
.then_some(re_build_info::CrateVersion::LOCAL),
},
})
})
Expand Down
9 changes: 9 additions & 0 deletions crates/re_data_ui/src/entity_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ impl crate::DataUi for EntityDb {
is_official_example: _,
started,
store_source,
store_version,
} = store_info;

if let Some(cloned_from) = cloned_from {
Expand All @@ -60,6 +61,14 @@ impl crate::DataUi for EntityDb {
ui.label(store_source.to_string());
ui.end_row();

if let Some(store_version) = store_version {
re_ui.grid_left_hand_label(ui, "Source RRD version");
ui.label(store_version.to_string());
ui.end_row();
} else {
re_log::debug_once!("store version is undefined for this recording, this is a bug");
}

re_ui.grid_left_hand_label(ui, "Kind");
ui.label(store_id.kind.to_string());
ui.end_row();
Expand Down
9 changes: 9 additions & 0 deletions crates/re_data_ui/src/log_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl DataUi for SetStoreInfo {
started,
store_source,
is_official_example,
store_version,
} = info;

let re_ui = &ctx.re_ui;
Expand Down Expand Up @@ -77,6 +78,14 @@ impl DataUi for SetStoreInfo {
ui.label(format!("{store_source}"));
ui.end_row();

if let Some(store_version) = store_version {
re_ui.grid_left_hand_label(ui, "store_version:");
ui.label(format!("{store_version}"));
ui.end_row();
} else {
re_log::debug_once!("store version is undefined for this recording, this is a bug");
}

re_ui.grid_left_hand_label(ui, "is_official_example:");
ui.label(format!("{is_official_example}"));
ui.end_row();
Expand Down
1 change: 1 addition & 0 deletions crates/re_entity_db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ serde = ["dep:serde", "dep:rmp-serde", "re_log_types/serde"]


[dependencies]
re_build_info.workspace = true
re_data_store.workspace = true
re_format.workspace = true
re_int_histogram.workspace = true
Expand Down
9 changes: 7 additions & 2 deletions crates/re_entity_db/examples/memory_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,13 @@ fn log_messages() {
fn encode_log_msg(log_msg: &LogMsg) -> Vec<u8> {
let mut bytes = vec![];
let encoding_options = re_log_encoding::EncodingOptions::COMPRESSED;
re_log_encoding::encoder::encode(encoding_options, std::iter::once(log_msg), &mut bytes)
.unwrap();
re_log_encoding::encoder::encode(
re_build_info::CrateVersion::LOCAL,
encoding_options,
std::iter::once(log_msg),
&mut bytes,
)
.unwrap();
bytes
}

Expand Down
1 change: 1 addition & 0 deletions crates/re_entity_db/src/store_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl StoreBundle {
is_official_example: false,
started: re_log_types::Time::now(),
store_source: re_log_types::StoreSource::Other("viewer".to_owned()),
store_version: Some(re_build_info::CrateVersion::LOCAL),
},
});

Expand Down
8 changes: 7 additions & 1 deletion crates/re_log_encoding/benches/msg_encode_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ criterion_main!(benches);
fn encode_log_msgs(messages: &[LogMsg]) -> Vec<u8> {
let encoding_options = re_log_encoding::EncodingOptions::COMPRESSED;
let mut bytes = vec![];
re_log_encoding::encoder::encode(encoding_options, messages.iter(), &mut bytes).unwrap();
re_log_encoding::encoder::encode(
re_build_info::CrateVersion::LOCAL,
encoding_options,
messages.iter(),
&mut bytes,
)
.unwrap();
assert!(bytes.len() > messages.len());
bytes
}
Expand Down
38 changes: 28 additions & 10 deletions crates/re_log_encoding/src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,22 @@ fn warn_on_version_mismatch(
CrateVersion::from_bytes(encoded_version)
};

const LOCAL_VERSION: CrateVersion = CrateVersion::parse(env!("CARGO_PKG_VERSION"));

if encoded_version.is_compatible_with(LOCAL_VERSION) {
if encoded_version.is_compatible_with(CrateVersion::LOCAL) {
Ok(())
} else {
match version_policy {
VersionPolicy::Warn => {
re_log::warn_once!(
"Found log stream with Rerun version {encoded_version}, \
which is incompatible with the local Rerun version {LOCAL_VERSION}. \
Loading will try to continue, but might fail in subtle ways."
which is incompatible with the local Rerun version {}. \
Loading will try to continue, but might fail in subtle ways.",
CrateVersion::LOCAL,
);
Ok(())
}
VersionPolicy::Error => Err(DecodeError::IncompatibleRerunVersion {
file: encoded_version,
local: LOCAL_VERSION,
local: CrateVersion::LOCAL,
}),
}
}
Expand Down Expand Up @@ -109,7 +108,7 @@ pub fn decode_bytes(
pub fn read_options(
version_policy: VersionPolicy,
bytes: &[u8],
) -> Result<EncodingOptions, DecodeError> {
) -> Result<(CrateVersion, EncodingOptions), DecodeError> {
let mut read = std::io::Cursor::new(bytes);

let FileHeader {
Expand All @@ -130,10 +129,11 @@ pub fn read_options(
Serializer::MsgPack => {}
}

Ok(options)
Ok((CrateVersion::from_bytes(version), options))
}

pub struct Decoder<R: std::io::Read> {
version: CrateVersion,
compression: Compression,
read: R,
uncompressed: Vec<u8>, // scratch space
Expand All @@ -146,15 +146,24 @@ impl<R: std::io::Read> Decoder<R> {

let mut data = [0_u8; FileHeader::SIZE];
read.read_exact(&mut data).map_err(DecodeError::Read)?;
let compression = read_options(version_policy, &data)?.compression;

let (version, options) = read_options(version_policy, &data)?;
let compression = options.compression;

Ok(Self {
version,
compression,
read,
uncompressed: vec![],
compressed: vec![],
})
}

/// Returns the Rerun version that was used to encode the data in the first place.
#[inline]
pub fn version(&self) -> CrateVersion {
self.version
}
}

impl<R: std::io::Read> Iterator for Decoder<R> {
Expand Down Expand Up @@ -211,6 +220,12 @@ impl<R: std::io::Read> Iterator for Decoder<R> {

re_tracing::profile_scope!("MsgPack deser");
match rmp_serde::from_slice(&self.uncompressed[..uncompressed_len]) {
Ok(re_log_types::LogMsg::SetStoreInfo(mut msg)) => {
// Propagate the protocol version from the header into the `StoreInfo` so that all
// parts of the app can easily access it.
msg.info.store_version = Some(self.version());
Some(Ok(re_log_types::LogMsg::SetStoreInfo(msg)))
}
Ok(msg) => Some(Ok(msg)),
Err(err) => Some(Err(err.into())),
}
Expand All @@ -227,6 +242,8 @@ fn test_encode_decode() {
Time,
};

let rrd_version = CrateVersion::LOCAL;

let messages = vec![LogMsg::SetStoreInfo(SetStoreInfo {
row_id: RowId::new(),
info: StoreInfo {
Expand All @@ -239,6 +256,7 @@ fn test_encode_decode() {
rustc_version: String::new(),
llvm_version: String::new(),
},
store_version: Some(rrd_version),
},
})];

Expand All @@ -255,7 +273,7 @@ fn test_encode_decode() {

for options in options {
let mut file = vec![];
crate::encoder::encode(options, messages.iter(), &mut file).unwrap();
crate::encoder::encode(rrd_version, options, messages.iter(), &mut file).unwrap();

let decoded_messages = Decoder::new(VersionPolicy::Error, &mut file.as_slice())
.unwrap()
Expand Down
Loading

0 comments on commit c19a08f

Please sign in to comment.