Skip to content

Commit 83576aa

Browse files
committed
Make Filter non-optional, make README part of the library documentation (to also have it build-tested...)
1 parent f2ff257 commit 83576aa

File tree

8 files changed

+130
-183
lines changed

8 files changed

+130
-183
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
All user visible changes to this project will be documented in this file. This project uses [Semantic Versioning 2.0.0].
55

6+
## [TODO]
7+
8+
- Remove `max_level` in favour of extracting it from the `Filter`
9+
10+
// TODO: bunch of releases are missing?
11+
612

713

814

README.md

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,74 +7,77 @@
77
This library is a drop-in replacement for `env_logger`. Instead, it outputs messages to
88
android's logcat.
99

10-
This only works on Android and requires linking to `log` which
11-
is only available under android. With Cargo, it is possible to conditionally require
12-
this library:
10+
This only works on Android and requires linking to `liblog` which
11+
is only available under Android. With Cargo, it is possible to conditionally
12+
include this crate and library requirement when targeting Android only:
1313

1414
```toml
1515
[target.'cfg(target_os = "android")'.dependencies]
1616
android_logger = "0.15"
1717
```
1818

19-
Example of initialization on activity creation, with log configuration:
19+
### Examples
2020

21-
```rust
22-
#[macro_use] extern crate log;
23-
extern crate android_logger;
21+
#### Example of initialization on activity creation, with log configuration
2422

25-
use log::LevelFilter;
26-
use android_logger::{Config,FilterBuilder};
23+
```rust
24+
use android_logger::Config;
2725

2826
fn native_activity_create() {
2927
android_logger::init_once(
3028
Config::default()
31-
.with_max_level(LevelFilter::Trace) // limit log level
3229
.with_tag("mytag") // logs will show under mytag tag
33-
.with_filter( // configure messages for specific crate
34-
FilterBuilder::new()
35-
.parse("debug,hello::crate=error")
36-
.build())
30+
.parse_filters("debug,hello::crate=error") // Limig log level to Debug, and limit the hello::crate module further to Error.
3731
);
3832

39-
trace!("this is a verbose {}", "message");
40-
error!("this is printed by default");
33+
log::debug!("this is a verbose {}", "message");
34+
log::error!("this is printed by default");
4135
}
4236
```
4337

44-
To allow all logs, use the default configuration with min level Trace:
38+
To allow all logs, use the default configuration with the global module level set to `Trace`
4539

4640
```rust
47-
#[macro_use] extern crate log;
48-
extern crate android_logger;
49-
50-
use log::LevelFilter;
5141
use android_logger::Config;
5242

5343
fn native_activity_create() {
5444
android_logger::init_once(
55-
Config::default().with_max_level(LevelFilter::Trace),
45+
Config::default().filter_level(log::LevelFilter::Trace),
5646
);
5747
}
5848
```
5949

50+
#### Example with a custom log formatter
51+
52+
```rust
53+
use android_logger::Config;
54+
55+
android_logger::init_once(
56+
Config::default()
57+
.format(|f, record| write!(f, "my_app: {}", record.args()))
58+
)
59+
```
60+
61+
### Single-initialization guarantee
62+
6063
There is a caveat that this library can only be initialized once
6164
(hence the `init_once` function name). However, Android native activity can be
6265
re-created every time the screen is rotated, resulting in multiple initialization calls.
6366
Therefore this library will only log a warning for subsequent `init_once` calls.
6467

68+
###
69+
6570
This library ensures that logged messages do not overflow Android log message limits
6671
by efficiently splitting messages into chunks.
6772

68-
## Consistent log filtering in mixed Rust/C/C++ apps
73+
### Consistent log filtering in mixed Rust/C/C++ apps
6974

70-
Android's C logging API determines the effective log level based on [a
71-
combination](https://cs.android.com/android/platform/superproject/main/+/main:system/logging/liblog/properties.cpp;l=243;drc=b74a506c1b69f5b295a8cdfd7e2da3b16db15934)
72-
of a process-wide global variable, [system-wide
73-
properties](https://cs.android.com/android/platform/superproject/main/+/main:system/logging/logd/README.property;l=45;drc=99c545d3098018a544cb292e1501daca694bee0f),
74-
and call-specific default. `log` + `android_logger` crates add another layer of
75-
log filtering on top of that, independent from the C API.
75+
Android's C logging API determines the effective log level based on [the 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.
7676

77-
```
77+
[the combination]: https://cs.android.com/android/platform/superproject/main/+/main:system/logging/liblog/properties.cpp;l=243;drc=b74a506c1b69f5b295a8cdfd7e2da3b16db15934
78+
[system-wide properties]: https://cs.android.com/android/platform/superproject/main/+/main:system/logging/logd/README.property;l=45;drc=99c545d3098018a544cb292e1501daca694bee0f
79+
80+
```text
7881
.-----.
7982
| app |
8083
'-----' Rust
@@ -97,18 +100,19 @@ C/C++ | '--------------.
97100
```
98101

99102
`liblog` APIs introduced in Android API 30 let `android_logger` delegate log
100-
filtering decision to `liblog`, making the log level consistent across C, C++
103+
filtering decisions to `liblog`, making the log level consistent across C, C++
101104
and Rust calls.
102105

103-
If you build `android_logger` with `android-api-30` feature enabled, the logger
106+
If you build `android_logger` with the `android-api-30` feature enabled, the logger
104107
will consider the process-wide global state (set via
105108
[`__android_log_set_minimum_priority`](https://cs.android.com/android/platform/superproject/main/+/main:prebuilts/runtime/mainline/runtime/sdk/common_os/include/system/logging/liblog/include/android/log.h;l=364;drc=4cf460634134d51dba174f8af60dffb10f703f51))
106109
and Android system properties when deciding if a message should be logged or
107110
not. In this case, the effective log level is the _least verbose_ of the levels
108-
set between those and [Rust log
109-
facilities](https://docs.rs/log/latest/log/fn.set_max_level.html).
111+
set between those and [Rust log facilities].
112+
113+
[Rust log facilities]: https://docs.rs/log/latest/log/fn.set_max_level.html
110114

111-
## License
115+
### License
112116

113117
Licensed under either of
114118

examples/system_log_level_overrides.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! An utility for testing the behavior of `android_logger` crate.
1+
//! An utility for testing the behavior of the `android_logger` crate.
22
//!
33
//! ## Build
44
//!
@@ -37,7 +37,7 @@
3737
//! HOME=$PWD bin/launch_cvd
3838
//! ```
3939
//!
40-
//! Once emulator launches, `adb` should detect it on `0.0.0.0:6520`
40+
//! Once the emulator launches, `adb` should detect it on `0.0.0.0:6520`
4141
//! automatically. Shut down the `launch_cvd` command to exit the emulator.
4242
//!
4343
//! 3. Upload & run:
@@ -55,7 +55,7 @@
5555
//!
5656
//! ```
5757
//! # default: should print info+ logs in `adb logcat -s log_test`
58-
//! # hint: use `adb logcat -v color` is awesome too
58+
//! # hint: `adb logcat -v color` is awesome too
5959
//! adb shell /data/local/tmp/system_log_level_overrides
6060
//!
6161
//! # should print trace+ logs in `adb logcat -s log_test`
@@ -68,16 +68,17 @@
6868
//! ```
6969
7070
fn main() {
71-
todo!("This test and its comments are no longer true after with_max_level is removed");
7271
android_logger::init_once(
73-
android_logger::Config::default().with_tag("log_test"),
74-
// If set, this is the highest level to log unless overridden by by the system.
75-
// Note the verbosity can be *increased* through system properties.
76-
// .with_max_level(log::LevelFilter::Info),
72+
android_logger::Config::default()
73+
.with_tag("log_test")
74+
// If set, this is the highest level to log unless overridden by the system.
75+
// Note the verbosity can be *increased* through system properties, as long
76+
// as it is also increased in the `log` crate (see the override below).
77+
.filter_level(log::LevelFilter::Info),
7778
);
7879
// The log crate applies its filtering before we even get to android_logger.
7980
// Pass everything down so that Android's liblog can determine the log level instead.
80-
// log::set_max_level(log::LevelFilter::Trace);
81+
log::set_max_level(log::LevelFilter::Trace);
8182

8283
log::trace!("trace");
8384
log::debug!("debug");

src/config.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,34 @@
11
use crate::{FormatFn, LogId};
22
#[cfg(all(target_os = "android", feature = "android-api-30"))]
33
use log::LevelFilter;
4-
use log::{Level, Record};
4+
use log::{Level, LevelFilter, Record};
55
use std::ffi::CString;
66
use std::fmt;
77

88
/// Filter for android logger.
9-
#[derive(Default)]
9+
// #[derive(Default)]
10+
// TODO: Rename to Builder.
1011
pub struct Config {
1112
pub(crate) buf_id: Option<LogId>,
12-
pub(crate) filter: Option<env_filter::Filter>,
13+
pub(crate) filter: env_filter::Builder,
1314
pub(crate) tag: Option<CString>,
1415
pub(crate) custom_format: Option<FormatFn>,
1516
}
1617

18+
impl Default for Config {
19+
/// Creates a default config that logs all modules at the [`LevelFilter::Error`] level by
20+
/// default, when no other filters are set.
21+
fn default() -> Self {
22+
Self {
23+
buf_id: None,
24+
// TODO: This doesn't read from an env var like RUST_LOG...
25+
filter: env_filter::Builder::new(),
26+
tag: None,
27+
custom_format: None,
28+
}
29+
}
30+
}
31+
1732
impl fmt::Debug for Config {
1833
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1934
f.debug_struct("Config")
@@ -88,19 +103,6 @@ pub(crate) fn is_loggable(tag: &str, record_level: Level) -> bool {
88103
}
89104

90105
impl Config {
91-
// /// Changes the maximum log level.
92-
// ///
93-
// /// Note, that `Trace` is the maximum level, because it provides the
94-
// /// maximum amount of detail in the emitted logs.
95-
// ///
96-
// /// If `Off` level is provided, then nothing is logged at all.
97-
// ///
98-
// /// [`log::max_level()`] is considered as the default level.
99-
// pub fn with_max_level(mut self, level: LevelFilter) -> Self {
100-
// self.log_level = Some(level);
101-
// self
102-
// }
103-
104106
/// Changes the Android logging system buffer to be used.
105107
///
106108
/// By default, logs are sent to the [`Main`] log. Other logging buffers may
@@ -112,18 +114,26 @@ impl Config {
112114
self
113115
}
114116

115-
pub(crate) fn filter_matches(&self, record: &Record) -> bool {
116-
if let Some(ref filter) = self.filter {
117-
filter.matches(record)
118-
} else {
119-
true
120-
}
117+
/// Adds a directive to the filter for a specific module.
118+
///
119+
/// Note that this replaces the default [`LevelFilter::Error`] for all global modules.
120+
pub fn filter_module(mut self, module: &str, level: LevelFilter) -> Self {
121+
self.filter.filter_module(module, level);
122+
self
123+
}
124+
125+
/// Adds a directive to the filter for all modules.
126+
pub fn filter_level(mut self, level: LevelFilter) -> Self {
127+
self.filter.filter_level(level);
128+
self
121129
}
122130

123-
// TODO: Replace this with env_logger-like constructors:
124-
// https://docs.rs/env_logger/latest/env_logger/struct.Builder.html
125-
pub fn with_filter(mut self, filter: env_filter::Filter) -> Self {
126-
self.filter = Some(filter);
131+
/// Parses the directives string in the same form as the `RUST_LOG`
132+
/// environment variable.
133+
///
134+
/// See the `env_logger` module documentation for more details.
135+
pub fn parse_filters(mut self, filters: &str) -> Self {
136+
self.filter.parse(filters);
127137
self
128138
}
129139

@@ -137,7 +147,6 @@ impl Config {
137147
/// # use android_logger::Config;
138148
/// android_logger::init_once(
139149
/// Config::default()
140-
/// .with_max_level(log::LevelFilter::Trace)
141150
/// .format(|f, record| write!(f, "my_app: {}", record.args()))
142151
/// )
143152
/// ```

0 commit comments

Comments
 (0)