Skip to content

Commit

Permalink
Add support for RecordingStream::serve (#2815)
Browse files Browse the repository at this point in the history
```rust
let rec_stream = RecordingStreamBuilder::new("minimal_serve_rs").serve(
    "0.0.0.0",
    Default::default(),
    Default::default(),
    true,
)?;
```

Try it with the new `minimal_serve` example:
```
$ cargo r -p minimal_serve
```

Fixes #2232

### What

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested [demo.rerun.io](https://demo.rerun.io/pr/2815) (if
applicable)

- [PR Build Summary](https://build.rerun.io/pr/2815)
- [Docs
preview](https://rerun.io/preview/pr%3Acmc%2Frecording_stream_serve/docs)
- [Examples
preview](https://rerun.io/preview/pr%3Acmc%2Frecording_stream_serve/examples)

---------

Co-authored-by: Andreas Reich <[email protected]>
  • Loading branch information
teh-cmc and Wumpf authored Jul 26, 2023
1 parent 7832e4c commit 20a6179
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 28 deletions.
14 changes: 13 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions crates/re_sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ glam = ["re_components/glam"]
## Integration with the [`image`](https://crates.io/crates/image/) crate, plus JPEG support..
image = ["re_components/image"]

## Support serving a web viewer over HTTP.
##
## Enabling this inflates the binary size quite a bit, since it embeds the viewer wasm.
##
## For faster & easier builds, the web-player build comes bundled with the crate.
## Enabling this feature will embed this pre-built web-player.
##
## However, when building from source in the repository, this feature adds quite a bit
## to the compile time since it requires compiling and bundling the viewer as wasm.
## You also need to install some additional tools, which you can do by running
## [`scripts/setup_web.sh`](https://github.com/rerun-io/rerun/blob/main/scripts/setup_web.sh).
web_viewer = [
"dep:re_smart_channel",
"dep:re_web_viewer_server",
"dep:re_ws_comms",
"dep:anyhow",
"dep:webbrowser",
"re_ws_comms?/server",
]


[dependencies]
re_build_info.workspace = true
Expand All @@ -48,6 +68,15 @@ once_cell.workspace = true
parking_lot.workspace = true
thiserror.workspace = true

# Optional dependencies

re_smart_channel = { workspace = true, optional = true }
re_ws_comms = { workspace = true, optional = true }
re_web_viewer_server = { workspace = true, optional = true }

anyhow = { workspace = true, optional = true }
webbrowser = { version = "0.8", optional = true }


[dev-dependencies]
re_components = { workspace = true, features = ["arrow_datagen"] }
Expand Down
4 changes: 4 additions & 0 deletions crates/re_sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ pub mod experimental {
pub use re_types::{archetypes, components, datatypes, Archetype, Component, Datatype};
}

/// Methods for spawning the web viewer and streaming the SDK log stream to it.
#[cfg(feature = "web_viewer")]
pub mod web_viewer;

/// Re-exports of other crates.
pub mod external {
pub use re_log;
Expand Down
56 changes: 56 additions & 0 deletions crates/re_sdk/src/recording_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ use re_log_types::{
TimePoint, TimeType, Timeline, TimelineName,
};

#[cfg(feature = "web_viewer")]
use re_web_viewer_server::WebViewerServerPort;
#[cfg(feature = "web_viewer")]
use re_ws_comms::RerunServerPort;

use crate::sink::{LogSink, MemorySinkStorage};

// ---
Expand All @@ -31,6 +36,10 @@ pub enum RecordingStreamError {
name: &'static str,
err: Box<dyn std::error::Error + Send + Sync>,
},

#[cfg(feature = "web_viewer")]
#[error(transparent)]
WebSink(anyhow::Error),
}

pub type RecordingStreamResult<T> = Result<T, RecordingStreamError>;
Expand Down Expand Up @@ -259,6 +268,53 @@ impl RecordingStreamBuilder {
}
}

/// Creates a new [`RecordingStream`] that is pre-configured to stream the data through to a
/// web-based Rerun viewer via WebSockets.
///
/// This method needs to be called in a context where a Tokio runtime is already running (see
/// example below).
///
/// If the `open_browser` argument is `true`, your default browser will be opened with a
/// connected web-viewer.
///
/// If not, you can connect to this server using the `rerun` binary (`cargo install rerun-cli`).
///
/// ## Example
///
/// ```ignore
/// // Ensure we have a running tokio runtime.
/// let mut tokio_runtime = None;
/// let tokio_runtime_handle = if let Ok(handle) = tokio::runtime::Handle::try_current() {
/// handle
/// } else {
/// let rt = tokio::runtime::Runtime::new().expect("Failed to create tokio runtime");
/// tokio_runtime.get_or_insert(rt).handle().clone()
/// };
/// let _tokio_runtime_guard = tokio_runtime_handle.enter();
///
/// let rec_stream = re_sdk::RecordingStreamBuilder::new("my_app")
/// .serve("0.0.0.0", Default::default(), Default::default(), true)?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
#[cfg(feature = "web_viewer")]
pub fn serve(
self,
bind_ip: &str,
web_port: WebViewerServerPort,
ws_port: RerunServerPort,
open_browser: bool,
) -> RecordingStreamResult<RecordingStream> {
let (enabled, store_info, batcher_config) = self.into_args();
if enabled {
let sink = crate::web_viewer::new_sink(open_browser, bind_ip, web_port, ws_port)
.map_err(RecordingStreamError::WebSink)?;
RecordingStream::new(store_info, batcher_config, sink)
} else {
re_log::debug!("Rerun disabled - call to serve() ignored");
Ok(RecordingStream::disabled())
}
}

/// Returns whether or not logging is enabled, a [`StoreInfo`] and the associated batcher
/// configuration.
///
Expand Down
File renamed without changes.
21 changes: 9 additions & 12 deletions crates/rerun/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,15 @@ sdk = ["dep:re_sdk"]
## Support serving a web viewer over HTTP.
##
## Enabling this inflates the binary size quite a bit, since it embeds the viewer wasm.
# When building from source (in the repository), this feature adds quite a bit
# to the compile time since it requires compiling and bundling the viewer as wasm.
#
# You also need to install some additional tools, which you can do by running
# [`scripts/setup_web.sh`](https://github.com/rerun-io/rerun/blob/main/scripts/setup_web.sh).
web_viewer = [
"dep:re_web_viewer_server",
"dep:webbrowser",
"re_ws_comms/server",
]
##
## For faster & easier builds, the web-player build comes bundled with the crate.
## Enabling this feature will embed this pre-built web-player.
##
## However, when building from source in the repository, this feature adds quite a bit
## to the compile time since it requires compiling and bundling the viewer as wasm.
## You also need to install some additional tools, which you can do by running
## [`scripts/setup_web.sh`](https://github.com/rerun-io/rerun/blob/main/scripts/setup_web.sh).
web_viewer = ["dep:re_web_viewer_server", "re_sdk?/web_viewer"]

[dependencies]
re_build_info.workspace = true
Expand All @@ -88,8 +87,6 @@ re_sdk_comms = { workspace = true, optional = true }
re_viewer = { workspace = true, optional = true }
re_web_viewer_server = { workspace = true, optional = true }

webbrowser = { version = "0.8", optional = true }

# Native dependencies:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
clap = { workspace = true, features = ["derive"] }
Expand Down
10 changes: 3 additions & 7 deletions crates/rerun/src/clap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
use std::{net::SocketAddr, path::PathBuf};

use re_sdk::RecordingStream;
#[cfg(feature = "web_viewer")]
use re_web_viewer_server::WebViewerServerPort;
#[cfg(feature = "web_viewer")]
use re_ws_comms::RerunServerPort;

// ---

Expand Down Expand Up @@ -113,11 +109,11 @@ impl RerunArgs {
#[cfg(feature = "web_viewer")]
RerunBehavior::Serve => {
let open_browser = true;
crate::web_viewer::new_sink(
re_sdk::web_viewer::new_sink(
open_browser,
&self.bind,
WebViewerServerPort::default(),
RerunServerPort::default(),
Default::default(),
Default::default(),
)?
}

Expand Down
4 changes: 0 additions & 4 deletions crates/rerun/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ pub mod clap;
#[cfg(all(feature = "sdk", feature = "native_viewer"))]
pub mod native_viewer;

/// Methods for spawning the web viewer and streaming the SDK log stream to it.
#[cfg(all(feature = "sdk", feature = "web_viewer"))]
pub mod web_viewer;

pub use run::{run, CallSource};

// NOTE: Have a look at `re_sdk/src/lib.rs` for an accurate listing of all these symbols.
Expand Down
6 changes: 3 additions & 3 deletions crates/rerun/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use re_smart_channel::{Receiver, SmartMessagePayload};

use anyhow::Context as _;
use clap::Subcommand;

#[cfg(feature = "web_viewer")]
use re_sdk::web_viewer::host_web_viewer;
#[cfg(feature = "web_viewer")]
use re_web_viewer_server::WebViewerServerPort;
#[cfg(feature = "web_viewer")]
use re_ws_comms::RerunServerPort;

#[cfg(feature = "web_viewer")]
use crate::web_viewer::host_web_viewer;

// Note the extra blank lines between the point-lists below: it is required by `clap`.

/// The Rerun Viewer and Server
Expand Down
2 changes: 1 addition & 1 deletion docs/content/reference/sdk-operating-modes.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Use [`rr.serve`](https://ref.rerun.io/docs/python/latest/package/rerun/__init__/

#### `Rust`

[TODO(#2232)](https://github.com/rerun-io/rerun/issues/2232): This is not available for the time being.
[`RecordingStream::serve`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.serve)

## Save

Expand Down
11 changes: 11 additions & 0 deletions examples/rust/minimal_serve/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "minimal_serve"
version = "0.8.0-alpha.7"
edition = "2021"
rust-version = "1.69"
license = "MIT OR Apache-2.0"
publish = false

[dependencies]
rerun = { path = "../../../crates/rerun", features = ["web_viewer"] }
tokio = "1.0"
19 changes: 19 additions & 0 deletions examples/rust/minimal_serve/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: Minimal `serve` example
rust: https://github.com/rerun-io/rerun/tree/latest/examples/rust/minimal_serve/src/main.rs
thumbnail: https://static.rerun.io/92a1f80b5cf2cd2c04a10d8ced35849da8f1c0ed_minimal_480w.png
---

<picture>
<source media="(max-width: 480px)" srcset="https://static.rerun.io/92a1f80b5cf2cd2c04a10d8ced35849da8f1c0ed_minimal_480w.png">
<source media="(max-width: 768px)" srcset="https://static.rerun.io/d78037f2306ed02505859adbae9f72d4ab2945d1_minimal_768w.png">
<source media="(max-width: 1024px)" srcset="https://static.rerun.io/cf926c580c8ca8b39fd844f6adf4b19972b5111e_minimal_1024w.png">
<source media="(max-width: 1200px)" srcset="https://static.rerun.io/8f03efd9e918f43b5e6d9257d0f1a3cb962b3889_minimal_1200w.png">
<img src="https://static.rerun.io/0e47ac513ab25d56cf2b493128097d499a07e5e8_minimal_full.png" alt="Minimal example screenshot">
</picture>

The simplest example of how to use Rerun with its Web-based UI, showing how to log a point cloud.

```bash
cargo run --release
```
39 changes: 39 additions & 0 deletions examples/rust/minimal_serve/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//! Demonstrates the most barebone usage of the Rerun SDK.
use rerun::{
components::{ColorRGBA, Point3D, Radius},
demo_util::grid,
external::glam,
MsgSender, RecordingStreamBuilder,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
// `serve()` requires to have a running Tokio runtime in the current context.
let rt = tokio::runtime::Runtime::new().expect("Failed to create tokio runtime");
let _guard = rt.enter();

let rec_stream = RecordingStreamBuilder::new("minimal_serve_rs").serve(
"0.0.0.0",
Default::default(),
Default::default(),
true,
)?;

let points = grid(glam::Vec3::splat(-10.0), glam::Vec3::splat(10.0), 10)
.map(Point3D::from)
.collect::<Vec<_>>();
let colors = grid(glam::Vec3::ZERO, glam::Vec3::splat(255.0), 10)
.map(|v| ColorRGBA::from_rgb(v.x as u8, v.y as u8, v.z as u8))
.collect::<Vec<_>>();

MsgSender::new("my_points")
.with_component(&points)?
.with_component(&colors)?
.with_splat(Radius(0.5))?
.send(&rec_stream)?;

eprintln!("Check your browser!");
std::thread::sleep(std::time::Duration::from_secs(100000));

Ok(())
}

0 comments on commit 20a6179

Please sign in to comment.