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