Logging
When to Use
Use this skill when the user wants to capture, route, filter, or silence ovstage's
log output: install a log callback, set a severity threshold, filter by channel, or
flush pending messages before a checkpoint. For operation/return-code error handling
(not logging), use the error-handling skill instead.
Inputs
Resolve inputs in this order: existing repository files and referenced snippets, explicit user request, then broader agent context.
- The desired default severity threshold (
LogSeverity / ovstage_log_severity_t).
- Any per-channel overrides (a comma-separated
<channel>=<level> filter).
- Target API surface: C, Python, or both.
- Whether the caller needs a barrier (
flush_log) before reading captured output.
- The shipped headers (
ovstage.h, ovstage_types.h) and the referenced test snippet
are the authoritative contract.
Prerequisites
- Use an ovstage checkout that contains the
include/ headers and the referenced snippet.
- Read the relevant
> **Source:** snippet before writing or explaining API usage.
- Hold a live instance/
Stage when installing a callback — the callback is
process-global but the runtime must be bootstrapped first.
- Do not emit ovstage/USD log messages from inside the callback (it re-enters the
dispatcher and can feed back indefinitely).
Instructions
- Install the callback: C
ovstage_set_log_callback(severity, channel_filter, cb, user_data);
Python set_log_callback(cb, severity=, channel_filter=). The callback receives
(severity, timestamp, message). In C, message is valid only during the call, so copy it
to keep it; the Python binding hands the callback an owned str, so there is no such hazard.
- Choose the default
severity threshold for channels not named in channel_filter
(NONE disables all unmatched channels); add <channel>=<level> overrides as needed.
- Do the log-producing work.
- Call
flush_log(timeout) to force pending (asynchronously-dispatched) messages through
before reading your captured output.
- Clear delivery by installing a NULL/
None callback (which also flushes and tears down
the dispatcher thread).
Output Format
- For explanations, cite the API names, the source snippet, the severity/threshold and
channel-filter semantics, and the async-delivery +
flush_log caveat.
- For code changes, summarize the files touched, snippets affected, and validation run.
Scripts
This skill has no scripts.
Limitations
- The referenced snippet is the source of truth; this skill composes it and describes the
surrounding logging API rather than introducing new code.
- Process-global, single callback.
set_log_callback replaces any prior callback for
the whole process; it is not per-instance.
- Asynchronous delivery. Messages are dispatched on a dedicated thread, so they may
arrive after the call that produced them — use
flush_log as a barrier before asserting
on or reading captured output.
- Callback must not log. Emitting ovstage/USD messages from the callback re-enters the
dispatcher; a Python callback that raises has its traceback printed and is then suppressed.
- Not an error channel. Logging is diagnostic output; operation success/failure is
reported via return codes /
OvstageError (see error-handling).
- Silent by default (standalone). With no callback installed, the standalone runtime
prints nothing to the console — there is no default stderr/stdout sink to silence, and
the callback is the only way to observe diagnostics. Inside a host application that
configures its own logging, the host's console configuration governs.
- ⚠️ Draft — API in flux. Treat exact symbols/ordering as provisional against the headers.
Overview
ovstage_set_log_callback routes ovstage's log messages — and messages from its USD
support layer — to one process-global callback. severity is the default threshold
for channels not matched by a rule in channel_filter (messages below it are dropped);
channel_filter is an optional comma-separated <channel>=<level> list (e.g.
"omni.ovstage=verbose"), NULL applying severity uniformly. Delivery is
asynchronous on a dispatcher thread; ovstage_flush_log(timeout) blocks until messages
emitted before the call have drained.
When ovstage runs standalone (the shipped package used directly), no callback means
no output: the console (stdout/stderr) stays silent at every severity — a final
sanitized message on a fatal process abort is the only exception — and diagnostics
exist only for callback subscribers. When ovstage is embedded in a host application
that configures its own logging, console behavior follows the host's configuration.
Operation failures do not depend on logging — they surface through return codes and
the error string accessors (see error-handling). USD-support-layer statuses arrive
at INFO (warnings and USD coding errors at WARNING, other errors at ERROR), so
a callback whose threshold is the default WARNING will not see statuses; lower the
threshold (or add a channel rule such as omni.ovstage.usd=info) to observe
asset-resolution traffic.
Severities (ovstage_log_severity_t / LogSeverity): VERBOSE (-2), INFO (-1),
WARNING (0), ERROR (1), NONE (3, a threshold sentinel that disables all logging and
is never delivered).
C
Install a callback, prove a bogus channel-prefix filter with a NONE default threshold
suppresses everything, flush, and clear:
Source: tests/c/test_logging.cpp snippet log-callback-filter-c
Python
The Python binding takes the callback first, then severity / channel_filter; a None
callback clears delivery:
Source: tests/python/test_logging.py snippet log-callback-filter
Key Types / Functions
| Purpose |
C |
Python |
| Install / clear callback |
ovstage_set_log_callback(severity, channel_filter, cb, user_data) |
set_log_callback(cb, severity=, channel_filter=) (None clears) |
| Flush pending messages |
ovstage_flush_log(timeout) |
flush_log(timeout=) |
| Severity levels |
ovstage_log_severity_t (OVSTAGE_LOG_*) |
LogSeverity |
| Callback signature |
void(ovstage_log_severity_t, double, ovx_string_t, void*) |
f(severity, timestamp, message) |
Troubleshooting
- No messages delivered — the default
severity is too high (or NONE), or a channel
filter excludes the channels you expected; lower the threshold / adjust the filter. Also
confirm you called flush_log before checking (delivery is asynchronous).
set_log_callback fails (OP_FAILED) — the runtime is not bootstrapped; create a
Stage / instance first.
- Filter rejected (
INVALID_ARGUMENT) — the channel_filter string failed to parse;
use the <channel>=<level> form with levels verbose|debug|info|warn|warning|error|fatal|none.
flush_log hangs — a callback that blocks stalls the dispatcher; pass a finite
timeout, and never block (or log) inside the callback.
- Message text garbage after the call (C only) — the C
message is valid only during the
callback; copy it if it must outlive the call. The Python binding gives you an owned str.
References
- Use the
> **Source:** directives in this skill to locate tested snippets before reusing API patterns.
error-handling — operation return codes and per-op errors (the non-logging failure surface).
loading-usd — population is a convenient source of runtime log traffic to capture.
- The shipped
include/ovstage/ovstage.h / ovstage_types.h headers are the authoritative contract.
1---2name: logging3description: Route ovstage's diagnostic log messages (and messages from its USD support layer) to a process-global callback with a severity threshold and a RUST_LOG-style per-channel filter, and force delivery with flush_log. Use when the user asks about ovstage logging, a log callback, log severity or verbosity, channel filtering, or capturing/silencing ovstage/USD runtime log output. This is distinct from error handling (return codes) — see the error-handling skill for that.4license: LicenseRef-NvidiaProprietary5---67# Logging89## When to Use1011Use this skill when the user wants to **capture, route, filter, or silence** ovstage's12log output: install a log callback, set a severity threshold, filter by channel, or13flush pending messages before a checkpoint. For operation/return-code error handling14(not logging), use the `error-handling` skill instead.1516## Inputs1718Resolve inputs in this order: existing repository files and referenced snippets, explicit user request, then broader agent context.1920- The desired default severity threshold (`LogSeverity` / `ovstage_log_severity_t`).21- Any per-channel overrides (a comma-separated `<channel>=<level>` filter).22- Target API surface: C, Python, or both.23- Whether the caller needs a barrier (`flush_log`) before reading captured output.24- The shipped headers (`ovstage.h`, `ovstage_types.h`) and the referenced test snippet25 are the authoritative contract.2627## Prerequisites2829- Use an ovstage checkout that contains the `include/` headers and the referenced snippet.30- Read the relevant `> **Source:**` snippet before writing or explaining API usage.31- Hold a **live instance/`Stage`** when installing a callback — the callback is32 process-global but the runtime must be bootstrapped first.33- Do **not** emit ovstage/USD log messages from inside the callback (it re-enters the34 dispatcher and can feed back indefinitely).3536## Instructions37381. Install the callback: C `ovstage_set_log_callback(severity, channel_filter, cb, user_data)`;39 Python `set_log_callback(cb, severity=, channel_filter=)`. The callback receives40 `(severity, timestamp, message)`. In C, `message` is valid only during the call, so copy it41 to keep it; the Python binding hands the callback an owned `str`, so there is no such hazard.422. Choose the default `severity` threshold for channels not named in `channel_filter`43 (`NONE` disables all unmatched channels); add `<channel>=<level>` overrides as needed.443. Do the log-producing work.454. Call `flush_log(timeout)` to force pending (asynchronously-dispatched) messages through46 before reading your captured output.475. Clear delivery by installing a NULL/`None` callback (which also flushes and tears down48 the dispatcher thread).4950## Output Format5152- For explanations, cite the API names, the source snippet, the severity/threshold and53 channel-filter semantics, and the async-delivery + `flush_log` caveat.54- For code changes, summarize the files touched, snippets affected, and validation run.5556## Scripts5758This skill has no scripts.5960## Limitations6162- The referenced snippet is the source of truth; this skill composes it and describes the63 surrounding logging API rather than introducing new code.64- **Process-global, single callback.** `set_log_callback` replaces any prior callback for65 the whole process; it is not per-instance.66- **Asynchronous delivery.** Messages are dispatched on a dedicated thread, so they may67 arrive after the call that produced them — use `flush_log` as a barrier before asserting68 on or reading captured output.69- **Callback must not log.** Emitting ovstage/USD messages from the callback re-enters the70 dispatcher; a Python callback that raises has its traceback printed and is then suppressed.71- **Not an error channel.** Logging is diagnostic output; operation success/failure is72 reported via return codes / `OvstageError` (see `error-handling`).73- **Silent by default (standalone).** With no callback installed, the standalone runtime74 prints nothing to the console — there is no default stderr/stdout sink to silence, and75 the callback is the only way to observe diagnostics. Inside a host application that76 configures its own logging, the host's console configuration governs.77- **⚠️ Draft — API in flux.** Treat exact symbols/ordering as provisional against the headers.7879## Overview8081`ovstage_set_log_callback` routes ovstage's log messages — and messages from its USD82support layer — to one process-global callback. `severity` is the default threshold83for channels not matched by a rule in `channel_filter` (messages below it are dropped);84`channel_filter` is an optional comma-separated `<channel>=<level>` list (e.g.85`"omni.ovstage=verbose"`), `NULL` applying `severity` uniformly. Delivery is86asynchronous on a dispatcher thread; `ovstage_flush_log(timeout)` blocks until messages87emitted before the call have drained.8889When ovstage runs standalone (the shipped package used directly), no callback means90no output: the console (stdout/stderr) stays silent at every severity — a final91sanitized message on a fatal process abort is the only exception — and diagnostics92exist only for callback subscribers. When ovstage is embedded in a host application93that configures its own logging, console behavior follows the host's configuration.94Operation failures do not depend on logging — they surface through return codes and95the error string accessors (see `error-handling`). USD-support-layer statuses arrive96at `INFO` (warnings and USD coding errors at `WARNING`, other errors at `ERROR`), so97a callback whose threshold is the default `WARNING` will not see statuses; lower the98threshold (or add a channel rule such as `omni.ovstage.usd=info`) to observe99asset-resolution traffic.100101Severities (`ovstage_log_severity_t` / `LogSeverity`): `VERBOSE` (-2), `INFO` (-1),102`WARNING` (0), `ERROR` (1), `NONE` (3, a threshold sentinel that disables all logging and103is never delivered).104105## C106107Install a callback, prove a bogus channel-prefix filter with a `NONE` default threshold108suppresses everything, flush, and clear:109110> **Source:** `tests/c/test_logging.cpp` snippet `log-callback-filter-c`111112## Python113114The Python binding takes the callback first, then `severity` / `channel_filter`; a `None`115callback clears delivery:116117> **Source:** `tests/python/test_logging.py` snippet `log-callback-filter`118119## Key Types / Functions120121| Purpose | C | Python |122|---------|---|--------|123| Install / clear callback | `ovstage_set_log_callback(severity, channel_filter, cb, user_data)` | `set_log_callback(cb, severity=, channel_filter=)` (`None` clears) |124| Flush pending messages | `ovstage_flush_log(timeout)` | `flush_log(timeout=)` |125| Severity levels | `ovstage_log_severity_t` (`OVSTAGE_LOG_*`) | `LogSeverity` |126| Callback signature | `void(ovstage_log_severity_t, double, ovx_string_t, void*)` | `f(severity, timestamp, message)` |127128## Troubleshooting129130- **No messages delivered** — the default `severity` is too high (or `NONE`), or a channel131 filter excludes the channels you expected; lower the threshold / adjust the filter. Also132 confirm you called `flush_log` before checking (delivery is asynchronous).133- **`set_log_callback` fails (`OP_FAILED`)** — the runtime is not bootstrapped; create a134 `Stage` / instance first.135- **Filter rejected (`INVALID_ARGUMENT`)** — the `channel_filter` string failed to parse;136 use the `<channel>=<level>` form with levels verbose|debug|info|warn|warning|error|fatal|none.137- **`flush_log` hangs** — a callback that blocks stalls the dispatcher; pass a finite138 timeout, and never block (or log) inside the callback.139- **Message text garbage after the call (C only)** — the C `message` is valid only during the140 callback; copy it if it must outlive the call. The Python binding gives you an owned `str`.141142## References143144- Use the `> **Source:**` directives in this skill to locate tested snippets before reusing API patterns.145- `error-handling` — operation return codes and per-op errors (the non-logging failure surface).146- `loading-usd` — population is a convenient source of runtime log traffic to capture.147- The shipped `include/ovstage/ovstage.h` / `ovstage_types.h` headers are the authoritative contract.