Logging

Buttplug exposes a few methods to receive log messages from the internal Rust library. These messages relay the internal state of the system, and can be handy for debugging purposes.

Message Exposure

What log messages you'll get depend on the type of system you're building. If you are using an embedded connector (i.e. server and client in the same process), you'll get both client and server information. If you're using a remote connector (i.e. your application uses the client, and the server is in another process/on another machine), you'll only receive log messages for the client. This preserves privacy for users who may not want to reveal information about their local setup to a untrusted client (For more information, see the Privacy Models section of the this guide).

This model may may things challenging to debug, which is why we recommend doing initial development in an embedded context if possible, the moving to remote once core development is set.

Accessing Logs

Logs are generated in Rust using the tracing crate (opens new window). This functionality is exposed to Rust via normal tracing subsystems (for instance, output to stdout via tracing_subscriber::fmt), or via various language specifics for FFIs (C# and JS have the ability to emit log messages as events).

Temporary FFI Logging Limitations

At the time of this writing, logging capabilties in FFI instances are somewhat limited. Logging must be started manually, can only be set to one level for a session (i.e. if logging is started a "Debug or higher" levels, it will stay there for the remainder of the process), and only comes as string. As library development progresses, this system will be tuned to allow finer grained access to control and log information.

Available log levels are as follows:

  • Error
    • Something went wrong and you should probably pay attention.
  • Warn
    • Something bad possibly happened, but may not warrant full attention.
  • Info
    • Something possibly useful to the user happened
  • Debug
    • Something insignificant but possibly useful to development happened
  • Trace
    • A butterfly flapped its wings. Trace is EXTREMELY spammy.

Example Code

  • Rust
  • C#
  • Javascript

Handling and/or outputting log messages in Rust is left up to the user, via normal methods of output for the tracing crate. (opens new window) To output messages to stdout (i.e. the console) we recommend using the tracing_subscriber (opens new window) create with its fmt instance, like so:

use buttplug::{
  client::ButtplugClient,
  server::ButtplugServerOptions,
};
use tracing_subscriber;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
  // Run this to turn on the environment logger. Running this more than once will panic.
  tracing_subscriber::fmt::init();

  // Now when you connect here, if you've set the RUST_LOG environment variable
  // (set it to "Info" or "Debug"), you should see messages about connection
  // setup.
  let client = ButtplugClient::new("Example Client");
  client.connect_in_process(&ButtplugServerOptions::default()).await?;

  Ok(())
}

tracing_subscriber::fmt uses environment variables to set log level filters. The filters are strings set to the levels mentioned in the previous section.

To set up log output using tracing_subscriber on a shell, you can use

RUST_LOG="debug" ./[your_program_here]

To set this up in Powershell on windows, you can use

$env:RUST_LOG="debug"

Running the example above, you should see something like this (may not be exact. For instance, most people probably won't be writing sex toy software documentation on Christmas.):

Dec 25 20:49:11.826  INFO buttplug::server::comm_managers::btleplug: Setting bluetooth device event handler.
Dec 25 20:49:11.826  INFO InProcessClientConnectorEventSenderLoop: buttplug::connector::in_process_connector: Starting In Process Client Connector Event Sender Loop
Dec 25 20:49:11.839  INFO buttplug::server::comm_managers::serialport::serialport_comm_manager: Serial port created!
Dec 25 20:49:11.840  INFO buttplug::server::comm_managers::lovense_dongle::lovense_hid_dongle_comm_manager: Lovense dongle HID Manager created!
Dec 25 20:49:11.841  INFO buttplug::server::comm_managers::lovense_dongle::lovense_serial_dongle_comm_manager: Lovense dongle serial port created!
Dec 25 20:49:11.841  INFO Lovense HID Dongle State Machine: buttplug::server::comm_managers::lovense_dongle::lovense_dongle_state_machine: Running wait for dongle step
Dec 25 20:49:11.842  INFO Lovense Dongle State Machine: buttplug::server::comm_managers::lovense_dongle::lovense_dongle_state_machine: Running wait for dongle step
Dec 25 20:49:11.842  INFO Client: buttplug::client: Connecting to server.
Dec 25 20:49:11.845  INFO Client: buttplug::client: Connection to server succeeded.
Dec 25 20:49:11.846  INFO buttplug::server::comm_managers::lovense_dongle::lovense_serial_dongle_comm_manager: Got 0 serial ports back
Dec 25 20:49:11.847  INFO Client: buttplug::client: Running handshake with server.
Dec 25 20:49:11.847  INFO Client:Client Loop Span: buttplug::client::internal: Starting client event loop.
Dec 25 20:49:11.850  INFO Client:Client Loop Span:Client Event Loop: buttplug::server: Performing server handshake check
Dec 25 20:49:11.852  INFO Client:Client Loop Span:Client Event Loop: buttplug::server: Server handshake check successful.
Dec 25 20:49:11.854  INFO Client: buttplug::client: Connected to Buttplug Server