Skip to content

Commit

Permalink
feat: filtering device by shell getprop ro.product.model
Browse files Browse the repository at this point in the history
  • Loading branch information
pyxis committed Dec 13, 2023
1 parent 51a1af0 commit bc50d0e
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 3 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ clap = { version = "4.4.11", features = ["derive"] }
derive_builder = "0.12.0"
lazy_static = "1.4.0"
regex = "1.10.2"
tokio = { version = "1.34.0", features = ["full"] }
tokio = { version = "1.34.0", features = ["full"] }
wait-timeout = "0.2.0"
53 changes: 51 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,60 @@
Prometheus exporter for expose 'adb devices' on host

## Metrics
* connected_android_device guage
* connected_android_device_state_(device|unauthorized|disconnected|sideload|recovery|offline|fastbood|bootloader) gauge
```
# HELP connected_android_device Information about Android devices connected to the host.
# TYPE connected_android_device gauge
connected_android_device 0
# HELP connected_android_device_state_device Number of Android devices connected in 'device' status
# TYPE connected_android_device_state_device gauge
connected_android_device_state_device 0
# HELP connected_android_device_state_unauthorized Number of Android devices connected in 'unauthorized' status
# TYPE connected_android_device_state_unauthorized gauge
connected_android_device_state_unauthorized 0
# HELP connected_android_device_state_disconnected Number of Android devices connected in 'disconnected' status
# TYPE connected_android_device_state_disconnected gauge
connected_android_device_state_disconnected 0
# HELP connected_android_device_state_sideload Number of Android devices connected in 'sideload' status
# TYPE connected_android_device_state_sideload gauge
connected_android_device_state_sideload 0
# HELP connected_android_device_state_recovery Number of Android devices connected in 'recovery' status
# TYPE connected_android_device_state_recovery gauge
connected_android_device_state_recovery 0
# HELP connected_android_device_state_offline Number of Android devices connected in 'offline' status
# TYPE connected_android_device_state_offline gauge
connected_android_device_state_offline 0
# HELP connected_android_device_state_fastbootd Number of Android devices connected in 'fastbootd' status
# TYPE connected_android_device_state_fastbootd gauge
connected_android_device_state_fastbootd 0
# HELP connected_android_device_state_bootloader Number of Android devices connected in 'bootloader' status
# TYPE connected_android_device_state_bootloader gauge
connected_android_device_state_bootloader 0
```

## Usage

```
Prometheus exporter for monitoring adb devices
Usage: adb-devices-prometheus-exporter [OPTIONS]
Options:
-p <PORT> Port to listening metrics endpoint [default: 9001]
-f, --filter-commend-available Filtering devices that are in 'device' status but cannot be used
-h, --help Print help
-V, --version Print version
```

### Install

for macOS and Homebrew users
```
brew tap windsekirun/tap
Expand Down
5 changes: 5 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ use clap::Parser;
#[clap(author, version, about)]
#[clap(about = "Prometheus exporter for monitoring adb devices")]
pub struct Cli {
/// Port to listening metrics endpoint
#[clap(default_value_t = 9001, short = 'p')]
pub port: u32,

/// Filtering devices that are in 'device' status but cannot be used
#[clap(long, short, action, short = 'f')]
pub filter_commend_available: bool
}
50 changes: 50 additions & 0 deletions src/device.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
use clap::Parser;
use regex::Regex;
use std::{
io::{BufRead, BufReader},
process::{Command, Stdio},
time::Duration,
};
use wait_timeout::ChildExt;

use crate::cli;

lazy_static! {
static ref ADB_DEVICES_PATTERN: Regex = Regex::new(r"(\S+)\s+(device|offline|recovery|fastbootd|sideload|unauthorized|disconnected|bootloader)?\s*usb:(\S+)\s(?:product:(\S+)\s+)?(?:model:(\S+)\s+)?(?:device:(\S+)\s+)?transport_id:(\S+)").unwrap();
}

#[derive(Clone)]
pub struct DeviceInfo {
pub serial: String,
pub state: String,
Expand All @@ -32,7 +38,51 @@ pub fn get_device_list() -> Vec<DeviceInfo> {
state: captures.get(2).map_or("", |m| m.as_str()).to_string(),
model: captures.get(5).map_or("", |m| m.as_str()).to_string(),
})
.map(|info| check_command_available(&info))
.collect();

return device_infos;
}

fn check_command_available(device_info: &DeviceInfo) -> DeviceInfo {
let cli = cli::Cli::parse();
let filter_command_available = cli.filter_commend_available;

if !filter_command_available {
return device_info.clone();
}

// Doesn't filter when device has not 'device' state (unauthorized.. etc)
if device_info.state != "device" {
return device_info.clone();
}

let mut child: std::process::Child = Command::new("adb")
.arg("-s")
.arg(&device_info.serial)
.arg("shell")
.arg("getprop")
.arg("ro.product.model")
.stdout(Stdio::piped())
.spawn()
.unwrap();

let one_sec = Duration::from_secs(1);

let status_code = match child.wait_timeout(one_sec).unwrap() {
Some(status) => status.code(),
None => {
// child hasn't exited yet
child.kill().unwrap();
child.wait().unwrap().code()
}
};

if status_code.is_some() && status_code.unwrap() != 0 {
let mut new_info = device_info.clone();
new_info.state = "FILTERED".to_owned();
return new_info;
}

return device_info.clone();
}

0 comments on commit bc50d0e

Please sign in to comment.