Skip to content

Commit c4c2def

Browse files
committed
rebase
1 parent 0454065 commit c4c2def

File tree

3 files changed

+62
-97
lines changed

3 files changed

+62
-97
lines changed

src/collectors/github_rate_limit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ impl ProductMetrics {
184184
let gauge = |name, help| -> IntGauge {
185185
IntGauge::with_opts(
186186
Opts::new(name, help)
187-
.namespace("monitorbot_github_rate_limit")
187+
.namespace("github_rate_limit")
188188
.const_label("username", user)
189189
.const_label("product", product),
190190
)

src/collectors/github_runners.rs

Lines changed: 61 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use crate::{http, http::is_token_flagged, Config};
1+
use crate::{http, Config};
22
use anyhow::Error;
33
use log::{debug, error, warn};
4-
use prometheus::core::Desc;
4+
use prometheus::core::AtomicI64;
5+
use prometheus::core::{Desc, GenericGauge};
56
use prometheus::proto::MetricFamily;
67
use prometheus::{core::Collector, IntGauge, Opts};
8+
use reqwest::header::LINK;
79
use std::collections::HashMap;
810
use std::sync::{Arc, RwLock};
911
use tokio::time::Duration;
@@ -23,15 +25,6 @@ struct Runner {
2325
os: String,
2426
status: String,
2527
busy: bool,
26-
labels: Vec<Label>,
27-
}
28-
29-
#[derive(Debug, serde::Deserialize)]
30-
struct Label {
31-
id: usize,
32-
name: String,
33-
#[serde(rename = "type")]
34-
the_type: String,
3528
}
3629

3730
#[derive(Clone)]
@@ -40,8 +33,6 @@ pub struct GithubRunners {
4033
token: String,
4134
// repos to track gha runners
4235
repos: Vec<String>,
43-
// metric namespace
44-
ns: String,
4536
// actual metrics
4637
metrics: Arc<RwLock<Vec<IntGauge>>>,
4738
// default metric description
@@ -57,15 +48,13 @@ impl GithubRunners {
5748
.map(|v| v.trim().to_string())
5849
.collect();
5950

60-
let ns = String::from("gha_runner");
6151
let rv = Self {
6252
token,
6353
repos,
64-
ns: ns.clone(),
6554
metrics: Arc::new(RwLock::new(Vec::new())),
6655
desc: Desc::new(
67-
ns,
68-
"GHA runner's status".to_string(),
56+
String::from("gha_runner"),
57+
String::from("GHA runner's status"),
6958
Vec::new(),
7059
HashMap::new(),
7160
)
@@ -90,63 +79,47 @@ impl GithubRunners {
9079
async fn update_stats(&mut self) -> Result<(), Error> {
9180
let mut gauges = Vec::new();
9281
for repo in self.repos.iter() {
93-
let url = String::from(GH_RUNNERS_ENDPOINT).replace("{owner_repo}", repo);
82+
let mut url: Option<String> = String::from(GH_RUNNERS_ENDPOINT)
83+
.replace("{owner_repo}", repo)
84+
.into();
85+
86+
while url.is_some() {
87+
let response = http::get(&self.token, &url.unwrap()).send().await?;
88+
url = match response.headers().get(LINK) {
89+
Some(data) => {
90+
//TODO: parse Link header for rel=next
91+
warn!("{:#?}", data);
92+
None
93+
}
94+
_ => None,
95+
};
96+
97+
let resp = response.json::<ApiResponse>().await?;
98+
debug!("{:#?}", resp);
99+
100+
for runner in resp.runners.iter() {
101+
let online = metric_factory(
102+
"online",
103+
"runner is online",
104+
&self.desc.fq_name,
105+
&repo,
106+
&runner.name,
107+
);
94108

95-
// does this token still able to query github api? (rate limit wise)
96-
match is_token_flagged(&self.token).await {
97-
Err(e) => {
98-
error!("checking if token is flagged: {:?}", e);
99-
continue;
100-
}
101-
Ok(true) => {
102-
warn!(
103-
"token: '{}' is currently flagged. skipping data gathering",
104-
&self.token
109+
online.set(if runner.status == "online" { 1 } else { 0 });
110+
gauges.push(online);
111+
112+
// busy
113+
let busy = metric_factory(
114+
"busy",
115+
"runner is busy",
116+
&self.desc.fq_name,
117+
&repo,
118+
&runner.name,
105119
);
106-
continue;
120+
busy.set(if runner.busy { 1 } else { 0 });
121+
gauges.push(busy);
107122
}
108-
Ok(false) => {}
109-
}
110-
111-
debug!("Querying gha runner's status at: {}", url);
112-
let resp = http::get(&self.token, &url)
113-
.send()
114-
.await?
115-
.json::<ApiResponse>()
116-
.await?;
117-
118-
debug!("ApiResponse: {:#?}", resp);
119-
120-
// convert to metrics
121-
for runner in resp.runners.iter() {
122-
let status = &runner.status.clone();
123-
let value_busy = if runner.busy { 1 } else { 0 };
124-
let label_repo = repo.clone();
125-
let label_runner = runner.name.clone();
126-
127-
// online
128-
let online = IntGauge::with_opts(
129-
Opts::new("online", "runner is online.")
130-
.namespace(self.ns.clone())
131-
.const_label("repo", label_repo.clone())
132-
.const_label("runner", label_runner.clone()),
133-
)
134-
.unwrap();
135-
136-
online.set(if status == "online" { 1 } else { 0 });
137-
gauges.push(online);
138-
139-
// busy
140-
let busy = IntGauge::with_opts(
141-
Opts::new("busy", "runner is busy.")
142-
.namespace(self.ns.clone())
143-
.const_label("repo", label_repo)
144-
.const_label("runner", label_runner),
145-
)
146-
.unwrap();
147-
148-
busy.set(value_busy);
149-
gauges.push(busy);
150123
}
151124
}
152125

@@ -167,7 +140,7 @@ impl Collector for GithubRunners {
167140
self.metrics.read().map_or_else(
168141
|e| {
169142
error!("Unable to collect: {:#?}", e);
170-
Vec::new()
143+
Vec::with_capacity(0)
171144
},
172145
|guard| {
173146
guard.iter().fold(Vec::new(), |mut acc, item| {
@@ -178,3 +151,19 @@ impl Collector for GithubRunners {
178151
)
179152
}
180153
}
154+
155+
fn metric_factory<S: Into<String>>(
156+
name: S,
157+
help: S,
158+
ns: S,
159+
repo: S,
160+
runner: S,
161+
) -> GenericGauge<AtomicI64> {
162+
IntGauge::with_opts(
163+
Opts::new(name, help)
164+
.namespace(ns)
165+
.const_label("repo", repo)
166+
.const_label("runner", runner),
167+
)
168+
.unwrap()
169+
}

src/http.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
use anyhow::{Context, Error, Result};
21
use reqwest::header::{ACCEPT, AUTHORIZATION, USER_AGENT};
32
use reqwest::{Client, Method, RequestBuilder};
4-
use std::collections::HashMap;
5-
6-
pub(crate) const GH_API_RATE_LIMIT_ENDPOINT: &str = "https://api.github.com/rate_limit";
73

84
pub(crate) fn get(token: &str, url: &str) -> RequestBuilder {
95
Client::new()
@@ -15,23 +11,3 @@ pub(crate) fn get(token: &str, url: &str) -> RequestBuilder {
1511
.header(AUTHORIZATION, format!("{} {}", "token", token))
1612
.header(ACCEPT, "application/vnd.github.v3+json")
1713
}
18-
19-
#[derive(Debug, serde::Deserialize)]
20-
pub(crate) struct GithubRateLimit {
21-
pub rate: HashMap<String, usize>,
22-
}
23-
24-
pub(crate) async fn is_token_flagged(token: &str) -> Result<bool, Error> {
25-
get_token_rate_limit_stats(token)
26-
.await
27-
.map(|mut r| Ok(r.rate.remove("remaining").unwrap_or(0) == 0))?
28-
}
29-
30-
pub(crate) async fn get_token_rate_limit_stats(token: &str) -> Result<GithubRateLimit, Error> {
31-
get(token, GH_API_RATE_LIMIT_ENDPOINT)
32-
.send()
33-
.await?
34-
.json::<GithubRateLimit>()
35-
.await
36-
.context("Unable to get rate limit stats")
37-
}

0 commit comments

Comments
 (0)