rust-mobile/android_logger-rs

A Rust logging implementation for `log` which hooks to android log output

Rust

144

165 commits

updated Sep 23, 2026

See the code

README

Send Rust logs to Logcat

Version CI status

This library is a drop-in replacement for env_logger. Instead, it outputs messages to android's logcat.

This only works on Android and requires linking to log which is only available under android. With Cargo, it is possible to conditionally require this library:

[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.15"

Example of initialization on activity creation, with log configuration:

#[macro_use] extern crate log;
extern crate android_logger;

use log::LevelFilter;
use android_logger::{Config,FilterBuilder};

fn native_activity_create() {
    android_logger::init_once(
        Config::default()
            .with_max_level(LevelFilter::Trace) // limit log level
            .with_tag("mytag") // logs will show under mytag tag
            .with_filter( // configure messages for specific crate
                FilterBuilder::new()
                    .try_parse("debug,hello::crate=error")
                    .expect("Failed to build filter")
                    .build())
    );

    trace!("this is a verbose {}", "message");
    error!("this is printed by default");
}

To allow all logs, use the default configuration with min level Trace:

#[macro_use] extern crate log;
extern crate android_logger;

use log::LevelFilter;
use android_logger::Config;

fn native_activity_create() {
    android_logger::init_once(
        Config::default().with_max_level(LevelFilter::Trace),
    );
}

There is a caveat that this library can only be initialized once (hence the init_once function name). However, Android native activity can be re-created every time the screen is rotated, resulting in multiple initialization calls. Therefore this library will only log a warning for subsequent init_once calls.

This library ensures that logged messages do not overflow Android log message limits by efficiently splitting messages into chunks.

Consistent log filtering in mixed Rust/C/C++ apps

Android's C logging API determines the effective log level based on a combination of a process-wide global variable, system-wide properties, and call-specific default. log + android_logger crates add another layer of log filtering on top of that, independent from the C API.

    .-----.
    | app |
    '-----'     Rust
C/C++ | '--------------.
      |                v
      |          .-----------.   filter by log::STATIC_MAX_LEVEL +
      |          | log crate | - log::MAX_LOG_LEVEL_FILTER,
      |          '-----------'   overrideable via log::set_max_level
      |                |
      |                v
      |     .----------------------.
      |     | android_logger crate | - filter by Config::max_level
      |     '----------------------'
      |                |
      |   .------------'
      v   v
   .--------.
   | liblog | - filter by global state or system-wide properties
   '--------'

liblog APIs introduced in Android API 30 let android_logger delegate log filtering decision to liblog, making the log level consistent across C, C++ and Rust calls.

If you build android_logger with android-api-30 feature enabled, the logger will consider the process-wide global state (set via __android_log_set_minimum_priority) and Android system properties when deciding if a message should be logged or not. In this case, the effective log level is the least verbose of the levels set between those and Rust log facilities.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

rust-mobile/android_logger-rs

A Rust logging implementation for `log` which hooks to android log output

Rust

144

165 commits

updated Sep 23, 2026

See the code

README

Send Rust logs to Logcat

Version CI status

This library is a drop-in replacement for env_logger. Instead, it outputs messages to android's logcat.

This only works on Android and requires linking to log which is only available under android. With Cargo, it is possible to conditionally require this library:

[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.15"

Example of initialization on activity creation, with log configuration:

#[macro_use] extern crate log;
extern crate android_logger;

use log::LevelFilter;
use android_logger::{Config,FilterBuilder};

fn native_activity_create() {
    android_logger::init_once(
        Config::default()
            .with_max_level(LevelFilter::Trace) // limit log level
            .with_tag("mytag") // logs will show under mytag tag
            .with_filter( // configure messages for specific crate
                FilterBuilder::new()
                    .try_parse("debug,hello::crate=error")
                    .expect("Failed to build filter")
                    .build())
    );

    trace!("this is a verbose {}", "message");
    error!("this is printed by default");
}

To allow all logs, use the default configuration with min level Trace:

#[macro_use] extern crate log;
extern crate android_logger;

use log::LevelFilter;
use android_logger::Config;

fn native_activity_create() {
    android_logger::init_once(
        Config::default().with_max_level(LevelFilter::Trace),
    );
}

There is a caveat that this library can only be initialized once (hence the init_once function name). However, Android native activity can be re-created every time the screen is rotated, resulting in multiple initialization calls. Therefore this library will only log a warning for subsequent init_once calls.

This library ensures that logged messages do not overflow Android log message limits by efficiently splitting messages into chunks.

Consistent log filtering in mixed Rust/C/C++ apps

Android's C logging API determines the effective log level based on a combination of a process-wide global variable, system-wide properties, and call-specific default. log + android_logger crates add another layer of log filtering on top of that, independent from the C API.

    .-----.
    | app |
    '-----'     Rust
C/C++ | '--------------.
      |                v
      |          .-----------.   filter by log::STATIC_MAX_LEVEL +
      |          | log crate | - log::MAX_LOG_LEVEL_FILTER,
      |          '-----------'   overrideable via log::set_max_level
      |                |
      |                v
      |     .----------------------.
      |     | android_logger crate | - filter by Config::max_level
      |     '----------------------'
      |                |
      |   .------------'
      v   v
   .--------.
   | liblog | - filter by global state or system-wide properties
   '--------'

liblog APIs introduced in Android API 30 let android_logger delegate log filtering decision to liblog, making the log level consistent across C, C++ and Rust calls.

If you build android_logger with android-api-30 feature enabled, the logger will consider the process-wide global state (set via __android_log_set_minimum_priority) and Android system properties when deciding if a message should be logged or not. In this case, the effective log level is the least verbose of the levels set between those and Rust log facilities.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Project health

Overall

4.0/10

Maintained

1/10

Code review

7/10
OpenSSF Scorecard

Significant stargazers

Oscar Beaumont

414 followers · starred Oct 2022

jalciné

527 followers · starred May 2026

Felix Obenhuber

75 followers · starred Sep 2017