Rerun C++ SDK
Loading...
Searching...
No Matches
recording_stream.hpp
1#pragma once
2
3#include <chrono>
4#include <cstdint> // uint32_t etc.
5#include <filesystem>
6#include <optional>
7#include <string_view>
8#include <type_traits>
9#include <vector>
10
11#include "as_components.hpp"
12#include "component_column.hpp"
13#include "error.hpp"
14#include "spawn_options.hpp"
15#include "time_column.hpp"
16
17namespace rerun {
18 struct ComponentBatch;
19
20 enum class StoreKind {
21 Recording,
22 Blueprint,
23 };
24
25 /// A `RecordingStream` handles everything related to logging data into Rerun.
26 ///
27 /// ## Multithreading and ordering
28 ///
29 /// A `RecordingStream` is thread-safe.
30 ///
31 /// Internally, all operations are linearized into a pipeline:
32 /// - All operations sent by a given thread will take effect in the same exact order as that
33 /// thread originally sent them in, from its point of view.
34 /// - There isn't any well defined global order across multiple threads.
35 ///
36 /// This means that e.g. flushing the pipeline (`flush_blocking`) guarantees that all
37 /// previous data sent by the calling thread has been recorded; no more, no less.
38 /// (e.g. it does not mean that all file caches are flushed)
39 ///
40 /// ## Shutdown
41 ///
42 /// The `RecordingStream` can only be shutdown by dropping all instances of it, at which point
43 /// it will automatically take care of flushing any pending data that might remain in the
44 /// pipeline.
45 ///
46 /// TODO(andreas): The only way of having two instances of a `RecordingStream` is currently to
47 /// set it as a the global.
48 ///
49 /// Shutting down cannot ever block.
50 ///
51 /// ## Logging
52 ///
53 /// Internally, the stream will automatically micro-batch multiple log calls to optimize
54 /// transport.
55 /// See [SDK Micro Batching](https://www.rerun.io/docs/reference/sdk/micro-batching) for
56 /// more information.
57 ///
58 /// The data will be timestamped automatically based on the `RecordingStream`'s
59 /// internal clock.
61 public:
62 /// Creates a new recording stream to log to.
63 ///
64 /// \param app_id The user-chosen name of the application doing the logging.
65 /// \param recording_id The user-chosen name of the recording being logged to.
66 /// \param store_kind Whether to log to the recording store or the blueprint store.
68 std::string_view app_id, std::string_view recording_id = std::string_view(),
69 StoreKind store_kind = StoreKind::Recording
70 );
72
73 /// \private
75
76 // TODO(andreas): We could easily make the recording stream trivial to copy by bumping Rusts
77 // ref counter by adding a copy of the recording stream to the list of C recording streams.
78 // Doing it this way would likely yield the most consistent behavior when interacting with
79 // global streams (and especially when interacting with different languages in the same
80 // application).
81 /// \private
82 RecordingStream(const RecordingStream&) = delete;
83 /// \private
84 RecordingStream() = delete;
85
86 // -----------------------------------------------------------------------------------------
87 /// \name Properties
88 /// @{
89
90 /// Returns the store kind as passed during construction
91 StoreKind kind() const {
92 return _store_kind;
93 }
94
95 /// Returns whether the recording stream is enabled.
96 ///
97 /// All log functions early out if a recording stream is disabled.
98 /// Naturally, logging functions that take unserialized data will skip the serialization step as well.
99 bool is_enabled() const {
100 return _enabled;
101 }
102
103 /// @}
104
105 // -----------------------------------------------------------------------------------------
106 /// \name Controlling globally available instances of RecordingStream.
107 /// @{
108
109 /// Replaces the currently active recording for this stream's store kind in the global scope
110 /// with this one.
111 ///
112 /// Afterwards, destroying this recording stream will *not* change the global recording
113 /// stream, as it increases an internal ref-count.
114 void set_global() const;
115
116 /// Replaces the currently active recording for this stream's store kind in the thread-local
117 /// scope with this one
118 ///
119 /// Afterwards, destroying this recording stream will *not* change the thread local
120 /// recording stream, as it increases an internal ref-count.
121 void set_thread_local() const;
122
123 /// Retrieves the most appropriate globally available recording stream for the given kind.
124 ///
125 /// I.e. thread-local first, then global.
126 /// If neither was set, any operations on the returned stream will be no-ops.
127 static RecordingStream& current(StoreKind store_kind = StoreKind::Recording);
128
129 /// @}
130
131 // -----------------------------------------------------------------------------------------
132 /// \name Directing the recording stream.
133 /// \details Either of these needs to be called, otherwise the stream will buffer up indefinitely.
134 /// @{
135
136 /// Connect to a remote Rerun Viewer on the given ip:port.
137 ///
138 /// Requires that you first start a Rerun Viewer by typing 'rerun' in a terminal.
139 ///
140 /// flush_timeout_sec:
141 /// The minimum time the SDK will wait during a flush before potentially
142 /// dropping data if progress is not being made. Passing a negative value indicates no
143 /// timeout, and can cause a call to `flush` to block indefinitely.
144 ///
145 /// This function returns immediately.
146 [[deprecated("Use `connect_tcp` instead")]] Error connect(
147 std::string_view tcp_addr = "127.0.0.1:9876", float flush_timeout_sec = 2.0
148 ) const;
149
150 /// Connect to a remote Rerun Viewer on the given ip:port.
151 ///
152 /// Requires that you first start a Rerun Viewer by typing 'rerun' in a terminal.
153 ///
154 /// flush_timeout_sec:
155 /// The minimum time the SDK will wait during a flush before potentially
156 /// dropping data if progress is not being made. Passing a negative value indicates no
157 /// timeout, and can cause a call to `flush` to block indefinitely.
158 ///
159 /// This function returns immediately.
161 std::string_view tcp_addr = "127.0.0.1:9876", float flush_timeout_sec = 2.0
162 ) const;
163
164 /// Spawns a new Rerun Viewer process from an executable available in PATH, then connects to it
165 /// over TCP.
166 ///
167 /// If a Rerun Viewer is already listening on this TCP port, the stream will be redirected to
168 /// that viewer instead of starting a new one.
169 ///
170 /// ## Parameters
171 /// options:
172 /// See `rerun::SpawnOptions` for more information.
173 ///
174 /// flush_timeout_sec:
175 /// The minimum time the SDK will wait during a flush before potentially
176 /// dropping data if progress is not being made. Passing a negative value indicates no
177 /// timeout, and can cause a call to `flush` to block indefinitely.
178 Error spawn(const SpawnOptions& options = {}, float flush_timeout_sec = 2.0) const;
179
180 /// @see RecordingStream::spawn
181 template <typename TRep, typename TPeriod>
183 const SpawnOptions& options = {},
184 std::chrono::duration<TRep, TPeriod> flush_timeout = std::chrono::seconds(2)
185 ) const {
186 using seconds_float = std::chrono::duration<float>; // Default ratio is 1:1 == seconds.
187 return spawn(options, std::chrono::duration_cast<seconds_float>(flush_timeout).count());
188 }
189
190 /// Stream all log-data to a given `.rrd` file.
191 ///
192 /// The Rerun Viewer is able to read continuously from the resulting rrd file while it is being written.
193 /// However, depending on your OS and configuration, changes may not be immediately visible due to file caching.
194 /// This is a common issue on Windows and (to a lesser extent) on MacOS.
195 ///
196 /// This function returns immediately.
197 Error save(std::string_view path) const;
198
199 /// Stream all log-data to standard output.
200 ///
201 /// Pipe the result into the Rerun Viewer to visualize it.
202 ///
203 /// If there isn't any listener at the other end of the pipe, the `RecordingStream` will
204 /// default back to `buffered` mode, in order not to break the user's terminal.
205 ///
206 /// This function returns immediately.
207 //
208 // NOTE: This should be called `stdout` like in other SDK, but turns out that `stdout` is a
209 // macro when compiling with msvc [1].
210 // [1]: https://learn.microsoft.com/en-us/cpp/c-runtime-library/stdin-stdout-stderr?view=msvc-170
212
213 /// Initiates a flush the batching pipeline and waits for it to propagate.
214 ///
215 /// See `RecordingStream` docs for ordering semantics and multithreading guarantees.
216 void flush_blocking() const;
217
218 /// @}
219
220 // -----------------------------------------------------------------------------------------
221 /// \name Controlling log time.
222 /// \details
223 /// @{
224
225 /// Set the current time of the recording, for the current calling thread.
226 ///
227 /// Used for all subsequent logging performed from this same thread, until the next call
228 /// to one of the time setting methods.
229 ///
230 /// For example: `rec.set_time_sequence("frame_nr", frame_nr)`.
231 ///
232 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
233 /// @see set_time_seconds, set_time_nanos, reset_time, set_time, disable_timeline
234 void set_time_sequence(std::string_view timeline_name, int64_t sequence_nr) const;
235
236 /// Set the current time of the recording, for the current calling thread.
237 ///
238 /// Used for all subsequent logging performed from this same thread, until the next call
239 /// to one of the time setting methods.
240 ///
241 /// For example: `rec.set_time("sim_time", sim_time_secs)`.
242 ///
243 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
244 /// @see set_time_sequence, set_time_seconds, set_time_nanos, reset_time, disable_timeline
245 template <typename TClock>
246 void set_time(std::string_view timeline_name, std::chrono::time_point<TClock> time) const {
247 set_time(timeline_name, time.time_since_epoch());
248 }
249
250 /// Set the current time of the recording, for the current calling thread.
251 ///
252 /// Used for all subsequent logging performed from this same thread, until the next call
253 /// to one of the time setting methods.
254 ///
255 /// For example: `rec.set_time("sim_time", sim_time_secs)`.
256 ///
257 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
258 /// @see set_time_sequence, set_time_seconds, set_time_nanos, reset_time, disable_timeline
259 template <typename TRep, typename TPeriod>
260 void set_time(std::string_view timeline_name, std::chrono::duration<TRep, TPeriod> time)
261 const {
262 if constexpr (std::is_floating_point<TRep>::value) {
263 using seconds_double =
264 std::chrono::duration<double>; // Default ratio is 1:1 == seconds.
266 timeline_name,
267 std::chrono::duration_cast<seconds_double>(time).count()
268 );
269 } else {
271 timeline_name,
272 std::chrono::duration_cast<std::chrono::nanoseconds>(time).count()
273 );
274 }
275 }
276
277 /// Set the current time of the recording, 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_seconds("sim_time", sim_time_secs)`.
283 ///
284 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
285 /// @see set_time_sequence, set_time_nanos, reset_time, set_time, disable_timeline
286 void set_time_seconds(std::string_view timeline_name, double seconds) const;
287
288 /// Set the current time of the recording, for the current calling thread.
289 ///
290 /// Used for all subsequent logging performed from this same thread, until the next call
291 /// to one of the time setting methods.
292 ///
293 /// For example: `rec.set_time_nanos("sim_time", sim_time_nanos)`.
294 ///
295 /// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
296 /// @see set_time_sequence, set_time_seconds, reset_time, set_time, disable_timeline
297 void set_time_nanos(std::string_view timeline_name, int64_t nanos) const;
298
299 /// Stops logging to the specified timeline for subsequent log calls.
300 ///
301 /// The timeline is still there, but will not be updated with any new data.
302 ///
303 /// No-op if the timeline doesn't exist.
304 ///
305 /// @see set_time_sequence, set_time_seconds, set_time, reset_time
306 void disable_timeline(std::string_view timeline_name) const;
307
308 /// Clears out the current time of the recording, for the current calling thread.
309 ///
310 /// Used for all subsequent logging performed from this same thread, until the next call
311 /// to one of the time setting methods.
312 ///
313 /// For example: `rec.reset_time()`.
314 /// @see set_time_sequence, set_time_seconds, set_time_nanos, disable_timeline
315 void reset_time() const;
316
317 /// @}
318
319 // -----------------------------------------------------------------------------------------
320 /// \name Sending & logging data.
321 /// @{
322
323 /// Logs one or more archetype and/or component batches.
324 ///
325 /// This is the main entry point for logging data to rerun. It can be used to log anything
326 /// that implements the `AsComponents<T>` trait.
327 ///
328 /// When logging data, you must always provide an [entity_path](https://www.rerun.io/docs/concepts/entity-path)
329 /// for identifying the data. Note that the path prefix "rerun/" is considered reserved for use by the Rerun SDK
330 /// itself and should not be used for logging user data. This is where Rerun will log additional information
331 /// such as warnings.
332 ///
333 /// The most common way to log is with one of the rerun archetypes, all of which implement the `AsComponents` trait.
334 ///
335 /// For example, to log two 3D points:
336 /// ```
337 /// rec.log("my/point", rerun::Points3D({{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}}));
338 /// ```
339 ///
340 /// The `log` function can flexibly accept an arbitrary number of additional objects which will
341 /// be merged into the first entity so long as they don't expose conflicting components, for instance:
342 /// ```
343 /// // Log three points with arrows sticking out of them:
344 /// rec.log(
345 /// "my/points",
346 /// rerun::Points3D({{0.2f, 0.5f, 0.3f}, {0.9f, 1.2f, 0.1f}, {1.0f, 4.2f, 0.3f}})
347 /// .with_radii({0.1, 0.2, 0.3}),
348 /// rerun::Arrows3D::from_vectors({{0.3f, 2.1f, 0.2f}, {0.9f, -1.1, 2.3f}, {-0.4f, 0.5f, 2.9f}})
349 /// );
350 /// ```
351 ///
352 /// Any failures that may occur during serialization are handled with `Error::handle`.
353 ///
354 /// \param entity_path Path to the entity in the space hierarchy.
355 /// \param archetypes_or_collections Any type for which the `AsComponents<T>` trait is implemented.
356 /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements.
357 ///
358 /// @see try_log, log_static, try_log_with_static
359 template <typename... Ts>
360 void log(std::string_view entity_path, const Ts&... archetypes_or_collections) const {
361 if (!is_enabled()) {
362 return;
363 }
364 try_log_with_static(entity_path, false, archetypes_or_collections...).handle();
365 }
366
367 template <typename... Ts>
368 [[deprecated("Use `log_static` instead")]] void log_timeless(
369 std::string_view entity_path, const Ts&... archetypes_or_collections
370 ) const {
371 return log_static(entity_path, archetypes_or_collections...);
372 }
373
374 /// Logs one or more archetype and/or component batches as static data.
375 ///
376 /// Like `log` but logs the data as static:
377 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
378 /// any temporal data of the same type.
379 ///
380 /// Failures are handled with `Error::handle`.
381 ///
382 /// \param entity_path Path to the entity in the space hierarchy.
383 /// \param archetypes_or_collections Any type for which the `AsComponents<T>` trait is implemented.
384 /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements.
385 ///
386 /// @see log, try_log_static, try_log_with_static
387 template <typename... Ts>
388 void log_static(std::string_view entity_path, const Ts&... archetypes_or_collections)
389 const {
390 if (!is_enabled()) {
391 return;
392 }
393 try_log_with_static(entity_path, true, archetypes_or_collections...).handle();
394 }
395
396 /// Logs one or more archetype and/or component batches.
397 ///
398 /// See `log` for more information.
399 /// Unlike `log` this method returns an error if an error occurs during serialization or logging.
400 ///
401 /// \param entity_path Path to the entity in the space hierarchy.
402 /// \param archetypes_or_collections Any type for which the `AsComponents<T>` trait is implemented.
403 /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements.
404 ///
405 /// @see log, try_log_static, try_log_with_static
406 template <typename... Ts>
407 Error try_log(std::string_view entity_path, const Ts&... archetypes_or_collections) const {
408 if (!is_enabled()) {
409 return Error::ok();
410 }
411 return try_log_with_static(entity_path, false, archetypes_or_collections...);
412 }
413
414 template <typename... Ts>
415 [[deprecated("Use `try_log_static` instead")]] Error try_log_timeless(
416 std::string_view entity_path, const Ts&... archetypes_or_collections
417 ) const {
418 return try_log_static(entity_path, archetypes_or_collections...);
419 }
420
421 /// Logs one or more archetype and/or component batches as static data, returning an error.
422 ///
423 /// See `log`/`log_static` for more information.
424 /// Unlike `log_static` this method returns if an error occurs during serialization or logging.
425 ///
426 /// \param entity_path Path to the entity in the space hierarchy.
427 /// \param archetypes_or_collections Any type for which the `AsComponents<T>` trait is implemented.
428 /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements.
429 /// \returns An error if an error occurs during serialization or logging.
430 ///
431 /// @see log_static, try_log, try_log_with_static
432 template <typename... Ts>
433 Error try_log_static(std::string_view entity_path, const Ts&... archetypes_or_collections)
434 const {
435 if (!is_enabled()) {
436 return Error::ok();
437 }
438 return try_log_with_static(entity_path, true, archetypes_or_collections...);
439 }
440
441 template <typename... Ts>
442 [[deprecated("Use `log_with_static` instead")]] void log_with_timeless(
443 std::string_view entity_path, bool timeless, const Ts&... archetypes_or_collections
444 ) const {
445 return log_with_static(entity_path, timeless, archetypes_or_collections...);
446 }
447
448 /// Logs one or more archetype and/or component batches optionally static, returning an error.
449 ///
450 /// See `log`/`log_static` for more information.
451 /// Returns an error if an error occurs during serialization or logging.
452 ///
453 /// \param entity_path Path to the entity in the space hierarchy.
454 /// \param static_ If true, the logged components will be static.
455 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
456 /// any temporal data of the same type.
457 /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`.
458 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
459 /// \param archetypes_or_collections Any type for which the `AsComponents<T>` trait is implemented.
460 /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements.
461 ///
462 /// @see log, try_log, log_static, try_log_static
463 template <typename... Ts>
465 std::string_view entity_path, bool static_, const Ts&... archetypes_or_collections
466 ) const {
467 try_log_with_static(entity_path, static_, archetypes_or_collections...).handle();
468 }
469
470 template <typename... Ts>
471 [[deprecated("Use `try_log_with_static` instead")]] Error try_log_with_timeless(
472 std::string_view entity_path, bool static_, const Ts&... archetypes_or_collections
473 ) const {
474 return try_log_with_static(entity_path, static_, archetypes_or_collections...);
475 }
476
477 /// Logs one or more archetype and/or component batches optionally static, returning an error.
478 ///
479 /// See `log`/`log_static` for more information.
480 /// Returns an error if an error occurs during serialization or logging.
481 ///
482 /// \param entity_path Path to the entity in the space hierarchy.
483 /// \param static_ If true, the logged components will be static.
484 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
485 /// any temporal data of the same type.
486 /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`.
487 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
488 /// \param archetypes_or_collections Any type for which the `AsComponents<T>` trait is implemented.
489 /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements.
490 /// \returns An error if an error occurs during serialization or logging.
491 ///
492 /// @see log, try_log, log_static, try_log_static
493 template <typename... Ts>
495 std::string_view entity_path, bool static_, const Ts&... archetypes_or_collections
496 ) const {
497 if (!is_enabled()) {
498 return Error::ok();
499 }
500 std::vector<ComponentBatch> serialized_columns;
501 Error err;
502 (
503 [&] {
504 if (err.is_err()) {
505 return;
506 }
507
508 const Result<std::vector<ComponentBatch>> serialization_result =
509 AsComponents<Ts>().serialize(archetypes_or_collections);
510 if (serialization_result.is_err()) {
511 err = serialization_result.error;
512 return;
513 }
514
515 if (serialized_columns.empty()) {
516 // Fast path for the first batch (which is usually the only one!)
517 serialized_columns = std::move(serialization_result.value);
518 } else {
519 serialized_columns.insert(
520 serialized_columns.end(),
521 std::make_move_iterator(serialization_result.value.begin()),
522 std::make_move_iterator(serialization_result.value.end())
523 );
524 }
525 }(),
526 ...
527 );
528 RR_RETURN_NOT_OK(err);
529
530 return try_log_serialized_batches(entity_path, static_, std::move(serialized_columns));
531 }
532
533 /// Logs several serialized batches batches, returning an error on failure.
534 ///
535 /// This is a more low-level API than `log`/`log_static\ and requires you to already serialize the data
536 /// ahead of time.
537 ///
538 /// \param entity_path Path to the entity in the space hierarchy.
539 /// \param static_ If true, the logged components will be static.
540 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
541 /// any temporal data of the same type.
542 /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`.
543 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
544 /// \param batches The serialized batches to log.
545 ///
546 /// \see `log`, `try_log`, `log_static`, `try_log_static`, `try_log_with_static`
548 std::string_view entity_path, bool static_, std::vector<ComponentBatch> batches
549 ) const;
550
551 /// Bottom level API that logs raw data cells to the recording stream.
552 ///
553 /// In order to use this you need to pass serialized Arrow data cells.
554 ///
555 /// \param entity_path Path to the entity in the space hierarchy.
556 /// \param num_data_cells Number of data cells passed in.
557 /// \param data_cells The data cells to log.
558 /// \param inject_time
559 /// If set to `true`, the row's timestamp data will be overridden using the recording
560 /// streams internal clock.
561 ///
562 /// \see `try_log_serialized_batches`
564 std::string_view entity_path, size_t num_data_cells, const ComponentBatch* data_cells,
565 bool inject_time
566 ) const;
567
568 /// Logs the file at the given `path` using all `DataLoader`s available.
569 ///
570 /// A single `path` might be handled by more than one loader.
571 ///
572 /// This method blocks until either at least one `DataLoader` starts streaming data in
573 /// or all of them fail.
574 ///
575 /// See <https://www.rerun.io/docs/reference/data-loaders/overview> for more information.
576 ///
577 /// \param filepath Path to the file to be logged.
578 /// \param entity_path_prefix What should the logged entity paths be prefixed with?
579 /// \param static_ If true, the logged components will be static.
580 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
581 /// any temporal data of the same type.
582 /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`.
583 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
584 ///
585 /// \see `try_log_file_from_path`
587 const std::filesystem::path& filepath,
588 std::string_view entity_path_prefix = std::string_view(), bool static_ = false
589 ) const {
590 try_log_file_from_path(filepath, entity_path_prefix, static_).handle();
591 }
592
593 /// Logs the file at the given `path` using all `DataLoader`s available.
594 ///
595 /// A single `path` might be handled by more than one loader.
596 ///
597 /// This method blocks until either at least one `DataLoader` starts streaming data in
598 /// or all of them fail.
599 ///
600 /// See <https://www.rerun.io/docs/reference/data-loaders/overview> for more information.
601 ///
602 /// \param filepath Path to the file to be logged.
603 /// \param entity_path_prefix What should the logged entity paths be prefixed with?
604 /// \param static_ If true, the logged components will be static.
605 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
606 /// any temporal data of the same type.
607 /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`.
608 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
609 ///
610 /// \see `log_file_from_path`
612 const std::filesystem::path& filepath,
613 std::string_view entity_path_prefix = std::string_view(), bool static_ = false
614 ) const;
615
616 /// Logs the given `contents` using all `DataLoader`s available.
617 ///
618 /// A single `path` might be handled by more than one loader.
619 ///
620 /// This method blocks until either at least one `DataLoader` starts streaming data in
621 /// or all of them fail.
622 ///
623 /// See <https://www.rerun.io/docs/reference/data-loaders/overview> for more information.
624 ///
625 /// \param filepath Path to the file that the `contents` belong to.
626 /// \param contents Contents to be logged.
627 /// \param contents_size Size in bytes of the `contents`.
628 /// \param entity_path_prefix What should the logged entity paths be prefixed with?
629 /// \param static_ If true, the logged components will be static.
630 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
631 /// any temporal data of the same type.
632 /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`.
633 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
634 ///
635 /// \see `try_log_file_from_contents`
637 const std::filesystem::path& filepath, const std::byte* contents, size_t contents_size,
638 std::string_view entity_path_prefix = std::string_view(), bool static_ = false
639 ) const {
641 filepath,
642 contents,
643 contents_size,
644 entity_path_prefix,
645 static_
646 )
647 .handle();
648 }
649
650 /// Logs the given `contents` using all `DataLoader`s available.
651 ///
652 /// A single `path` might be handled by more than one loader.
653 ///
654 /// This method blocks until either at least one `DataLoader` starts streaming data in
655 /// or all of them fail.
656 ///
657 /// See <https://www.rerun.io/docs/reference/data-loaders/overview> for more information.
658 ///
659 /// \param filepath Path to the file that the `contents` belong to.
660 /// \param contents Contents to be logged.
661 /// \param contents_size Size in bytes of the `contents`.
662 /// \param entity_path_prefix What should the logged entity paths be prefixed with?
663 /// \param static_ If true, the logged components will be static.
664 /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows
665 /// any temporal data of the same type.
666 /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`.
667 /// Additional timelines set by `set_time_sequence` or `set_time` will also be included.
668 ///
669 /// \see `log_file_from_contents`
671 const std::filesystem::path& filepath, const std::byte* contents, size_t contents_size,
672 std::string_view entity_path_prefix = std::string_view(), bool static_ = false
673 ) const;
674
675 /// Directly log a columns of data to Rerun.
676 ///
677 /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data
678 /// in a columnar form. Each `TimeColumn` and `Collection<T>` represents a column of data that will be sent to Rerun.
679 /// The lengths of all of these columns must match, equivalent to a single call to `RecordingStream::log` with a list
680 /// of individual components.
681 ///
682 /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs.
683 /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns.
684 ///
685 /// Any failures that may occur during serialization are handled with `Error::handle`.
686 ///
687 /// \param entity_path Path to the entity in the space hierarchy.
688 /// \param time_columns The time columns to send.
689 /// \param component_columns The columns of components to send.
690 /// Each individual component in each collection will be associated with a single time value.
691 /// I.e. this creates `ComponentColumn` objects consisting of single component runs.
692 /// \see `try_send_columns`
693 template <typename... Ts>
695 std::string_view entity_path, Collection<TimeColumn> time_columns,
696 Collection<Ts>... component_columns // NOLINT
697 ) const {
698 try_send_columns(entity_path, time_columns, component_columns...).handle();
699 }
700
701 /// Directly log a columns of data to Rerun.
702 ///
703 /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data
704 /// in a columnar form. Each `TimeColumn` and `Collection<T>` represents a column of data that will be sent to Rerun.
705 /// The lengths of all of these columns must match, equivalent to a single call to `RecordingStream::log` with a list
706 /// of individual components.
707 ///
708 /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs.
709 /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns.
710 ///
711 /// \param entity_path Path to the entity in the space hierarchy.
712 /// \param time_columns The time columns to send.
713 /// \param component_columns The columns of components to send.
714 /// Each individual component in each collection will be associated with a single time value.
715 /// I.e. this creates `ComponentColumn` objects consisting of single component runs.
716 /// \see `send_columns`
717 template <typename... Ts>
719 std::string_view entity_path, Collection<TimeColumn> time_columns,
720 Collection<Ts>... component_columns // NOLINT
721 ) const {
722 if (!is_enabled()) {
723 return Error::ok();
724 }
725 std::vector<ComponentColumn> serialized_columns;
726 Error err;
727 (
728 [&] {
729 if (err.is_err()) {
730 return;
731 }
732
733 const Result<ComponentColumn> serialization_result =
734 ComponentColumn::from_loggable(component_columns);
735 if (serialization_result.is_err()) {
736 err = serialization_result.error;
737 return;
738 }
739 serialized_columns.emplace_back(std::move(serialization_result.value));
740 }(),
741 ...
742 );
743 RR_RETURN_NOT_OK(err);
744
745 return try_send_columns(entity_path, time_columns, std::move(serialized_columns));
746 }
747
748 /// Directly log a columns of data to Rerun.
749 ///
750 /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data
751 /// in a columnar form. Each `TimeColumn` and `ComponentColumn` represents a column of data that will be sent to Rerun.
752 /// The lengths of all of these columns must match, and all
753 /// data that shares the same index across the different columns will act as a single logical row,
754 /// equivalent to a single call to `RecordingStream::log`.
755 ///
756 /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs.
757 /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns.
758 ///
759 /// Any failures that may occur during serialization are handled with `Error::handle`.
760 ///
761 /// \param entity_path Path to the entity in the space hierarchy.
762 /// \param time_columns The time columns to send.
763 /// \param component_columns The columns of components to send.
764 /// \see `try_send_columns`
766 std::string_view entity_path, Collection<TimeColumn> time_columns,
767 Collection<ComponentColumn> component_columns
768 ) const {
769 try_send_columns(entity_path, time_columns, component_columns).handle();
770 }
771
772 /// Directly log a columns of data to Rerun.
773 ///
774 /// Unlike the regular `log` API, which is row-oriented, this API lets you submit the data
775 /// in a columnar form. Each `TimeColumn` and `ComponentColumn` represents a column of data that will be sent to Rerun.
776 /// The lengths of all of these columns must match, and all
777 /// data that shares the same index across the different columns will act as a single logical row,
778 /// equivalent to a single call to `RecordingStream::log`.
779 ///
780 /// Note that this API ignores any stateful time set on the log stream via the `RecordingStream::set_time_*` APIs.
781 /// Furthermore, this will _not_ inject the default timelines `log_tick` and `log_time` timeline columns.
782 ///
783 /// \param entity_path Path to the entity in the space hierarchy.
784 /// \param time_columns The time columns to send.
785 /// \param component_columns The columns of components to send.
786 /// \see `send_columns`
788 std::string_view entity_path, Collection<TimeColumn> time_columns,
789 Collection<ComponentColumn> component_columns
790 ) const;
791
792 /// @}
793
794 private:
795 RecordingStream(uint32_t id, StoreKind store_kind);
796
797 uint32_t _id;
798 StoreKind _store_kind;
799 bool _enabled;
800 };
801} // 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:95
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:131
static Error ok()
Creates a new error set to ok.
Definition error.hpp:116
A RecordingStream handles everything related to logging data into Rerun.
Definition recording_stream.hpp:60
Error spawn(const SpawnOptions &options={}, float flush_timeout_sec=2.0) const
Spawns a new Rerun Viewer process from an executable available in PATH, then connects to it over TCP.
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 DataLoaders available.
Definition recording_stream.hpp:586
bool is_enabled() const
Returns whether the recording stream is enabled.
Definition recording_stream.hpp:99
Error try_log_static(std::string_view entity_path, const Ts &... archetypes_or_collections) const
Logs one or more archetype and/or component batches as static data, returning an error.
Definition recording_stream.hpp:433
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:765
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 DataLoaders available.
Error save(std::string_view path) const
Stream all log-data to a given .rrd file.
void log_with_static(std::string_view entity_path, bool static_, const Ts &... archetypes_or_collections) const
Logs one or more archetype and/or component batches optionally static, returning an error.
Definition recording_stream.hpp:464
StoreKind kind() const
Returns the store kind as passed during construction.
Definition recording_stream.hpp:91
void log(std::string_view entity_path, const Ts &... archetypes_or_collections) const
Logs one or more archetype and/or component batches.
Definition recording_stream.hpp:360
Error try_send_columns(std::string_view entity_path, Collection< TimeColumn > time_columns, Collection< Ts >... component_columns) const
Directly log a columns of data to Rerun.
Definition recording_stream.hpp:718
Error spawn(const SpawnOptions &options={}, std::chrono::duration< TRep, TPeriod > flush_timeout=std::chrono::seconds(2)) const
Definition recording_stream.hpp:182
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 DataLoaders available.
Definition recording_stream.hpp:636
Error try_log(std::string_view entity_path, const Ts &... archetypes_or_collections) const
Logs one or more archetype and/or component batches.
Definition recording_stream.hpp:407
void flush_blocking() const
Initiates a flush the batching pipeline and waits for it to propagate.
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.
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:260
void log_static(std::string_view entity_path, const Ts &... archetypes_or_collections) const
Logs one or more archetype and/or component batches as static data.
Definition recording_stream.hpp:388
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 set_thread_local() const
Replaces the currently active recording for this stream's store kind in the thread-local scope with t...
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.
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:246
Error connect_tcp(std::string_view tcp_addr="127.0.0.1:9876", float flush_timeout_sec=2.0) const
Connect to a remote Rerun Viewer on the given ip:port.
void send_columns(std::string_view entity_path, Collection< TimeColumn > time_columns, Collection< Ts >... component_columns) const
Directly log a columns of data to Rerun.
Definition recording_stream.hpp:694
void set_time_seconds(std::string_view timeline_name, double seconds) const
Set the current time of the recording, for the current calling thread.
Error try_log_with_static(std::string_view entity_path, bool static_, const Ts &... archetypes_or_collections) const
Logs one or more archetype and/or component batches optionally static, returning an error.
Definition recording_stream.hpp:494
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 DataLoaders available.
void set_global() const
Replaces the currently active recording for this stream's store kind in the global scope with this on...
Error connect(std::string_view tcp_addr="127.0.0.1:9876", float flush_timeout_sec=2.0) const
Connect to a remote Rerun Viewer on the given ip:port.
void set_time_sequence(std::string_view timeline_name, int64_t sequence_nr) const
Set the current time of the recording, for the current calling thread.
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:22
Arrow-encoded data of a single batch components for a single entity.
Definition component_batch.hpp:22
static Result< ComponentColumn > from_loggable(const Collection< T > &components)
Creates a new component column from a collection of component instances where each run has a length o...
Definition component_column.hpp:60
Options to control the behavior of spawn.
Definition spawn_options.hpp:17