Skip to content

Tauri Plugin

Add the plugin crate to your Tauri app:

[dependencies]
tauri-plugin-auditaur = "0.1.3"
tracing = "0.1"
tracing-subscriber = "0.3"

Register the plugin and, if you want backend tracing, install the tracing layer before starting Tauri:

use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
fn main() {
tracing_subscriber::registry()
.with(tauri_plugin_auditaur::tracing_layer())
.init();
tauri::Builder::default()
.plugin(
tauri_plugin_auditaur::Builder::new()
.service_name("my-tauri-app")
.session_name("dev")
.redact_defaults(true)
.max_session_bytes(256 * 1024 * 1024)
.build(),
)
.run(tauri::generate_context!())
.expect("failed to run app");
}

The plugin creates the SQLite session database, writes a discovery file, receives frontend telemetry batches through export_otel_batch, applies recursive redaction, records Rust tracing events/spans, stores the optional session name, and applies best-effort retention after frontend batches.

To continue frontend invoke() traces into backend command spans, use auditaur_command on app-owned Tauri commands:

#[tauri_plugin_auditaur::auditaur_command]
fn load_user(id: String) -> Result<String, String> {
tracing::info!(user.id = %id, "loading user");
Ok(id)
}

The frontend wrapper sends W3C traceparent in Tauri invoke request headers and also sends the older reserved auditaurTraceContext argument for compatibility. auditaur_command wraps #[tauri::command], injects both IPC carriers, prefers the request header, falls back to the reserved argument, and adds the tracing::instrument fields needed for Auditaur’s tracing layer, so the backend command span is parented to the frontend invoke span without command-name or timestamp heuristics. Existing tracing options can be passed through, for example #[tauri_plugin_auditaur::auditaur_command(err)] or #[tauri_plugin_auditaur::auditaur_command(skip(app))].

If you need to keep an explicit #[tauri::command], use the lower-level compatibility helper:

use tauri_plugin_auditaur::IpcTraceContext;
#[tauri::command]
#[tauri_plugin_auditaur::instrument_ipc(err)]
fn load_user_legacy(
id: String,
auditaur_trace_context: Option<IpcTraceContext>,
) -> Result<String, String> {
tracing::info!(user.id = %id, "loading user");
Ok(id)
}

An expected healthy invoke trace has:

RowExpected shape
Frontend spanname = "tauri.invoke load_user", kind = "client", and a generated trace_id / span_id.
IPC rowcommand = "load_user" with the same trace_id and span_id as the frontend span.
Backend spanSame trace_id, parent_span_id equal to the frontend invoke span id, and a traceparent attribute.

If auditaur explain --trace <id> --json sees a frontend invoke span without a backend child span, it reports a missing backend trace continuation finding and suggests adding auditaur_command or instrument_ipc.

App integration tests can assert the same shape after exercising a command:

tauri_plugin_auditaur::test_helpers::assert_trace_stitched(
"path/to/telemetry.sqlite",
"load_user",
);

Add auditaur:default to the app capability so the frontend package can call the plugin command:

{
"permissions": ["core:default", "auditaur:default"]
}

The collector is development-first. Release builds are blocked unless allow_release_builds(true) is explicitly set after reviewing what the app emits and how diagnostics will be handled.