Skip to content

Commit 6915e68

Browse files
committed
add api handler
1 parent 2f18ecf commit 6915e68

File tree

4 files changed

+113
-2
lines changed

4 files changed

+113
-2
lines changed

site/src/api.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,62 @@ pub mod detail_sections {
201201
}
202202
}
203203

204+
pub mod runtime_detail_graphs {
205+
use crate::api::graphs::{GraphKind, Series};
206+
use collector::Bound;
207+
use serde::de::{DeserializeOwned, Error};
208+
use serde::{Deserialize, Deserializer, Serialize};
209+
use std::fmt::Formatter;
210+
use std::marker::PhantomData;
211+
212+
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
213+
pub struct Request {
214+
pub start: Bound,
215+
pub end: Bound,
216+
pub stat: String,
217+
pub benchmark: String,
218+
pub scenario: String,
219+
pub profile: String,
220+
#[serde(deserialize_with = "vec_from_comma_separated")]
221+
pub kinds: Vec<GraphKind>,
222+
}
223+
224+
// Deserializes a comma separated list of GraphKind values
225+
fn vec_from_comma_separated<'de, T: DeserializeOwned, D>(
226+
deserializer: D,
227+
) -> Result<Vec<T>, D::Error>
228+
where
229+
D: Deserializer<'de>,
230+
{
231+
struct CommaSeparatedVisitor<T>(PhantomData<T>);
232+
233+
impl<'de, T: DeserializeOwned> serde::de::Visitor<'de> for CommaSeparatedVisitor<T> {
234+
type Value = Vec<T>;
235+
236+
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
237+
formatter.write_str("comma separated list of GraphKind values")
238+
}
239+
240+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
241+
where
242+
E: Error,
243+
{
244+
v.split(',')
245+
.map(|v| T::deserialize(serde::de::value::StrDeserializer::new(v)))
246+
.collect::<Result<Vec<T>, _>>()
247+
}
248+
}
249+
250+
deserializer.deserialize_str(CommaSeparatedVisitor(Default::default()))
251+
}
252+
253+
#[derive(Debug, Serialize)]
254+
pub struct Response {
255+
pub commits: Vec<(i64, String)>,
256+
pub graphs: Vec<Series>,
257+
}
258+
}
259+
204260
pub mod bootstrap {
205261
use collector::Bound;
206262
use hashbrown::HashMap;

site/src/request_handlers.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ mod status_page;
99
pub use bootstrap::handle_bootstrap;
1010
pub use dashboard::handle_dashboard;
1111
pub use github::handle_github;
12-
pub use graph::{handle_compile_detail_graphs, handle_compile_detail_sections, handle_graphs};
12+
pub use graph::{
13+
handle_compile_detail_graphs, handle_compile_detail_sections, handle_graphs,
14+
handle_runtime_detail_graphs,
15+
};
1316
pub use next_artifact::handle_next_artifact;
1417
pub use self_profile::{
1518
handle_self_profile, handle_self_profile_processed_download, handle_self_profile_raw,

site/src/request_handlers/graph.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use collector::Bound;
55

66
use crate::api::detail_sections::CompilationSections;
77
use crate::api::graphs::GraphKind;
8-
use crate::api::{detail_graphs, detail_sections, graphs, ServerResult};
8+
use crate::api::{detail_graphs, detail_sections, graphs, runtime_detail_graphs, ServerResult};
99
use crate::db::{self, ArtifactId, Profile, Scenario};
1010
use crate::interpolate::IsInterpolated;
1111
use crate::load::SiteCtxt;
@@ -121,6 +121,50 @@ pub async fn handle_compile_detail_sections(
121121
Ok(detail_sections::Response { before, after })
122122
}
123123

124+
pub async fn handle_runtime_detail_graphs(
125+
request: runtime_detail_graphs::Request,
126+
ctxt: Arc<SiteCtxt>,
127+
) -> ServerResult<runtime_detail_graphs::Response> {
128+
log::info!("handle_runtime_detail_graphs({:?})", request);
129+
130+
let artifact_ids = Arc::new(master_artifact_ids_for_range(
131+
&ctxt,
132+
request.start,
133+
request.end,
134+
));
135+
136+
let scenario = request.scenario.parse()?;
137+
let interpolated_responses: Vec<_> = ctxt
138+
.statistic_series(
139+
CompileBenchmarkQuery::default()
140+
.benchmark(Selector::One(request.benchmark.clone()))
141+
.profile(Selector::One(request.profile.parse()?))
142+
.scenario(Selector::One(scenario))
143+
.metric(Selector::One(request.stat.parse()?)),
144+
artifact_ids.clone(),
145+
)
146+
.await?
147+
.into_iter()
148+
.map(|sr| sr.interpolate().map(|series| series.collect::<Vec<_>>()))
149+
.collect();
150+
151+
let mut graphs = Vec::new();
152+
153+
let mut interpolated_responses = interpolated_responses.into_iter();
154+
if let Some(response) = interpolated_responses.next() {
155+
let series = response.series.into_iter().collect::<Vec<_>>();
156+
for kind in request.kinds {
157+
graphs.push(graph_series(series.clone().into_iter(), kind));
158+
}
159+
}
160+
assert!(interpolated_responses.next().is_none());
161+
162+
Ok(runtime_detail_graphs::Response {
163+
commits: artifact_ids_to_commits(artifact_ids),
164+
graphs,
165+
})
166+
}
167+
124168
pub async fn handle_graphs(
125169
request: graphs::Request,
126170
ctxt: Arc<SiteCtxt>,

site/src/server.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,14 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
410410
})
411411
.await;
412412
}
413+
"/perf/compare-runtime-detail-graphs" => {
414+
let query = check!(parse_query_string(req.uri()));
415+
return server
416+
.handle_fallible_get_async(&req, &compression, |c| {
417+
request_handlers::handle_runtime_detail_graphs(query, c)
418+
})
419+
.await;
420+
}
413421
"/perf/graphs" => {
414422
let query = check!(parse_query_string(req.uri()));
415423
return server

0 commit comments

Comments
 (0)