initLog static method

void initLog(
  1. String fallback
)

Initializes the zenoh logger from the RUST_LOG environment variable, falling back to fallback if RUST_LOG is not set.

Must be called before Session.open for logging to take effect. This is a one-time initialization -- subsequent calls are ignored by the underlying runtime.

And it forecloses initLogWithSink for the life of the process. Canon's logging slot is process-global and first-wins; calling this claims it permanently, so a host that wants records delivered into its own application must install the sink first. The foreclosure surfaces as a StateError at the sink install, not here — this call stays silent, because a caller who asked for the env logger got the env logger and there is nothing to report.

Calling it a second time is likewise silent and idempotent, unchanged. ⭐ The asymmetry is deliberate and structural: a throw belongs where a returned value would otherwise be false. initLogWithSink hands back a Stream, and a stream that can never emit is a lie handed back as a live channel; this returns void, and void cannot be false. What a late call to this loses is a filter level, not a channel.

⚠️ The guard sees only inits made through this binding. Canon returns void from its own init and reports nothing, so there is no way to observe an init made by other code in the same process — another binding, or a Rust crate linked into the same image. This is a guard against an ordering mistake in your program, not a view of canon's state.

What the log channel carries, measured

This is the route to canon's own explanation of a failure, and the measurement that made it the recommended one is worth carrying with its condition, because the condition is what a reader needs:

  • initLog('error') prints the precise cause of a Session.open failure with zero leakage of the config that produced it. That is true, and it is why open-failure diagnosis is routed here rather than onto the exception message.
  • ⚠️ It is a property of the failure class, not of the channel. Config-rejection records echo the offending value verbatim — with the surrounding source line and a caret under the offending token — on both build variants. On the default stable build, where the exception channel carries no upstream detail at all, this is the only channel that leaks.

No severity ceiling removes it, because the records are emitted at error. The control is a host-side filter on the delivered records, which is what initLogWithSink exists to make possible; this call sends them to stdout, where the host has no control at all.

Filter syntax follows the Rust env_logger format:

  • "error" -- errors only (recommended for production)
  • "warn" -- warnings and errors
  • "info" -- informational messages
  • "debug" -- debug-level detail
  • "trace" -- maximum verbosity

See: https://docs.rs/env_logger/latest/env_logger/

Implementation

static void initLog(String fallback) {
  final cStr = fallback.toNativeUtf8();
  try {
    bindings.zd_init_log(cStr.cast<Char>());
  } finally {
    calloc.free(cStr);
  }
}