Skip to content

Other classes and functions

rerun

class RecordingStream

A RecordingStream is used to send data to Rerun.

You can instantiate a RecordingStream by calling either rerun.init (to create a global recording) or rerun.new_recording (for more advanced use cases).

Multithreading

A RecordingStream can safely be copied and sent to other threads. You can also set a recording as the global active one for all threads (rerun.set_global_data_recording) or just for the current thread (rerun.set_thread_local_data_recording).

Similarly, the with keyword can be used to temporarily set the active recording for the current thread, e.g.:

with rec:
    rr.log(...)
WARNING: if using a RecordingStream as a context manager, yielding from a generator function while holding the context open will leak the context and likely cause your program to send data to the wrong stream. See: https://github.com/rerun-io/rerun/issues/6238. You can work around this by using the rerun.recording_stream_generator_ctx decorator.

See also: rerun.get_data_recording, rerun.get_global_data_recording, rerun.get_thread_local_data_recording.

Available methods

Every function in the Rerun SDK that takes an optional RecordingStream as a parameter can also be called as a method on RecordingStream itself.

This includes, but isn't limited to:

For an exhaustive list, see help(rerun.RecordingStream).

Micro-batching

Micro-batching using both space and time triggers (whichever comes first) is done automatically in a dedicated background thread.

You can configure the frequency of the batches using the following environment variables:

  • RERUN_FLUSH_TICK_SECS: Flush frequency in seconds (default: 0.05 (50ms)).
  • RERUN_FLUSH_NUM_BYTES: Flush threshold in bytes (default: 1048576 (1MiB)).
  • RERUN_FLUSH_NUM_ROWS: Flush threshold in number of rows (default: 18446744073709551615 (u64::MAX)).

class LoggingHandler

Bases: Handler

Provides a logging handler that forwards all events to the Rerun SDK.

Read more about logging handlers.

def __init__(path_prefix=None)

Initializes the logging handler with an optional path prefix.

PARAMETER DESCRIPTION
path_prefix

A common prefix for all logged entity paths. Defaults to no prefix.

TYPE: str | None DEFAULT: None

def emit(record)

Emits a record to the Rerun SDK.

class MemoryRecording

A recording that stores data in memory.

def drain_as_bytes()

Drains the MemoryRecording and returns the data as bytes.

This will flush the current sink before returning.

def num_msgs()

The number of pending messages in the MemoryRecording.

Note: counting the messages will flush the batcher in order to get a deterministic count.

def get_data_recording(recording=None)

Returns the most appropriate recording to log data to, in the current context, if any.

  • If recording is specified, returns that one;
  • Otherwise, falls back to the currently active thread-local recording, if there is one;
  • Otherwise, falls back to the currently active global recording, if there is one;
  • Otherwise, returns None.
PARAMETER DESCRIPTION
recording

Specifies the rerun.RecordingStream to use. If left unspecified, defaults to the current active data recording, if there is one. See also: rerun.init, rerun.set_global_data_recording.

TYPE: RecordingStream | None DEFAULT: None

RETURNS DESCRIPTION
Optional[RecordingStream]

The most appropriate recording to log data to, in the current context, if any.

def get_global_data_recording()

Returns the currently active global recording, if any.

RETURNS DESCRIPTION
Optional[RecordingStream]

The currently active global recording, if any.

def get_recording_id(recording=None)

Get the recording ID that this recording is logging to, as a UUIDv4, if any.

The default recording_id is based on multiprocessing.current_process().authkey which means that all processes spawned with multiprocessing will have the same default recording_id.

If you are not using multiprocessing and still want several different Python processes to log to the same Rerun instance (and be part of the same recording), you will need to manually assign them all the same recording_id. Any random UUIDv4 will work, or copy the recording id for the parent process.

PARAMETER DESCRIPTION
recording

Specifies the rerun.RecordingStream to use. If left unspecified, defaults to the current active data recording, if there is one. See also: rerun.init, rerun.set_global_data_recording.

TYPE: RecordingStream | None DEFAULT: None

RETURNS DESCRIPTION
str

The recording ID that this recording is logging to.

def get_thread_local_data_recording()

Returns the currently active thread-local recording, if any.

RETURNS DESCRIPTION
Optional[RecordingStream]

The currently active thread-local recording, if any.

def is_enabled(recording=None)

Is this Rerun recording enabled.

If false, all calls to the recording are ignored.

The default can be set in rerun.init, but is otherwise True.

This can be controlled with the environment variable RERUN (e.g. RERUN=on or RERUN=off).

def new_recording(application_id, *, recording_id=None, make_default=False, make_thread_default=False, spawn=False, default_enabled=True)

Creates a new recording with a user-chosen application id (name) that can be used to log data.

If you only need a single global recording, rerun.init might be simpler.

Note that unless setting spawn=True new recording streams always begin connected to a buffered sink. To send the data to a viewer or file you will likely want to call rerun.connect or rerun.save explicitly.

Warning

If you don't specify a recording_id, it will default to a random value that is generated once at the start of the process. That value will be kept around for the whole lifetime of the process, and even inherited by all its subprocesses, if any.

This makes it trivial to log data to the same recording in a multiprocess setup, but it also means that the following code will not create two distinct recordings:

rr.init("my_app")
rr.init("my_app")

To create distinct recordings from the same process, specify distinct recording IDs:

from uuid import uuid4
rec = rr.new_recording(application_id="test", recording_id=uuid4())
rec = rr.new_recording(application_id="test", recording_id=uuid4())

PARAMETER DESCRIPTION
application_id

Your Rerun recordings will be categorized by this application id, so try to pick a unique one for each application that uses the Rerun SDK.

For example, if you have one application doing object detection and another doing camera calibration, you could have rerun.init("object_detector") and rerun.init("calibrator").

TYPE: str

recording_id

Set the recording ID that this process is logging to, as a UUIDv4.

The default recording_id is based on multiprocessing.current_process().authkey which means that all processes spawned with multiprocessing will have the same default recording_id.

If you are not using multiprocessing and still want several different Python processes to log to the same Rerun instance (and be part of the same recording), you will need to manually assign them all the same recording_id. Any random UUIDv4 will work, or copy the recording id for the parent process.

TYPE: Optional[str] DEFAULT: None

make_default

If true (not the default), the newly initialized recording will replace the current active one (if any) in the global scope.

TYPE: bool DEFAULT: False

make_thread_default

If true (not the default), the newly initialized recording will replace the current active one (if any) in the thread-local scope.

TYPE: bool DEFAULT: False

spawn

Spawn a Rerun Viewer and stream logging data to it. Short for calling spawn separately. If you don't call this, log events will be buffered indefinitely until you call either connect, show, or save

TYPE: bool DEFAULT: False

default_enabled

Should Rerun logging be on by default? Can be overridden with the RERUN env-var, e.g. RERUN=on or RERUN=off.

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
RecordingStream

A handle to the rerun.RecordingStream. Use it to log data to Rerun.

Examples:

Using a recording stream object directly.

from uuid import uuid4
stream = rr.new_recording("my_app", recording_id=uuid4())
stream.connect()
stream.log("hello", rr.TextLog("Hello world"))

Setting up a new global recording explicitly.

from uuid import uuid4
rr.new_recording("my_app", make_default=True, recording_id=uuid4())
rr.connect()
rr.log("hello", rr.TextLog("Hello world"))

def set_global_data_recording(recording)

Replaces the currently active global recording with the specified one.

PARAMETER DESCRIPTION
recording

The newly active global recording.

TYPE: RecordingStream

def set_thread_local_data_recording(recording)

Replaces the currently active thread-local recording with the specified one.

PARAMETER DESCRIPTION
recording

The newly active thread-local recording.

TYPE: RecordingStream | None

def start_web_viewer_server(port=0)

Start an HTTP server that hosts the rerun web viewer.

This only provides the web-server that makes the viewer available and does not otherwise provide a rerun websocket server or facilitate any routing of data.

This is generally only necessary for application such as running a jupyter notebook in a context where app.rerun.io is unavailable, or does not have the matching resources for your build (such as when running from source.)

PARAMETER DESCRIPTION
port

Port to serve assets on. Defaults to 0 (random port).

TYPE: int DEFAULT: 0

def escape_entity_path_part(part)

Escape an individual part of an entity path.

For instance, escape_entity_path_path("my image!") will return "my\ image\!".

See https://www.rerun.io/docs/concepts/entity-path for more on entity paths.

PARAMETER DESCRIPTION
part

An unescaped string

TYPE: str

RETURNS DESCRIPTION
str

The escaped entity path.

TYPE: str

def new_entity_path(entity_path)

Construct an entity path, defined by a list of (unescaped) parts.

If any part if not a string, it will be converted to a string using str().

For instance, new_entity_path(["world", 42, "my image!"]) will return "world/42/my\ image\!".

See https://www.rerun.io/docs/concepts/entity-path for more on entity paths.

PARAMETER DESCRIPTION
entity_path

A list of strings to escape and join with slash.

TYPE: list[Any]

RETURNS DESCRIPTION
str

The escaped entity path.

TYPE: str

def thread_local_stream(application_id)

Create a thread-local recording stream and use it when executing the decorated function.

This can be helpful for decorating a function that represents a job or a task that you want to to produce its own isolated recording.

Example

@rr.thread_local_stream("rerun_example_job")
def job(name: str) -> None:
    rr.save(f"job_{name}.rrd")
    for i in range(5):
        time.sleep(0.2)
        rr.log("hello", rr.TextLog(f"Hello {i) from Job {name}"))

threading.Thread(target=job, args=("A",)).start()
threading.Thread(target=job, args=("B",)).start()
This will produce 2 separate rrd files, each only containing the logs from the respective threads.

PARAMETER DESCRIPTION
application_id

The application ID that this recording is associated with.

TYPE: str

def recording_stream_generator_ctx(func)

Decorator to manage recording stream context for generator functions.

This is only necessary if you need to implement a generator which yields while holding an open recording stream context which it created. This decorator will ensure that the recording stream context is suspended and then properly resumed upon re-entering the generator.

See: https://github.com/rerun-io/rerun/issues/6238 for context on why this is necessary.

There are plenty of things that can go wrong when mixing context managers with generators, so don't use this decorator unless you're sure you need it.

If you can plumb through RecordingStream objects and use those directly instead of relying on the context manager, that will always be more robust.

Example
@rr.recording_stream.recording_stream_generator_ctx
def my_generator(name: str) -> Iterator[None]:
    with rr.new_recording(name):
        rr.save(f"{name}.rrd")
        for i in range(10):
            rr.log("stream", rr.TextLog(f"{name} {i}"))
            yield i

for i in my_generator("foo"):
    pass