Rerun C++ SDK
Loading...
Searching...
No Matches
recording_stream.hpp
1#pragma once
2
3#include <chrono>
4#include <cmath>
5#include <cstdint> // uint32_t etc.
6#include <filesystem>
7#include <limits>
8#include <optional>
9#include <string_view>
10#include <type_traits>
11#include <vector>
12
13#include "as_components.hpp"
14#include "component_column.hpp"
15#include "error.hpp"
16#include "log_sink.hpp"
17#include "spawn_options.hpp"
18#include "time_column.hpp"
19
20namespace rerun {
21 struct ComponentBatch;
22
23 enum class StoreKind {
24 Recording,
25 Blueprint,
26 };
27
28 /// A `RecordingStream` handles everything related to logging data into Rerun.
29 ///
30 /// ## Multithreading and ordering
31 ///
32 /// A `RecordingStream` is thread-safe.
33 ///
34 /// Internally, all operations are linearized into a pipeline:
35 /// - All operations sent by a given thread will take effect in the same exact order as that
36 /// thread originally sent them in, from its point of view.
37 /// - There isn't any well defined global order across multiple threads.
38 ///
39 /// This means that e.g. flushing the pipeline (`flush_blocking`) guarantees that all
40 /// previous data sent by the calling thread has been recorded; no more, no less.
41 /// (e.g. it does not mean that all file caches are flushed)
42 ///
43 /// ## Shutdown
44 ///
45 /// The `RecordingStream` can only be shutdown by dropping all instances of it, at which point
46 /// it will automatically take care of flushing any pending data that might remain in the
47 /// pipeline.
48 ///
49 /// TODO(andreas): The only way of having two instances of a `RecordingStream` is currently to
50 /// set it as a the global.
51 ///
52 /// Shutting down cannot ever block.
53 ///
54 /// ## Logging
55 ///
56 /// Internally, the stream will automatically micro-batch multiple log calls to optimize
57 /// transport.
58 /// See [SDK Micro Batching](https://www.rerun.io/docs/reference/sdk/micro-batching) for
59 /// more information.
60 ///
61 /// The data will be timestamped automatically based on the `RecordingStream`'s
62 /// internal clock.
64 private:
65 // TODO(grtlr): Ideally we'd expose more of the `EntityPath` struct to the C++ world so
66 // that we don't have to hardcode this here.
67 static constexpr const char PROPERTIES_ENTITY_PATH[] = "__properties/";
68
69 public:
70 /// Creates a new recording stream to log to.
71 ///
72 /// \param app_id The user-chosen name of the application doing the logging.
73 /// \param recording_id The user-chosen name of the recording being logged to.
74 /// \param store_kind Whether to log to the recording store or the blueprint store.
76 std::string_view app_id, std::string_view recording_id = std::string_view(),
77 StoreKind store_kind = StoreKind::Recording
78 );
80
81 /// \private
83
84 // TODO(andreas): We could easily make the recording stream trivial to copy by bumping Rusts
85 // ref counter by adding a copy of the recording stream to the list of C recording streams.
86 // Doing it this way would likely yield the most consistent behavior when interacting with
87 // global streams (and especially when interacting with different languages in the same
88 // application).
89 /// \private
90 RecordingStream(const RecordingStream&) = delete;
91 /// \private
92 RecordingStream() = delete;
93
94 // -----------------------------------------------------------------------------------------
95 /// \name Properties
96 /// @{
97
98 /// Returns the store kind as passed during construction
99 StoreKind kind() const {
100 return _store_kind;
101 }
102
103 /// Returns whether the recording stream is enabled.
104 ///
105 /// All log functions early out if a recording stream is disabled.
106 /// Naturally, logging functions that take unserialized data will skip the serialization step as well.
107 bool is_enabled() const {
108 return _enabled;
109 }
110
111 /// @}
112
113 // -----------------------------------------------------------------------------------------
114 /// \name Controlling globally available instances of RecordingStream.
115 /// @{
116
117 /// Replaces the currently active recording for this stream's store kind in the global scope
118 /// with this one.
119 ///
120 /// Afterwards, destroying this recording stream will *not* change the global recording
121 /// stream, as it increases an internal ref-count.
122 void set_global() const;
123
124 /// Replaces the currently active recording for this stream's store kind in the thread-local
125 /// scope with this one
126 ///
127 /// Afterwards, destroying this recording stream will *not* change the thread local
128 /// recording stream, as it increases an internal ref-count.
129 void set_thread_local() const;
130
131 /// Retrieves the most appropriate globally available recording stream for the given kind.
132 ///
133 /// I.e. thread-local first, then global.
134 /// If neither was set, any operations on the returned stream will be no-ops.
135 static RecordingStream& current(StoreKind store_kind = StoreKind::Recording);
136
137 /// @}
138
139 // -----------------------------------------------------------------------------------------
140 /// \name Directing the recording stream.
141 /// \details Either of these needs to be called, otherwise the stream will buffer up indefinitely.
142 /// @{
143
144 /// Stream data to multiple sinks.
145 ///
146 /// See specific sink types for more information:
147 /// * `FileSink`
148 /// * `GrpcSink`
149 /// * `GrpcServerSink`
150 ///
151 /// Sink descriptors are copied and may be destroyed after this call.
152 /// Replacing the sinks or destroying the recording shuts hosted servers down.
153 template <typename... Ts>
154 Error set_sinks(const Ts&... sinks) const {
155 LogSink out_sinks[] = {sinks...};
156 uint32_t num_sinks = sizeof...(Ts);
157 return try_set_sinks(out_sinks, num_sinks);
158 }
159
160 /// Connect to a remote Rerun Viewer on the given URL.
161 ///
162 /// Requires that you first start a Rerun Viewer by typing 'rerun' in a terminal.
163 ///
164 /// \param url The scheme must be one of `rerun://`, `rerun+http://`, or `rerun+https://`,
165 /// and the pathname must be `/proxy`. The default is `rerun+http://127.0.0.1:9876/proxy`.
166 ///
167 /// This function returns immediately.
168 Error connect_grpc(std::string_view url = "rerun+http://127.0.0.1:9876/proxy") const;
169
170 /// Swaps the underlying sink for a gRPC server sink pre-configured to listen on `rerun+http://{bind_ip}:{port}/proxy`.
171 ///
172 /// The gRPC server will buffer all log data in memory so that late connecting viewers will get all the data.
173 /// You can control the amount of data buffered by the gRPC server with the `server_memory_limit` argument.
174 /// Once reached, the earliest logged data will be dropped. Static data is never dropped.
175 ///
176 /// Returns the URI of the gRPC server so you can connect to it from a viewer.
177 ///
178 /// This function returns immediately.
180 std::string_view bind_ip = "0.0.0.0", uint16_t port = 9876,
181 std::string_view server_memory_limit = "1GiB",
183 std::vector<std::string> cors_allow_origins = {}
184 ) const;
185
186 /// Spawns a new Rerun Viewer process from an executable available in PATH, then connects to it
187 /// over gRPC.
188 ///
189 /// If a Rerun Viewer is already listening on this port, the stream will be redirected to
190 /// that viewer instead of starting a new one.
191 ///
192 /// \param options See `rerun::SpawnOptions` for more information.
193 Error spawn(const SpawnOptions& options = {}) const;
194
195 /// @see RecordingStream::spawn
196 template <typename TRep, typename TPeriod>
198 const SpawnOptions& options = {},
199 std::chrono::duration<TRep, TPeriod> flush_timeout = std::chrono::seconds(2)
200 ) const {
201 using seconds_float = std::chrono::duration<float>; // Default ratio is 1:1 == seconds.
202 return spawn(options, std::chrono::duration_cast<seconds_float>(flush_timeout).count());
203 }
204
205 /// Stream all log-data to a given `.rrd` file.
206 ///
207 /// The Rerun Viewer is able to read continuously from the resulting rrd file while it is being written.
208 /// However, depending on your OS and configuration, changes may not be immediately visible due to file caching.
209 /// This is a common issue on Windows and (to a lesser extent) on MacOS.
210 ///
211 /// This function returns immediately.
212 Error save(std::string_view path) const;
213
214 /// Stream all log-data to standard output.
215 ///
216 /// Pipe the result into the Rerun Viewer to visualize it.
217 ///
218 /// If there isn't any listener at the other end of the pipe, the `RecordingStream` will
219 /// default back to `buffered` mode, in order not to break the user's terminal.
220 ///
221 /// This function returns immediately.
222 //
223 // NOTE: This should be called `stdout` like in other SDK, but turns out that `stdout` is a
224 // macro when compiling with msvc [1].
225 // [1]: https://learn.microsoft.com/en-us/cpp/c-runtime-library/stdin-stdout-stderr?view=msvc-170
227
228 /// Initiates a flush the batching pipeline and waits for it to propagate.
229 ///
230 /// \param timeout_sec The minimum time the SDK will wait during a flush before potentially
231 /// dropping data if progress is not being made. If you pass in FLT_MAX or infinity,
232 /// the function will block until it either succeeds or fails.
233 ///
234 /// Returns an error if we fail to flush all previously sent log messages.
235 ///
236 /// See `RecordingStream` docs for ordering semantics and multithreading guarantees.
237 Error flush_blocking(float timeout_sec = std::numeric_limits<float>::infinity()) const;
238
239 /// @}
240
241 // -----------------------------------------------------------------------------------------
242 /// \name Controlling log time (index).
243 /// \details
244 /// @{
245
246 /// Set the index value of the given timeline as a sequence number, for the current calling thread.
247 ///
248 /// Used for all subsequent logging performed from this same thread, until the next call
249 /// to one of the time setting methods.
250 ///
251 /// For example: `rec.set_time_sequence("frame_nr", frame_nr)`.
252 ///
253 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
254 /// @see set_time_sequence, set_time_duration, set_time_duration_secs, set_time_duration_nanos, set_time_timestamp, set_time_timestamp_secs_since_epoch, set_time_timestamp_nanos_since_epoch
255 void set_time_sequence(std::string_view timeline_name, int64_t sequence_nr) const;
256
257 /// Set the index value of the given timeline as a duration, for the current calling thread.
258 ///
259 /// Used for all subsequent logging performed from this same thread, until the next call
260 /// to one of the time setting methods.
261 ///
262 /// For example: `rec.set_time_duration("runtime", time_since_start)`.
263 ///
264 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
265 /// @see set_time_sequence, set_time_duration, set_time_duration_secs, set_time_duration_nanos, set_time_timestamp, set_time_timestamp_secs_since_epoch, set_time_timestamp_nanos_since_epoch
266 template <typename TRep, typename TPeriod>
268 std::string_view timeline_name, std::chrono::duration<TRep, TPeriod> duration
269 ) const {
270 auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
271 set_time_duration_nanos(timeline_name, nanos);
272 }
273
274 /// Set the index value of the given timeline as a duration in seconds, for the current calling thread.
275 ///
276 /// Used for all subsequent logging performed from this same thread, until the next call
277 /// to one of the time setting methods.
278 ///
279 /// For example: `rec.set_time_duration_secs("runtime", seconds_since_start)`.
280 ///
281 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
282 /// @see set_time_sequence, set_time_duration, set_time_duration_secs, set_time_duration_nanos, set_time_timestamp, set_time_timestamp_secs_since_epoch, set_time_timestamp_nanos_since_epoch
283 void set_time_duration_secs(std::string_view timeline_name, double secs) const {
284 set_time_duration_nanos(timeline_name, std::llround(1e9 * secs));
285 }
286
287 /// Set the index value of the given timeline as a duration in nanoseconds, for the current calling thread.
288 ///
289 /// Used for all subsequent logging performed from this same thread, until the next call
290 /// to one of the time setting methods.
291 ///
292 /// For example: `rec.set_time_duration_nanos("runtime", nanos_since_start)`.
293 ///
294 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
295 /// @see set_time_sequence, set_time_duration, set_time_duration_secs, set_time_duration_nanos, set_time_timestamp, set_time_timestamp_secs_since_epoch, set_time_timestamp_nanos_since_epoch
296 void set_time_duration_nanos(std::string_view timeline_name, int64_t nanos) const;
297
298 /// Set the index value of the given timeline as a timestamp, for the current calling thread.
299 ///
300 /// Used for all subsequent logging performed from this same thread, until the next call
301 /// to one of the time setting methods.
302 ///
303 /// For example: `rec.set_time_timestamp("capture_time", now())`.
304 ///
305 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
306 /// @see set_time_sequence, set_time_duration, set_time_duration_secs, set_time_duration_nanos, set_time_timestamp, set_time_timestamp_secs_since_epoch, set_time_timestamp_nanos_since_epoch
307 template <typename TClock>
309 std::string_view timeline_name, std::chrono::time_point<TClock> timestamp
310 ) const {
312 timeline_name,
313 std::chrono::duration_cast<std::chrono::nanoseconds>(timestamp.time_since_epoch())
314 .count()
315 );
316 }
317
318 /// Set the index value of the given timeline as seconds since Unix Epoch (1970), for the current calling thread.
319 ///
320 /// Used for all subsequent logging performed from this same thread, until the next call
321 /// to one of the time setting methods.
322 ///
323 /// For example: `rec.set_time_timestamp_secs_since_epoch("capture_time", secs_since_epoch())`.
324 ///
325 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
326 /// @see set_time_sequence, set_time_duration, set_time_duration_secs, set_time_duration_nanos, set_time_timestamp, set_time_timestamp_secs_since_epoch, set_time_timestamp_nanos_since_epoch
327 void set_time_timestamp_secs_since_epoch(std::string_view timeline_name, double seconds)
328 const {
330 timeline_name,
331 static_cast<int64_t>(1e9 * seconds)
332 );
333 }
334
335 /// Set the index value of the given timeline as nanoseconds since Unix Epoch (1970), for the current calling thread.
336 ///
337 /// Used for all subsequent logging performed from this same thread, until the next call
338 /// to one of the time setting methods.
339 ///
340 /// For example: `rec.set_time_timestamp_nanos_since_epoch("capture_time", nanos_since_epoch())`.
341 ///
342 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
343 /// @see set_time_sequence, set_time_duration, set_time_duration_secs, set_time_duration_nanos, set_time_timestamp, set_time_timestamp_secs_since_epoch, set_time_timestamp_nanos_since_epoch
344 void set_time_timestamp_nanos_since_epoch(std::string_view timeline_name, int64_t nanos)
345 const;
346
347 /// Set the current time of the recording, for the current calling thread.
348 ///
349 /// Used for all subsequent logging performed from this same thread, until the next call
350 /// to one of the time setting methods.
351 ///
352 /// For example: `rec.set_time("sim_time", sim_time_secs)`.
353 ///
354 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
355 /// @see set_time_sequence, set_time_seconds, set_time_nanos, reset_time, disable_timeline
356 template <typename TClock>
357 [[deprecated("Renamed to `set_time_timestamp`")]] void set_time(
358 std::string_view timeline_name, std::chrono::time_point<TClock> time
359 ) const {
360 set_time(timeline_name, time.time_since_epoch());
361 }
362
363 /// Set the current time of the recording, for the current calling thread.
364 ///
365 /// Used for all subsequent logging performed from this same thread, until the next call
366 /// to one of the time setting methods.
367 ///
368 /// For example: `rec.set_time("sim_time", sim_time_secs)`.
369 ///
370 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
371 /// @see set_time_sequence, set_time_seconds, set_time_nanos, reset_time, disable_timeline
372 template <typename TRep, typename TPeriod>
373 [[deprecated("Renamed `set_time_duration`")]] void set_time(
374 std::string_view timeline_name, std::chrono::duration<TRep, TPeriod> time
375 ) const {
376 set_time_duration(timeline_name, time);
377 }
378
379 /// Set the current time of the recording, for the current calling thread.
380 ///
381 /// Used for all subsequent logging performed from this same thread, until the next call
382 /// to one of the time setting methods.
383 ///
384 /// For example: `rec.set_time_seconds("sim_time", sim_time_secs)`.
385 ///
386 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
387 /// @see set_time_sequence, set_time_nanos, reset_time, set_time, disable_timeline
388 [[deprecated("Use either `set_time_duration_secs` or `set_time_timestamp_secs_since_epoch`"
389 )]] void
390 set_time_seconds(std::string_view timeline_name, double seconds) const {
391 set_time_duration_secs(timeline_name, seconds);
392 }
393
394 /// Set the current time of the recording, for the current calling thread.
395 ///
396 /// Used for all subsequent logging performed from this same thread, until the next call
397 /// to one of the time setting methods.
398 ///
399 /// For example: `rec.set_time_nanos("sim_time", sim_time_nanos)`.
400 ///
401 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
402 /// @see set_time_sequence, set_time_seconds, reset_time, set_time, disable_timeline
403 [[deprecated(
404 "Use either `set_time_duration_nanos` or `set_time_timestamp_nanos_since_epoch`"
405 )]] void
406 set_time_nanos(std::string_view timeline_name, int64_t nanos) const {
407 set_time_duration_nanos(timeline_name, nanos);
408 }
409
410 /// Stops logging to the specified timeline for subsequent log calls.
411 ///
412 /// The timeline is still there, but will not be updated with any new data.
413 ///
414 /// No-op if the timeline doesn't exist.
415 ///
416 /// @see set_time_sequence, set_time_seconds, set_time, reset_time
417 void disable_timeline(std::string_view timeline_name) const;
418
419 /// Clears out the current time of the recording, for the current calling thread.
420 ///
421 /// Used for all subsequent logging performed from this same thread, until the next call
422 /// to one of the time setting methods.
423 ///
424 /// For example: `rec.reset_time()`.
425 /// @see set_time_sequence, set_time_seconds, set_time_nanos, disable_timeline
426 void reset_time() const;
427
428 /// Enable or disable automatic injection of the `log_tick` timeline into logged data.
429 ///
430 /// `log_tick` is a per-recording counter that increments on every logging call.
431 /// It is **disabled** by default (it can also be controlled via the `RERUN_LOG_TICK`
432 /// environment variable).
433 ///
434 /// @see set_log_time_enabled
435 void set_log_tick_enabled(bool enabled) const;
436
437 /// Enable or disable automatic injection of the `log_time` timeline into logged data.
438 ///
439 /// `log_time` is the wall-clock time at which data was logged.
440 /// It is **enabled** by default (it can also be controlled via the `RERUN_LOG_TIME`
441 /// environment variable).
442 ///
443 /// @see set_log_tick_enabled
444 void set_log_time_enabled(bool enabled) const;
445
446 /// @}
447
448 // -----------------------------------------------------------------------------------------
449 /// \name Sending & logging data.
450 /// @{
451
452 /// Logs one or more archetype and/or component batches.
453 ///
454 /// This is the main entry point for logging data to rerun. It can be used to log anything
455 /// that implements the `AsComponents<T>` trait.
456 ///
457 /// When logging data, you must always provide an [entity_path](https://www.rerun.io/docs/concepts/logging-and-ingestion/entity-path)
458 /// for identifying the data. Note that paths prefixed with "__" are considered reserved for use by the Rerun SDK
459 /// itself and should not be used for logging user data. This is where Rerun will log additional information
460 /// such as properties and warnings.
461 ///
462 /// The most common way to log is with one of the rerun archetypes, all of which implement the `AsComponents` trait.
463 ///
464 /// For example, to log two 3D points:
465 /// ```
466 /// rec.log("my/point", rerun::Points3D({{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}}));
467 /// ```
468 ///
469 /// The `log` function can flexibly accept an arbitrary number of additional objects which will
470 /// be merged into the first entity, for instance:
471 /// ```
472 /// // Log three points with arrows sticking out of them:
473 /// rec.log(
474 /// "my/points",
475 /// rerun::Points3D({{0.2f, 0.5f, 0.3f}, {0.9f, 1.2f, 0.1f}, {1.0f, 4.2f, 0.3f}})
476 /// .with_radii({0.1, 0.2, 0.3}),
477 /// rerun::Arrows3D::from_vectors({{0.3f, 2.1f, 0.2f}, {0.9f, -1.1, 2.3f}, {-0.4f, 0.5f, 2.9f}})
478 /// );
479 /// ```
480 ///
481 /// Any failures that may are handled with `Error::handle`.
482 ///
483 /// \param entity_path Path to the entity in the space hierarchy.
484 /// \param as_components Any type for which the `AsComponents<T>` trait is implemented.
485 /// This is the case for any archetype as well as individual or collection of `ComponentBatch`.
486 /// You can implement `AsComponents` for your own types as well
487 ///
488 /// @see try_log, log_static, try_log_with_static
489 template <typename... Ts>
490 void log(std::string_view entity_path, const Ts&... as_components) const {
491 if (!is_enabled()) {
492 return;
493 }
494 try_log_with_static(entity_path, false, as_components...).handle();
495 }
496
497 /// Logs one or more archetype and/or component batches as static data.
498 ///
499 /// Like `log` but logs the data as static:
500 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
501 /// any temporal data of the same type.
502 ///
503 /// Failures are handled with `Error::handle`.
504 ///
505 /// \param entity_path Path to the entity in the space hierarchy.
506 /// \param as_components Any type for which the `AsComponents<T>` trait is implemented.
507 /// This is the case for any archetype as well as individual or collection of `ComponentBatch`.
508 /// You can implement `AsComponents` for your own types as well
509 ///
510 /// @see log, try_log_static, try_log_with_static
511 template <typename... Ts>
512 void log_static(std::string_view entity_path, const Ts&... as_components) const {
513 if (!is_enabled()) {
514 return;
515 }
516 try_log_with_static(entity_path, true, as_components...).handle();
517 }
518
519 /// Logs one or more archetype and/or component batches.
520 ///
521 /// See `log` for more information.
522 /// Unlike `log` this method returns an error if an error occurs.
523 ///
524 /// \param entity_path Path to the entity in the space hierarchy.
525 /// \param as_components Any type for which the `AsComponents<T>` trait is implemented.
526 /// This is the case for any archetype as well as individual or collection of `ComponentBatch`.
527 /// You can implement `AsComponents` for your own types as well
528 ///
529 /// @see log, try_log_static, try_log_with_static
530 template <typename... Ts>
531 Error try_log(std::string_view entity_path, const Ts&... as_components) const {
532 if (!is_enabled()) {
533 return Error::ok();
534 }
535 return try_log_with_static(entity_path, false, as_components...);
536 }
537
538 /// Logs one or more archetype and/or component batches as static data, returning an error.
539 ///
540 /// See `log`/`log_static` for more information.
541 /// Unlike `log_static` this method returns if an error occurs.
542 ///
543 /// \param entity_path Path to the entity in the space hierarchy.
544 /// \param as_components Any type for which the `AsComponents<T>` trait is implemented.
545 /// This is the case for any archetype as well as individual or collection of `ComponentBatch`.
546 /// You can implement `AsComponents` for your own types as well
547 /// \returns An error if an error occurs during evaluation of `AsComponents` or logging.
548 ///
549 /// @see log_static, try_log, try_log_with_static
550 template <typename... Ts>
551 Error try_log_static(std::string_view entity_path, const Ts&... as_components) const {
552 if (!is_enabled()) {
553 return Error::ok();
554 }
555 return try_log_with_static(entity_path, true, as_components...);
556 }
557
558 /// Logs one or more archetype and/or component batches optionally static, returning an error.
559 ///
560 /// See `log`/`log_static` for more information.
561 /// Returns an error if an error occurs during evaluation of `AsComponents` or logging.
562 ///
563 /// \param entity_path Path to the entity in the space hierarchy.
564 /// \param static_ If true, the logged components will be static.
565 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
566 /// any temporal data of the same type.
567 /// Otherwise, the data will be timestamped automatically with `log_time` (and `log_tick`, if enabled).
568 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
569 /// \param as_components Any type for which the `AsComponents<T>` trait is implemented.
570 /// This is the case for any archetype as well as individual or collection of `ComponentBatch`.
571 /// You can implement `AsComponents` for your own types as well
572 ///
573 /// @see log, try_log, log_static, try_log_static
574 template <typename... Ts>
575 void log_with_static(std::string_view entity_path, bool static_, const Ts&... as_components)
576 const {
577 try_log_with_static(entity_path, static_, as_components...).handle();
578 }
579
580 /// Logs one or more archetype and/or component batches optionally static, returning an error.
581 ///
582 /// See `log`/`log_static` for more information.
583 /// Returns an error if an error occurs during evaluation of `AsComponents` or logging.
584 ///
585 /// \param entity_path Path to the entity in the space hierarchy.
586 /// \param static_ If true, the logged components will be static.
587 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
588 /// any temporal data of the same type.
589 /// Otherwise, the data will be timestamped automatically with `log_time` (and `log_tick`, if enabled).
590 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
591 /// \param as_components Any type for which the `AsComponents<T>` trait is implemented.
592 /// This is the case for any archetype as well as individual or collection of `ComponentBatch`.
593 /// You can implement `AsComponents` for your own types as well
594 /// \returns An error if an error occurs during evaluation of `AsComponents` or logging.
595 ///
596 /// @see log, try_log, log_static, try_log_static
597 template <typename... Ts>
599 std::string_view entity_path, bool static_, const Ts&... as_components
600 ) const {
601 if (!is_enabled()) {
602 return Error::ok();
603 }
604 std::vector<ComponentBatch> serialized_columns;
605 Error err;
606 (
607 [&] {
608 if (err.is_err()) {
609 return;
610 }
611
612 const Result<Collection<ComponentBatch>> serialization_result =
613 AsComponents<Ts>().as_batches(as_components);
614 if (serialization_result.is_err()) {
615 err = serialization_result.error;
616 return;
617 }
618
619 if (serialized_columns.empty()) {
620 // Fast path for the first batch (which is usually the only one!)
621 serialized_columns = std::move(serialization_result.value).to_vector();
622 } else {
623 serialized_columns.insert(
624 serialized_columns.end(),
625 std::make_move_iterator(serialization_result.value.begin()),
626 std::make_move_iterator(serialization_result.value.end())
627 );
628 }
629 }(),
630 ...
631 );
632 RR_RETURN_NOT_OK(err);
633
634 return try_log_serialized_batches(entity_path, static_, std::move(serialized_columns));
635 }
636
637 /// Logs several serialized batches batches, returning an error on failure.
638 ///
639 /// This is a more low-level API than `log`/`log_static\ and requires you to already serialize the data
640 /// ahead of time.
641 ///
642 /// \param entity_path Path to the entity in the space hierarchy.
643 /// \param static_ If true, the logged components will be static.
644 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
645 /// any temporal data of the same type.
646 /// Otherwise, the data will be timestamped automatically with `log_time` (and `log_tick`, if enabled).
647 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
648 /// \param batches The serialized batches to log.
649 ///
650 /// \see `log`, `try_log`, `log_static`, `try_log_static`, `try_log_with_static`
652 std::string_view entity_path, bool static_, std::vector<ComponentBatch> batches
653 ) const;
654
655 /// Bottom level API that logs raw data cells to the recording stream.
656 ///
657 /// In order to use this you need to pass serialized Arrow data cells.
658 ///
659 /// \param entity_path Path to the entity in the space hierarchy.
660 /// \param num_data_cells Number of data cells passed in.
661 /// \param data_cells The data cells to log.
662 /// \param inject_time
663 /// If set to `true`, the row's timestamp data will be overridden using the recording
664 /// streams internal clock.
665 ///
666 /// \see `try_log_serialized_batches`
668 std::string_view entity_path, size_t num_data_cells, const ComponentBatch* data_cells,
669 bool inject_time
670 ) const;
671
672 /// Logs the file at the given `path` using all `Importer`s available.
673 ///
674 /// A single `path` might be handled by more than one importer.
675 ///
676 /// This method blocks until either at least one `Importer` starts streaming data in
677 /// or all of them fail.
678 ///
679 /// See <https://www.rerun.io/docs/concepts/logging-and-ingestion/importers/overview> for more information.
680 ///
681 /// \param filepath Path to the file to be logged.
682 /// \param entity_path_prefix What should the logged entity paths be prefixed with?
683 /// \param static_ If true, the logged components will be static.
684 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
685 /// any temporal data of the same type.
686 /// Otherwise, the data will be timestamped automatically with `log_time` (and `log_tick`, if enabled).
687 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
688 ///
689 /// \see `try_log_file_from_path`
691 const std::filesystem::path& filepath,
692 std::string_view entity_path_prefix = std::string_view(), bool static_ = false
693 ) const {
694 try_log_file_from_path(filepath, entity_path_prefix, static_).handle();
695 }
696
697 /// Logs the file at the given `path` using all `Importer`s available.
698 ///
699 /// A single `path` might be handled by more than one importer.
700 ///
701 /// This method blocks until either at least one `Importer` starts streaming data in
702 /// or all of them fail.
703 ///
704 /// See <https://www.rerun.io/docs/concepts/logging-and-ingestion/importers/overview> for more information.
705 ///
706 /// \param filepath Path to the file to be logged.
707 /// \param entity_path_prefix What should the logged entity paths be prefixed with?
708 /// \param static_ If true, the logged components will be static.
709 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
710 /// any temporal data of the same type.
711 /// Otherwise, the data will be timestamped automatically with `log_time` (and `log_tick`, if enabled).
712 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
713 ///
714 /// \see `log_file_from_path`
716 const std::filesystem::path& filepath,
717 std::string_view entity_path_prefix = std::string_view(), bool static_ = false
718 ) const;
719
720 /// Logs the given `contents` using all `Importer`s available.
721 ///
722 /// A single `path` might be handled by more than one importer.
723 ///
724 /// This method blocks until either at least one `Importer` starts streaming data in
725 /// or all of them fail.
726 ///
727 /// See <https://www.rerun.io/docs/concepts/logging-and-ingestion/importers/overview> for more information.
728 ///
729 /// \param filepath Path to the file that the `contents` belong to.
730 /// \param contents Contents to be logged.
731 /// \param contents_size Size in bytes of the `contents`.
732 /// \param entity_path_prefix What should the logged entity paths be prefixed with?
733 /// \param static_ If true, the logged components will be static.
734 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
735 /// any temporal data of the same type.
736 /// Otherwise, the data will be timestamped automatically with `log_time` (and `log_tick`, if enabled).
737 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
738 ///
739 /// \see `try_log_file_from_contents`
741 const std::filesystem::path& filepath, const std::byte* contents, size_t contents_size,
742 std::string_view entity_path_prefix = std::string_view(), bool static_ = false
743 ) const {
745 filepath,
746 contents,
747 contents_size,
748 entity_path_prefix,
749 static_
750 )
751 .handle();
752 }
753
754 /// Logs the given `contents` using all `Importer`s available.
755 ///
756 /// A single `path` might be handled by more than one importer.
757 ///
758 /// This method blocks until either at least one `Importer` starts streaming data in
759 /// or all of them fail.
760 ///
761 /// See <https://www.rerun.io/docs/concepts/logging-and-ingestion/importers/overview> for more information.
762 ///
763 /// \param filepath Path to the file that the `contents` belong to.
764 /// \param contents Contents to be logged.
765 /// \param contents_size Size in bytes of the `contents`.
766 /// \param entity_path_prefix What should the logged entity paths be prefixed with?
767 /// \param static_ If true, the logged components will be static.
768 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
769 /// any temporal data of the same type.
770 /// Otherwise, the data will be timestamped automatically with `log_time` (and `log_tick`, if enabled).
771 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
772 ///
773 /// \see `log_file_from_contents`
775 const std::filesystem::path& filepath, const std::byte* contents, size_t contents_size,
776 std::string_view entity_path_prefix = std::string_view(), bool static_ = false
777 ) const;
778
779 /// Directly log a columns of data to Rerun.
780 ///
781 /// This variant takes in arbitrary amount of `ComponentColumn`s and `ComponentColumn` collections.
782 ///
783 /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data
784 /// in a columnar form. Each `TimeColumn` and `ComponentColumn` represents a column of data that will be sent to Rerun.
785 /// The lengths of all of these columns must match, and all
786 /// data that shares the same index across the different columns will act as a single logical row,
787 /// equivalent to a single call to `RecordingStream::log`.
788 ///
789 /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs.
790 /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns.
791 ///
792 /// Any failures that may occur during serialization are handled with `Error::handle`.
793 ///
794 /// \param entity_path Path to the entity in the space hierarchy.
795 /// \param time_columns The time columns to send.
796 /// \param component_columns The columns of components to send. Both individual `ComponentColumn`s and `Collection<ComponentColumn>`s are accepted.
797 /// \see `try_send_columns`
798 template <typename... Ts>
800 std::string_view entity_path, Collection<TimeColumn> time_columns,
801 Ts... component_columns // NOLINT
802 ) const {
803 try_send_columns(entity_path, time_columns, component_columns...).handle();
804 }
805
806 /// Directly log a columns of data to Rerun.
807 ///
808 /// This variant takes in arbitrary amount of `ComponentColumn`s and `ComponentColumn` collections.
809 ///
810 /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data
811 /// in a columnar form. Each `TimeColumn` and `ComponentColumn` represents a column of data that will be sent to Rerun.
812 /// The lengths of all of these columns must match, and all
813 /// data that shares the same index across the different columns will act as a single logical row,
814 /// equivalent to a single call to `RecordingStream::log`.
815 ///
816 /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs.
817 /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns.
818 ///
819 /// \param entity_path Path to the entity in the space hierarchy.
820 /// \param time_columns The time columns to send.
821 /// \param component_columns The columns of components to send. Both individual `ComponentColumn`s and `Collection<ComponentColumn>`s are accepted.
822 /// \see `send_columns`
823 template <typename... Ts>
825 std::string_view entity_path, Collection<TimeColumn> time_columns,
826 Ts... component_columns // NOLINT
827 ) const {
828 if constexpr (sizeof...(Ts) == 1) {
829 // Directly forward if this is only a single element,
830 // skipping collection of component column vector.
831 return try_send_columns(
832 entity_path,
833 std::move(time_columns),
834 Collection(std::forward<Ts...>(component_columns...))
835 );
836 }
837
838 std::vector<ComponentColumn> flat_column_list;
839 (
840 [&] {
841 static_assert(
842 std::is_same_v<std::remove_cv_t<Ts>, ComponentColumn> ||
843 std::is_constructible_v<Collection<ComponentColumn>, Ts>,
844 "Ts must be ComponentColumn or a collection thereof"
845 );
846
847 push_back_columns(flat_column_list, std::move(component_columns));
848 }(),
849 ...
850 );
851 return try_send_columns(
852 entity_path,
853 std::move(time_columns),
854 // Need to create collection explicitly, otherwise this becomes a recursive call.
855 Collection<ComponentColumn>(std::move(flat_column_list))
856 );
857 }
858
859 /// Directly log a columns of data to Rerun.
860 ///
861 /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data
862 /// in a columnar form. Each `TimeColumn` and `ComponentColumn` represents a column of data that will be sent to Rerun.
863 /// The lengths of all of these columns must match, and all
864 /// data that shares the same index across the different columns will act as a single logical row,
865 /// equivalent to a single call to `RecordingStream::log`.
866 ///
867 /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs.
868 /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns.
869 ///
870 /// Any failures that may occur during serialization are handled with `Error::handle`.
871 ///
872 /// \param entity_path Path to the entity in the space hierarchy.
873 /// \param time_columns The time columns to send.
874 /// \param component_columns The columns of components to send.
875 /// \see `try_send_columns`
877 std::string_view entity_path, Collection<TimeColumn> time_columns,
878 Collection<ComponentColumn> component_columns
879 ) const {
880 try_send_columns(entity_path, time_columns, component_columns).handle();
881 }
882
883 /// Directly log a columns of data to Rerun.
884 ///
885 /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data
886 /// in a columnar form. Each `TimeColumn` and `ComponentColumn` represents a column of data that will be sent to Rerun.
887 /// The lengths of all of these columns must match, and all
888 /// data that shares the same index across the different columns will act as a single logical row,
889 /// equivalent to a single call to `RecordingStream::log`.
890 ///
891 /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs.
892 /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns.
893 ///
894 /// \param entity_path Path to the entity in the space hierarchy.
895 /// \param time_columns The time columns to send.
896 /// \param component_columns The columns of components to send.
897 /// \see `send_columns`
899 std::string_view entity_path, Collection<TimeColumn> time_columns,
900 Collection<ComponentColumn> component_columns
901 ) const;
902
903 /// Set a property of a recording.
904 ///
905 /// Any failures that may occur during serialization are handled with `Error::handle`.
906 ///
907 /// \param name The name of the property.
908 /// \param values The values of the property.
909 /// \see `try_send_property`
910 template <typename... Ts>
911 void send_property(std::string_view name, const Ts&... values) const {
912 try_send_property(name, values...).handle();
913 }
914
915 /// Set a property of a recording.
916 ///
917 /// Any failures that may occur during serialization are handled with `Error::handle`.
918 ///
919 /// \param name The name of the property.
920 /// \param values The values of the property.
921 /// \see `set_property`
922 template <typename... Ts>
923 Error try_send_property(std::string_view name, const Ts&... values) const {
924 return try_log_static(
925 this->PROPERTIES_ENTITY_PATH + std::string(name),
926 values... // NOLINT
927 );
928 }
929
930 /// Set the name of a recording.
931 ///
932 /// Any failures that may occur during serialization are handled with `Error::handle`.
933 ///
934 /// \param name The name of the recording.
935 /// \see `try_send_recording_name`
936 void send_recording_name(std::string_view name) const {
938 }
939
940 /// Set the name of a recording.
941 ///
942 /// \param name The name of the recording.
943 /// \see `send_recording_name`
944 Error try_send_recording_name(std::string_view name) const;
945
946 /// Set the start time of a recording.
947 ///
948 /// Any failures that may occur during serialization are handled with `Error::handle`.
949 ///
950 /// \param nanos The timestamp of the recording in nanoseconds since Unix epoch.
951 /// \see `try_send_recording_start_time`
952 void send_recording_start_time_nanos(int64_t nanos) const {
954 }
955
956 /// Set the start time of a recording.
957 ///
958 /// \param nanos The timestamp of the recording in nanoseconds since Unix epoch.
959 /// \see `set_name`
961
962 /// @}
963
964 private:
965 Error try_set_sinks(const LogSink* sinks, uint32_t num_sinks) const;
966
967 // Utility function to implement `try_send_columns` variadic template.
968 static void push_back_columns(
969 std::vector<ComponentColumn>& component_columns, Collection<ComponentColumn> new_columns
970 ) {
971 for (const auto& new_column : new_columns) {
972 component_columns.emplace_back(std::move(new_column));
973 }
974 }
975
976 static void push_back_columns(
977 std::vector<ComponentColumn>& component_columns, ComponentColumn new_column
978 ) {
979 component_columns.emplace_back(std::move(new_column));
980 }
981
982 RecordingStream(uint32_t id, StoreKind store_kind);
983
984 uint32_t _id;
985 StoreKind _store_kind;
986 bool _enabled;
987 };
988} // namespace rerun
Generic collection of elements that are roughly contiguous in memory.
Definition collection.hpp:49
Status outcome object (success or error) returned for fallible operations.
Definition error.hpp:103
void handle() const
Handle this error based on the set log handler.
bool is_err() const
Returns true if the code is not Ok.
Definition error.hpp:139
static Error ok()
Creates a new error set to ok.
Definition error.hpp:124
A RecordingStream handles everything related to logging data into Rerun.
Definition recording_stream.hpp:63
Error try_log_with_static(std::string_view entity_path, bool static_, const Ts &... as_components) const
Logs one or more archetype and/or component batches optionally static, returning an error.
Definition recording_stream.hpp:598
Error try_send_property(std::string_view name, const Ts &... values) const
Set a property of a recording.
Definition recording_stream.hpp:923
void set_log_time_enabled(bool enabled) const
Enable or disable automatic injection of the log_time timeline into logged data.
Error try_send_columns(std::string_view entity_path, Collection< TimeColumn > time_columns, Collection< ComponentColumn > component_columns) const
Directly log a columns of data to Rerun.
void log_file_from_path(const std::filesystem::path &filepath, std::string_view entity_path_prefix=std::string_view(), bool static_=false) const
Logs the file at the given path using all Importers available.
Definition recording_stream.hpp:690
bool is_enabled() const
Returns whether the recording stream is enabled.
Definition recording_stream.hpp:107
void set_time_duration_nanos(std::string_view timeline_name, int64_t nanos) const
Set the index value of the given timeline as a duration in nanoseconds, for the current calling threa...
void send_property(std::string_view name, const Ts &... values) const
Set a property of a recording.
Definition recording_stream.hpp:911
Error try_send_recording_start_time_nanos(int64_t nanos) const
Set the start time of a recording.
Error try_log(std::string_view entity_path, const Ts &... as_components) const
Logs one or more archetype and/or component batches.
Definition recording_stream.hpp:531
void disable_timeline(std::string_view timeline_name) const
Stops logging to the specified timeline for subsequent log calls.
void reset_time() const
Clears out the current time of the recording, for the current calling thread.
Error to_stdout() const
Stream all log-data to standard output.
void send_columns(std::string_view entity_path, Collection< TimeColumn > time_columns, Collection< ComponentColumn > component_columns) const
Directly log a columns of data to Rerun.
Definition recording_stream.hpp:876
Error try_log_file_from_path(const std::filesystem::path &filepath, std::string_view entity_path_prefix=std::string_view(), bool static_=false) const
Logs the file at the given path using all Importers available.
Error save(std::string_view path) const
Stream all log-data to a given .rrd file.
Error try_log_static(std::string_view entity_path, const Ts &... as_components) const
Logs one or more archetype and/or component batches as static data, returning an error.
Definition recording_stream.hpp:551
StoreKind kind() const
Returns the store kind as passed during construction.
Definition recording_stream.hpp:99
Error flush_blocking(float timeout_sec=std::numeric_limits< float >::infinity()) const
Initiates a flush the batching pipeline and waits for it to propagate.
Error spawn(const SpawnOptions &options={}, std::chrono::duration< TRep, TPeriod > flush_timeout=std::chrono::seconds(2)) const
Definition recording_stream.hpp:197
Error try_log_data_row(std::string_view entity_path, size_t num_data_cells, const ComponentBatch *data_cells, bool inject_time) const
Bottom level API that logs raw data cells to the recording stream.
void log_file_from_contents(const std::filesystem::path &filepath, const std::byte *contents, size_t contents_size, std::string_view entity_path_prefix=std::string_view(), bool static_=false) const
Logs the given contents using all Importers available.
Definition recording_stream.hpp:740
void set_time_timestamp_secs_since_epoch(std::string_view timeline_name, double seconds) const
Set the index value of the given timeline as seconds since Unix Epoch (1970), for the current calling...
Definition recording_stream.hpp:327
void set_time_duration_secs(std::string_view timeline_name, double secs) const
Set the index value of the given timeline as a duration in seconds, for the current calling thread.
Definition recording_stream.hpp:283
void set_time_duration(std::string_view timeline_name, std::chrono::duration< TRep, TPeriod > duration) const
Set the index value of the given timeline as a duration, for the current calling thread.
Definition recording_stream.hpp:267
Error set_sinks(const Ts &... sinks) const
Stream data to multiple sinks.
Definition recording_stream.hpp:154
void set_time_nanos(std::string_view timeline_name, int64_t nanos) const
Set the current time of the recording, for the current calling thread.
Definition recording_stream.hpp:406
void set_time(std::string_view timeline_name, std::chrono::duration< TRep, TPeriod > time) const
Set the current time of the recording, for the current calling thread.
Definition recording_stream.hpp:373
Result< std::string > serve_grpc(std::string_view bind_ip="0.0.0.0", uint16_t port=9876, std::string_view server_memory_limit="1GiB", PlaybackBehavior playback_behavior=PlaybackBehavior::OldestFirst, std::vector< std::string > cors_allow_origins={}) const
Swaps the underlying sink for a gRPC server sink pre-configured to listen on rerun+http://{bind_ip}:{...
void send_recording_start_time_nanos(int64_t nanos) const
Set the start time of a recording.
Definition recording_stream.hpp:952
void log_with_static(std::string_view entity_path, bool static_, const Ts &... as_components) const
Logs one or more archetype and/or component batches optionally static, returning an error.
Definition recording_stream.hpp:575
static RecordingStream & current(StoreKind store_kind=StoreKind::Recording)
Retrieves the most appropriate globally available recording stream for the given kind.
RecordingStream(std::string_view app_id, std::string_view recording_id=std::string_view(), StoreKind store_kind=StoreKind::Recording)
Creates a new recording stream to log to.
void log(std::string_view entity_path, const Ts &... as_components) const
Logs one or more archetype and/or component batches.
Definition recording_stream.hpp:490
void set_thread_local() const
Replaces the currently active recording for this stream's store kind in the thread-local scope with t...
Error try_send_recording_name(std::string_view name) const
Set the name of a recording.
Error try_log_serialized_batches(std::string_view entity_path, bool static_, std::vector< ComponentBatch > batches) const
Logs several serialized batches batches, returning an error on failure.
Error connect_grpc(std::string_view url="rerun+http://127.0.0.1:9876/proxy") const
Connect to a remote Rerun Viewer on the given URL.
void set_time(std::string_view timeline_name, std::chrono::time_point< TClock > time) const
Set the current time of the recording, for the current calling thread.
Definition recording_stream.hpp:357
Error spawn(const SpawnOptions &options={}) const
Spawns a new Rerun Viewer process from an executable available in PATH, then connects to it over gRPC...
void set_time_seconds(std::string_view timeline_name, double seconds) const
Set the current time of the recording, for the current calling thread.
Definition recording_stream.hpp:390
void set_time_timestamp_nanos_since_epoch(std::string_view timeline_name, int64_t nanos) const
Set the index value of the given timeline as nanoseconds since Unix Epoch (1970), for the current cal...
void send_columns(std::string_view entity_path, Collection< TimeColumn > time_columns, Ts... component_columns) const
Directly log a columns of data to Rerun.
Definition recording_stream.hpp:799
Error try_log_file_from_contents(const std::filesystem::path &filepath, const std::byte *contents, size_t contents_size, std::string_view entity_path_prefix=std::string_view(), bool static_=false) const
Logs the given contents using all Importers available.
void send_recording_name(std::string_view name) const
Set the name of a recording.
Definition recording_stream.hpp:936
void set_global() const
Replaces the currently active recording for this stream's store kind in the global scope with this on...
void set_log_tick_enabled(bool enabled) const
Enable or disable automatic injection of the log_tick timeline into logged data.
void set_time_timestamp(std::string_view timeline_name, std::chrono::time_point< TClock > timestamp) const
Set the index value of the given timeline as a timestamp, for the current calling thread.
Definition recording_stream.hpp:308
void set_time_sequence(std::string_view timeline_name, int64_t sequence_nr) const
Set the index value of the given timeline as a sequence number, for the current calling thread.
Error try_send_columns(std::string_view entity_path, Collection< TimeColumn > time_columns, Ts... component_columns) const
Directly log a columns of data to Rerun.
Definition recording_stream.hpp:824
void log_static(std::string_view entity_path, const Ts &... as_components) const
Logs one or more archetype and/or component batches as static data.
Definition recording_stream.hpp:512
A class for representing either a usable value, or an error.
Definition result.hpp:14
bool is_err() const
Returns true if error is not set to rerun::ErrorCode::Ok, implying that no value is contained,...
Definition result.hpp:44
All Rerun C++ types and functions are in the rerun namespace or one of its nested namespaces.
Definition rerun.hpp:23
PlaybackBehavior
What happens when a client connects to a gRPC server.
Definition log_sink.hpp:12
@ OldestFirst
Start by playing back all old data, then send data that arrived during playback.
Arrow-encoded data of a single batch of components together with a component descriptor.
Definition component_batch.hpp:28
Arrow-encoded data of a column of components.
Definition component_column.hpp:20
A sink for log messages.
Definition log_sink.hpp:86
Options to control the behavior of spawn.
Definition spawn_options.hpp:17