70 lines
1.8 KiB
Rust
70 lines
1.8 KiB
Rust
|
use axum::{
|
||
|
routing::get,
|
||
|
Router,
|
||
|
};
|
||
|
|
||
|
use serde::{
|
||
|
Deserialize,
|
||
|
Serialize,
|
||
|
};
|
||
|
|
||
|
#[derive(Serialize, Deserialize)]
|
||
|
struct TrafficDataThresholds {
|
||
|
level: i64,
|
||
|
threshold: i64,
|
||
|
color: String,
|
||
|
description: String,
|
||
|
}
|
||
|
|
||
|
#[derive(Serialize, Deserialize)]
|
||
|
struct TrafficDataItem {
|
||
|
id: String,
|
||
|
level: i64,
|
||
|
color: Option<String>,
|
||
|
description: Option<String>,
|
||
|
counter: Option<i64>,
|
||
|
automatic: bool,
|
||
|
thresholds: Vec<TrafficDataThresholds>,
|
||
|
}
|
||
|
|
||
|
#[tokio::main]
|
||
|
async fn main() {
|
||
|
let app = Router::new()
|
||
|
.route("/", get(route_index))
|
||
|
.route("/metrics", get(route_metrics));
|
||
|
|
||
|
let listener = tokio::net::TcpListener::bind("[::]:3000").await.unwrap();
|
||
|
println!("Server listening on: http://{}", listener.local_addr().unwrap());
|
||
|
|
||
|
axum::serve(listener, app).await.unwrap();
|
||
|
}
|
||
|
|
||
|
async fn route_index() -> String {
|
||
|
return String::from("Prometheus exporter for Berlinerbaeder occupancy");
|
||
|
}
|
||
|
|
||
|
async fn route_metrics() -> Result<String, String> {
|
||
|
let client = reqwest::Client::new();
|
||
|
let trafficdata_req = client.get(String::from("https://www.berlinerbaeder.de/traffic/trafficdata.json"))
|
||
|
.send().await
|
||
|
.map_err(|_err| String::from("trafficdata API cannot be fetched"))?;
|
||
|
|
||
|
if trafficdata_req.status() != reqwest::StatusCode::OK {
|
||
|
return Err(String::from("Unexpected response from trafficdata API"));
|
||
|
}
|
||
|
|
||
|
let trafficdata_body = trafficdata_req.text().await
|
||
|
.map_err(|_err| "Cannot read body of trafficdata API")?;
|
||
|
|
||
|
let trafficdata: Vec<TrafficDataItem> = serde_json::from_str(trafficdata_body.as_str())
|
||
|
.map_err(|err| format!("{}", err))?;
|
||
|
|
||
|
let mut out = String::new();
|
||
|
|
||
|
for bad in trafficdata {
|
||
|
out.push_str(&format!("berlinerbaeder_occupation{{bad=\"{}\"}} {}\n", bad.id, bad.counter.unwrap_or(-1)));
|
||
|
}
|
||
|
|
||
|
return Ok(out);
|
||
|
}
|