Skip to content

Commit 29aa2cb

Browse files
committed
Add self_profile_processed types for processed self-profile endpoint
Instead of reusing `self_profile_raw` request and response types, use separate `self_profile_processed` types. Also, remove `get_self_profile_raw` and use serde to deserialize requests, which automatically enables support for the previously non-functioning `cid` parameter.
1 parent 2d18c1d commit 29aa2cb

File tree

5 files changed

+83
-98
lines changed

5 files changed

+83
-98
lines changed

site/src/api.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,38 @@ pub mod self_profile_raw {
266266
}
267267
}
268268

269+
pub mod self_profile_processed {
270+
use serde::{Deserialize, Serialize};
271+
272+
#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
273+
#[serde(rename_all = "lowercase")]
274+
pub enum ProcessorType {
275+
#[serde(rename = "codegen-schedule")]
276+
CodegenSchedule,
277+
Crox,
278+
Flamegraph,
279+
}
280+
281+
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
282+
pub struct Request {
283+
pub commit: String,
284+
pub benchmark: String,
285+
pub run_name: String,
286+
pub cid: Option<i32>,
287+
#[serde(rename = "type")]
288+
pub processor_type: ProcessorType,
289+
#[serde(default, flatten)]
290+
pub params: std::collections::HashMap<String, String>,
291+
}
292+
293+
#[derive(Debug, Clone, Serialize)]
294+
pub struct Response {
295+
pub cids: Vec<i32>,
296+
pub cid: i32,
297+
pub url: String,
298+
}
299+
}
300+
269301
pub mod self_profile {
270302
use database::QueryLabel;
271303
use serde::{Deserialize, Serialize};

site/src/request_handlers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ pub use github::handle_github;
1212
pub use graph::{handle_graph, handle_graph_new};
1313
pub use next_commit::handle_next_commit;
1414
pub use self_profile::{
15-
get_self_profile_raw, handle_self_profile, handle_self_profile_processed_download,
16-
handle_self_profile_raw, handle_self_profile_raw_download,
15+
handle_self_profile, handle_self_profile_processed_download, handle_self_profile_raw,
16+
handle_self_profile_raw_download,
1717
};
1818
pub use status_page::handle_status_page;
1919

site/src/request_handlers/self_profile.rs

Lines changed: 29 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
1-
use std::collections::{HashMap, HashSet};
1+
use std::collections::HashSet;
22
use std::io::Read;
33
use std::sync::Arc;
44
use std::time::{Duration, Instant};
55

66
use bytes::Buf;
77
use headers::{ContentType, Header};
88
use hyper::StatusCode;
9-
use log::error;
109

11-
use crate::api::{self_profile, self_profile_raw, ServerResult};
10+
use crate::api::{self_profile, self_profile_processed, self_profile_raw, ServerResult};
1211
use crate::db::ArtifactId;
1312
use crate::load::SiteCtxt;
1413
use crate::selector::{self, Tag};
15-
use crate::server::{Request, Response, ResponseHeaders};
14+
use crate::server::{Response, ResponseHeaders};
1615

1716
pub async fn handle_self_profile_processed_download(
18-
body: self_profile_raw::Request,
19-
mut params: HashMap<String, String>,
17+
body: self_profile_processed::Request,
2018
ctxt: &SiteCtxt,
2119
) -> http::Response<hyper::Body> {
20+
let mut params = body.params.clone();
2221
let diff_against = params.remove("base_commit");
23-
if params
24-
.get("type")
25-
.map_or(false, |t| t != "codegen-schedule")
22+
23+
if body.processor_type != self_profile_processed::ProcessorType::CodegenSchedule
2624
&& diff_against.is_some()
2725
{
28-
let mut resp = Response::new("Only codegen_schedule supports diffing right now.".into());
26+
let mut resp = Response::new("Only codegen-schedule supports diffing right now.".into());
2927
*resp.status_mut() = StatusCode::BAD_REQUEST;
3028
return resp;
3129
}
@@ -75,7 +73,17 @@ pub async fn handle_self_profile_processed_download(
7573
None
7674
};
7775

78-
let data = match handle_self_profile_raw(body, ctxt).await {
76+
let data = match handle_self_profile_raw(
77+
self_profile_raw::Request {
78+
commit: body.commit,
79+
benchmark: body.benchmark.clone(),
80+
run_name: body.run_name.clone(),
81+
cid: body.cid,
82+
},
83+
ctxt,
84+
)
85+
.await
86+
{
7987
Ok(v) => match get_self_profile_raw_data(&v.url).await {
8088
Ok(v) => v,
8189
Err(e) => return e,
@@ -89,15 +97,16 @@ pub async fn handle_self_profile_processed_download(
8997

9098
log::trace!("got data in {:?}", start.elapsed());
9199

92-
let output = match crate::self_profile::generate(&title, base_data, data, params) {
93-
Ok(c) => c,
94-
Err(e) => {
95-
log::error!("Failed to generate json {:?}", e);
96-
let mut resp = http::Response::new(format!("{:?}", e).into());
97-
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
98-
return resp;
99-
}
100-
};
100+
let output =
101+
match crate::self_profile::generate(&title, body.processor_type, base_data, data, params) {
102+
Ok(c) => c,
103+
Err(e) => {
104+
log::error!("Failed to generate json {:?}", e);
105+
let mut resp = http::Response::new(format!("{:?}", e).into());
106+
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
107+
return resp;
108+
}
109+
};
101110
let mut builder = http::Response::builder()
102111
.header_typed(if output.filename.ends_with("json") {
103112
ContentType::json()
@@ -436,60 +445,6 @@ pub async fn handle_self_profile_raw_download(
436445
server_resp
437446
}
438447

439-
pub fn get_self_profile_raw(
440-
req: &Request,
441-
) -> Result<(HashMap<String, String>, self_profile_raw::Request), http::Response<hyper::Body>> {
442-
// FIXME: how should this look?
443-
let url = match url::Url::parse(&format!("http://example.com{}", req.uri())) {
444-
Ok(v) => v,
445-
Err(e) => {
446-
error!("failed to parse url {}: {:?}", req.uri(), e);
447-
return Err(http::Response::builder()
448-
.header_typed(ContentType::text_utf8())
449-
.status(StatusCode::BAD_REQUEST)
450-
.body(hyper::Body::from(format!(
451-
"failed to parse url {}: {:?}",
452-
req.uri(),
453-
e
454-
)))
455-
.unwrap());
456-
}
457-
};
458-
let mut parts = url
459-
.query_pairs()
460-
.into_owned()
461-
.collect::<HashMap<String, String>>();
462-
macro_rules! key_or_error {
463-
($ident:ident) => {
464-
if let Some(v) = parts.remove(stringify!($ident)) {
465-
v
466-
} else {
467-
error!(
468-
"failed to deserialize request {}: missing {} in query string",
469-
req.uri(),
470-
stringify!($ident)
471-
);
472-
return Err(http::Response::builder()
473-
.header_typed(ContentType::text_utf8())
474-
.status(StatusCode::BAD_REQUEST)
475-
.body(hyper::Body::from(format!(
476-
"failed to deserialize request {}: missing {} in query string",
477-
req.uri(),
478-
stringify!($ident)
479-
)))
480-
.unwrap());
481-
}
482-
};
483-
}
484-
let request = self_profile_raw::Request {
485-
commit: key_or_error!(commit),
486-
benchmark: key_or_error!(benchmark),
487-
run_name: key_or_error!(run_name),
488-
cid: None,
489-
};
490-
return Ok((parts, request));
491-
}
492-
493448
async fn tarball(resp: reqwest::Response, mut sender: hyper::body::Sender) {
494449
// Ideally, we would stream the response though the snappy decoding, but
495450
// snappy doesn't support that AFAICT -- we'd need it to implement AsyncRead

site/src/self_profile.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ mod codegen_schedule;
88
pub mod crox;
99
pub mod flamegraph;
1010

11+
pub type ProcessorType = crate::api::self_profile_processed::ProcessorType;
12+
1113
pub struct Output {
1214
pub data: Vec<u8>,
1315
pub filename: &'static str,
@@ -16,13 +18,13 @@ pub struct Output {
1618

1719
pub fn generate(
1820
title: &str,
21+
processor_type: ProcessorType,
1922
self_profile_base_data: Option<Vec<u8>>,
2023
self_profile_data: Vec<u8>,
21-
mut params: HashMap<String, String>,
24+
params: HashMap<String, String>,
2225
) -> anyhow::Result<Output> {
23-
let removed = params.remove("type");
24-
match removed.as_deref() {
25-
Some("crox") => {
26+
match processor_type {
27+
ProcessorType::Crox => {
2628
let opt = serde_json::from_str(&serde_json::to_string(&params).unwrap())
2729
.context("crox opts")?;
2830
Ok(Output {
@@ -31,7 +33,7 @@ pub fn generate(
3133
is_download: true,
3234
})
3335
}
34-
Some("flamegraph") => {
36+
ProcessorType::Flamegraph => {
3537
let opt = serde_json::from_str(&serde_json::to_string(&params).unwrap())
3638
.context("flame opts")?;
3739
Ok(Output {
@@ -40,7 +42,7 @@ pub fn generate(
4042
is_download: false,
4143
})
4244
}
43-
Some("codegen-schedule") => {
45+
ProcessorType::CodegenSchedule => {
4446
let opt =
4547
serde_json::from_str(&serde_json::to_string(&params).unwrap()).context("params")?;
4648
Ok(Output {

site/src/server.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,9 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
313313
"/perf/triage" if *req.method() == http::Method::GET => {
314314
let ctxt: Arc<SiteCtxt> = server.ctxt.read().as_ref().unwrap().clone();
315315
let input: triage::Request = check!(parse_query_string(req.uri()));
316-
return Ok(to_triage_response(crate::comparison::handle_triage(input, &ctxt).await));
316+
return Ok(to_triage_response(
317+
crate::comparison::handle_triage(input, &ctxt).await,
318+
));
317319
}
318320
"/perf/metrics" => {
319321
return Ok(server.handle_metrics(req).await);
@@ -327,13 +329,9 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
327329
return Ok(request_handlers::handle_self_profile_raw_download(req, &ctxt).await);
328330
}
329331
"/perf/processed-self-profile" => {
330-
return match request_handlers::get_self_profile_raw(&req) {
331-
Ok((parts, v)) => {
332-
let ctxt: Arc<SiteCtxt> = server.ctxt.read().as_ref().unwrap().clone();
333-
Ok(request_handlers::handle_self_profile_processed_download(v, parts, &ctxt).await)
334-
}
335-
Err(e) => Ok(e),
336-
};
332+
let ctxt: Arc<SiteCtxt> = server.ctxt.read().as_ref().unwrap().clone();
333+
let req = check!(parse_query_string(req.uri()));
334+
return Ok(request_handlers::handle_self_profile_processed_download(req, &ctxt).await);
337335
}
338336
_ if req.method() == http::Method::GET => return Ok(not_found()),
339337
_ => {}
@@ -451,7 +449,7 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
451449
},
452450
),
453451
"/perf/triage" => Ok(to_triage_response(
454-
crate::comparison::handle_triage(check!(parse_body(&body)), &ctxt).await
452+
crate::comparison::handle_triage(check!(parse_body(&body)), &ctxt).await,
455453
)),
456454
_ => Ok(http::Response::builder()
457455
.header_typed(ContentType::html())
@@ -605,13 +603,11 @@ fn to_triage_response(result: ServerResult<api::triage::Response>) -> Response {
605603
let response = http::Response::builder().header_typed(ContentType::text());
606604
response.body(hyper::Body::from(result.0)).unwrap()
607605
}
608-
Err(err) => {
609-
http::Response::builder()
610-
.status(StatusCode::INTERNAL_SERVER_ERROR)
611-
.header_typed(ContentType::text_utf8())
612-
.body(hyper::Body::from(err.to_string()))
613-
.unwrap()
614-
}
606+
Err(err) => http::Response::builder()
607+
.status(StatusCode::INTERNAL_SERVER_ERROR)
608+
.header_typed(ContentType::text_utf8())
609+
.body(hyper::Body::from(err.to_string()))
610+
.unwrap(),
615611
}
616612
}
617613

0 commit comments

Comments
 (0)