Skip to content

Commit a9e7bf3

Browse files
committed
Make graph(s) endpoints GET requests
1 parent 068fd19 commit a9e7bf3

File tree

3 files changed

+76
-60
lines changed

3 files changed

+76
-60
lines changed

site/src/request_handlers/graph.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,22 @@ use crate::interpolate::IsInterpolated;
99
use crate::load::SiteCtxt;
1010
use crate::selector::{Query, Selector, SeriesResponse, Tag};
1111

12-
pub async fn handle_graph(body: graph::Request, ctxt: &SiteCtxt) -> ServerResult<graph::Response> {
13-
log::info!("handle_graph({:?})", body);
12+
pub async fn handle_graph(
13+
request: graph::Request,
14+
ctxt: Arc<SiteCtxt>,
15+
) -> ServerResult<graph::Response> {
16+
log::info!("handle_graph({:?})", request);
1417

15-
create_graph(body, ctxt).await
18+
create_graph(request, ctxt).await
1619
}
1720

1821
pub async fn handle_graphs(
19-
body: graphs::Request,
20-
ctxt: &SiteCtxt,
22+
request: graphs::Request,
23+
ctxt: Arc<SiteCtxt>,
2124
) -> ServerResult<Arc<graphs::Response>> {
22-
log::info!("handle_graphs({:?})", body);
25+
log::info!("handle_graphs({:?})", request);
2326

24-
let is_default_query = body
27+
let is_default_query = request
2528
== graphs::Request {
2629
start: Bound::None,
2730
end: Bound::None,
@@ -36,41 +39,45 @@ pub async fn handle_graphs(
3639
}
3740
}
3841

39-
let resp = create_graphs(body, ctxt).await?;
42+
let resp = create_graphs(request, &ctxt).await?;
4043

4144
if is_default_query {
4245
ctxt.landing_page.store(Arc::new(Some(resp.clone())));
4346
}
4447

4548
Ok(resp)
4649
}
47-
async fn create_graph(body: graph::Request, ctxt: &SiteCtxt) -> ServerResult<graph::Response> {
48-
let artifact_ids = artifact_ids_for_range(ctxt, body.start, body.end);
50+
51+
async fn create_graph(
52+
request: graph::Request,
53+
ctxt: Arc<SiteCtxt>,
54+
) -> ServerResult<graph::Response> {
55+
let artifact_ids = artifact_ids_for_range(&ctxt, request.start, request.end);
4956
let mut series_iterator = ctxt
5057
.statistic_series(
5158
Query::new()
52-
.set::<String>(Tag::Benchmark, Selector::One(body.benchmark))
53-
.set::<String>(Tag::Profile, Selector::One(body.profile))
54-
.set::<String>(Tag::Scenario, Selector::One(body.scenario))
55-
.set::<String>(Tag::Metric, Selector::One(body.metric)),
59+
.set::<String>(Tag::Benchmark, Selector::One(request.benchmark))
60+
.set::<String>(Tag::Profile, Selector::One(request.profile))
61+
.set::<String>(Tag::Scenario, Selector::One(request.scenario))
62+
.set::<String>(Tag::Metric, Selector::One(request.metric)),
5663
Arc::new(artifact_ids),
5764
)
5865
.await?
5966
.into_iter()
6067
.map(SeriesResponse::interpolate);
6168

6269
let result = series_iterator.next().unwrap();
63-
let graph_series = graph_series(result.series, body.kind);
70+
let graph_series = graph_series(result.series, request.kind);
6471
Ok(graph::Response {
6572
series: graph_series,
6673
})
6774
}
6875

6976
async fn create_graphs(
70-
body: graphs::Request,
77+
request: graphs::Request,
7178
ctxt: &SiteCtxt,
7279
) -> ServerResult<Arc<graphs::Response>> {
73-
let artifact_ids = Arc::new(artifact_ids_for_range(ctxt, body.start, body.end));
80+
let artifact_ids = Arc::new(artifact_ids_for_range(ctxt, request.start, request.end));
7481
let mut benchmarks = HashMap::new();
7582

7683
let interpolated_responses: Vec<_> = ctxt
@@ -79,23 +86,23 @@ async fn create_graphs(
7986
.set::<String>(Tag::Benchmark, Selector::All)
8087
.set::<String>(Tag::Profile, Selector::All)
8188
.set::<String>(Tag::Scenario, Selector::All)
82-
.set::<String>(Tag::Metric, Selector::One(body.stat)),
89+
.set::<String>(Tag::Metric, Selector::One(request.stat)),
8390
artifact_ids.clone(),
8491
)
8592
.await?
8693
.into_iter()
8794
.map(|sr| sr.interpolate().map(|series| series.collect::<Vec<_>>()))
8895
.collect();
8996

90-
let summary_benchmark = create_summary(ctxt, &interpolated_responses, body.kind)?;
97+
let summary_benchmark = create_summary(ctxt, &interpolated_responses, request.kind)?;
9198

9299
benchmarks.insert("Summary".to_string(), summary_benchmark);
93100

94101
for response in interpolated_responses {
95102
let benchmark = response.path.get::<Benchmark>()?.to_string();
96103
let profile = *response.path.get::<Profile>()?;
97104
let scenario = response.path.get::<Scenario>()?.to_string();
98-
let graph_series = graph_series(response.series.into_iter(), body.kind);
105+
let graph_series = graph_series(response.series.into_iter(), request.kind);
99106

100107
benchmarks
101108
.entry(benchmark)

site/src/server.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,39 @@ impl Server {
131131
.unwrap())
132132
}
133133

134+
async fn handle_fallible_get_async<F, R, S, E>(
135+
&self,
136+
req: &Request,
137+
handler: F,
138+
) -> Result<Response, ServerError>
139+
where
140+
F: FnOnce(Arc<SiteCtxt>) -> R,
141+
R: std::future::Future<Output = Result<S, E>> + Send,
142+
S: Serialize,
143+
E: Into<Vec<u8>>,
144+
{
145+
check_http_method!(*req.method(), http::Method::GET);
146+
let ctxt = self.ctxt.clone();
147+
let ctxt = ctxt.read().as_ref().unwrap().clone();
148+
let result = handler(ctxt).await;
149+
let response = match result {
150+
Ok(result) => {
151+
let response = http::Response::builder()
152+
.header_typed(ContentType::json())
153+
.header_typed(CacheControl::new().with_no_cache().with_no_store());
154+
let body = serde_json::to_vec(&result).unwrap();
155+
response.body(hyper::Body::from(body)).unwrap()
156+
}
157+
Err(err) => http::Response::builder()
158+
.status(StatusCode::INTERNAL_SERVER_ERROR)
159+
.header_typed(ContentType::text_utf8())
160+
.header_typed(CacheControl::new().with_no_cache().with_no_store())
161+
.body(hyper::Body::from(err.into()))
162+
.unwrap(),
163+
};
164+
Ok(response)
165+
}
166+
134167
fn check_auth(&self, req: &http::request::Parts) -> bool {
135168
if let Some(auth) = req
136169
.headers
@@ -317,6 +350,18 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
317350
crate::comparison::handle_triage(input, &ctxt).await,
318351
));
319352
}
353+
"/perf/graph" => {
354+
let query = check!(parse_query_string(req.uri()));
355+
return server
356+
.handle_fallible_get_async(&req, |c| request_handlers::handle_graph(query, c))
357+
.await;
358+
}
359+
"/perf/graphs" => {
360+
let query = check!(parse_query_string(req.uri()));
361+
return server
362+
.handle_fallible_get_async(&req, |c| request_handlers::handle_graphs(query, c))
363+
.await;
364+
}
320365
"/perf/metrics" => {
321366
return Ok(server.handle_metrics(req).await);
322367
}
@@ -403,40 +448,6 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
403448
"/perf/self-profile-raw" => Ok(to_response(
404449
request_handlers::handle_self_profile_raw(check!(parse_body(&body)), &ctxt).await,
405450
)),
406-
"/perf/graph" => Ok(
407-
match request_handlers::handle_graph(check!(parse_body(&body)), &ctxt).await {
408-
Ok(result) => {
409-
let response = http::Response::builder()
410-
.header_typed(ContentType::json())
411-
.header_typed(CacheControl::new().with_no_cache().with_no_store());
412-
let body = serde_json::to_vec(&result).unwrap();
413-
response.body(hyper::Body::from(body)).unwrap()
414-
}
415-
Err(err) => http::Response::builder()
416-
.status(StatusCode::INTERNAL_SERVER_ERROR)
417-
.header_typed(ContentType::text_utf8())
418-
.header_typed(CacheControl::new().with_no_cache().with_no_store())
419-
.body(hyper::Body::from(err))
420-
.unwrap(),
421-
},
422-
),
423-
"/perf/graphs" => Ok(
424-
match request_handlers::handle_graphs(check!(parse_body(&body)), &ctxt).await {
425-
Ok(result) => {
426-
let response = http::Response::builder()
427-
.header_typed(ContentType::json())
428-
.header_typed(CacheControl::new().with_no_cache().with_no_store());
429-
let body = serde_json::to_vec(&result).unwrap();
430-
response.body(hyper::Body::from(body)).unwrap()
431-
}
432-
Err(err) => http::Response::builder()
433-
.status(StatusCode::INTERNAL_SERVER_ERROR)
434-
.header_typed(ContentType::text_utf8())
435-
.header_typed(CacheControl::new().with_no_cache().with_no_store())
436-
.body(hyper::Body::from(err))
437-
.unwrap(),
438-
},
439-
),
440451
"/perf/bootstrap" => Ok(
441452
match request_handlers::handle_bootstrap(check!(parse_body(&body)), &ctxt).await {
442453
Ok(result) => {

site/static/index.html

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,9 @@ <h3>This may take a while!</h3>
387387
document.querySelector("#loading").style.display = 'none';
388388
}
389389

390-
function post_json(path, body) {
391-
return fetch(BASE_URL + path, {
392-
method: "POST",
393-
body: JSON.stringify(body),
394-
}).then(r => r.json());
390+
function get_json(path, query) {
391+
let q = Object.entries(query).map(e => `${e[0]}=${e[1]}`).join("&");
392+
return fetch(BASE_URL + path + "?" + q).then(r => r.json());
395393
}
396394

397395
function prepData(data) {
@@ -439,7 +437,7 @@ <h3>This may take a while!</h3>
439437
stat: "instructions:u",
440438
kind: "raw",
441439
}, state);
442-
post_json("/graphs", values).then(prepData).then(data =>
440+
get_json("/graphs", values).then(prepData).then(data =>
443441
renderPlots(data, values));
444442
});
445443
</script>

0 commit comments

Comments
 (0)