bugfixes 0.2.4

Rust logging client for Bugfixes with optional remote reporting
Documentation

bugfixes

Rust logging client for Bugfixes.

It provides:

  • local log output with file and line capture
  • global logging macros for application code
  • explicit logger instances for dependency injection
  • optional remote reporting to POST /log
  • optional panic and bug reporting to POST /bug
  • local-only logging paths for operational noise

Install

[dependencies]
bugfixes = "0.1.0"

Environment

Remote reporting is configured through:

  • BUGFIXES_AGENT_KEY
  • BUGFIXES_LOG_LEVEL
  • BUGFIXES_LOCAL_ONLY
  • BUGFIXES_SERVER

If the API key is missing, logs still print locally and remote reporting is skipped.

Examples

Runnable examples live in examples/:

  • cargo run --example app_init
  • cargo run --example explicit_logger
  • cargo run --example local_only

Recommended app setup

For most binaries, initialize the global logger once at startup and then use the macros everywhere else:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    init_bugfixes()?;

    bugfixes::info!("server starting on {}", ":3000")?;
    bugfixes::warn!("slow request threshold set to {}ms", 250)?;

    Ok(())
}

fn init_bugfixes() -> Result<(), Box<dyn std::error::Error>> {
    bugfixes::init_global_from_env()?;
    bugfixes::install_global_panic_hook();
    Ok(())
}

That is usually all you need. You do not need a custom init function to fall back to local-only mode when credentials are absent.

Explicit logger instances

Use explicit logger instances in library code, services built around dependency injection, or anywhere you want logging to be passed in explicitly:

use bugfixes::BugfixesLogger;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let logger = BugfixesLogger::from_env()?;
    handle_request(&logger)?;
    Ok(())
}

fn handle_request(logger: &BugfixesLogger) -> Result<(), Box<dyn std::error::Error>> {
    logger.info("request started")?;
    logger.warn("upstream latency is elevated")?;
    Ok(())
}

Local-only logging

Use local-only logging when a message should never be sent remotely:

use bugfixes::{BugfixesLogger, init_global_local, local_logger};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    BugfixesLogger::local()?.info("warming cache")?;
    local_logger().warn("retry loop is still booting")?;

    init_global_local()?;
    bugfixes::local::info!("server started on {}", ":3000")?;
    bugfixes::local::warn!("health check is not ready yet")?;

    Ok(())
}

API shape

The crate supports both:

  • explicit logger instances for libraries and injected dependencies
  • global macros for application code
  • local_logger() for direct local-only logging
  • bugfixes::local::{...} macros for namespaced local-only logging

Typical macro usage looks like this:

bugfixes::debug!("loaded {}", 3);
bugfixes::info!("started");
bugfixes::warn!("slow request");
bugfixes::error!("db error: {}", "timeout")?;

Panic capture is available either explicitly:

let logger = bugfixes::BugfixesLogger::from_env()?;
let _ = logger.report_panic_payload(&"worker crashed");

or through a global hook:

bugfixes::init_global_from_env()?;
bugfixes::install_global_panic_hook();