Skip to content

Commit 041ef30

Browse files
fix: home search api
request - `http://localhost:8000/api/prism/v1/home/search?key=frontend` response - ``` { "resources": [ { "id": "e890c2f70362528b57d528b65a39de62bbd3c65f90f6923dce25e27a8a66e8a4", "name": "select flags not 0", "resource_type": "Filter" }, { "id": "e71d1affa4ad72136e03092a717a4b0e0c3fd6d643a09572ad65e1748a5c2df8", "name": "body not null", "resource_type": "Filter" }, { "id": "6fe16f99b05566d7d4a598a7f0fa2604379d75164cdda5657c7fdbf61e54a555", "name": "select *", "resource_type": "Filter" }, { "id": "fcda9d6a2b98c3368cbf1d903bb408e59f084df2dcb7c7d5d7b044e800ec1437", "name": "frontend limit", "resource_type": "Filter" } ] } ```
1 parent 17c417e commit 041ef30

File tree

2 files changed

+132
-45
lines changed

2 files changed

+132
-45
lines changed

src/handlers/http/prism_home.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ use crate::{
2323
utils::actix::extract_session_key_from_req,
2424
};
2525

26+
const HOME_SEARCH_QUERY_PARAM: &str = "key";
27+
2628
/// Fetches the data to populate Prism's home
2729
///
2830
///
@@ -41,8 +43,22 @@ pub async fn home_api(req: HttpRequest) -> Result<impl Responder, PrismHomeError
4143
pub async fn home_search(req: HttpRequest) -> Result<impl Responder, PrismHomeError> {
4244
let key = extract_session_key_from_req(&req)
4345
.map_err(|err| PrismHomeError::Anyhow(anyhow::Error::msg(err.to_string())))?;
46+
let query_string = req.query_string();
47+
if query_string.is_empty() {
48+
return Ok(web::Json(serde_json::json!({})));
49+
}
50+
// Validate query string format
51+
let query_parts: Vec<&str> = query_string.split('=').collect();
52+
if query_parts.len() != 2 || query_parts[0] != HOME_SEARCH_QUERY_PARAM {
53+
return Err(PrismHomeError::InvalidQueryParameter(
54+
HOME_SEARCH_QUERY_PARAM.to_string(),
55+
));
56+
}
4457

45-
let res = generate_home_search_response(&key).await?;
58+
let query_value = query_parts[1].to_lowercase();
59+
let res = generate_home_search_response(&key, &query_value).await?;
60+
let json_res = serde_json::to_value(res)
61+
.map_err(|err| PrismHomeError::Anyhow(anyhow::Error::msg(err.to_string())))?;
4662

47-
Ok(web::Json(res))
63+
Ok(web::Json(json_res))
4864
}

src/prism/home/mod.rs

Lines changed: 114 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,6 @@ struct DatedStats {
5050
storage_size: u64,
5151
}
5252

53-
#[derive(Debug, Serialize)]
54-
struct TitleAndId {
55-
title: String,
56-
id: String,
57-
}
58-
5953
#[derive(Debug, Serialize)]
6054
enum DataSetType {
6155
Logs,
@@ -76,12 +70,25 @@ pub struct HomeResponse {
7670
datasets: Vec<DataSet>,
7771
}
7872

73+
#[derive(Debug, Serialize)]
74+
pub enum ResourceType {
75+
Alert,
76+
Correlation,
77+
Dashboard,
78+
Filter,
79+
DataSet,
80+
}
81+
82+
#[derive(Debug, Serialize)]
83+
pub struct Resource {
84+
id: String,
85+
name: String,
86+
resource_type: ResourceType,
87+
}
88+
7989
#[derive(Debug, Serialize)]
8090
pub struct HomeSearchResponse {
81-
alerts: Vec<TitleAndId>,
82-
correlations: Vec<TitleAndId>,
83-
dashboards: Vec<TitleAndId>,
84-
filters: Vec<TitleAndId>,
91+
resources: Vec<Resource>,
8592
}
8693

8794
pub async fn generate_home_response(key: &SessionKey) -> Result<HomeResponse, PrismHomeError> {
@@ -255,25 +262,37 @@ async fn get_stream_stats_for_date(
255262

256263
pub async fn generate_home_search_response(
257264
key: &SessionKey,
265+
query_value: &str,
258266
) -> Result<HomeSearchResponse, PrismHomeError> {
259-
let (alert_titles, correlation_titles, dashboard_titles, filter_titles) = tokio::join!(
260-
get_alert_titles(key),
261-
get_correlation_titles(key),
262-
get_dashboard_titles(key),
263-
get_filter_titles(key)
267+
let mut resources = Vec::new();
268+
let (alert_titles, correlation_titles, dashboard_titles, filter_titles, stream_titles) = tokio::join!(
269+
get_alert_titles(key, query_value),
270+
get_correlation_titles(key, query_value),
271+
get_dashboard_titles(key, query_value),
272+
get_filter_titles(key, query_value),
273+
get_stream_titles(key)
264274
);
265275

266276
let alerts = alert_titles?;
277+
resources.extend(alerts);
267278
let correlations = correlation_titles?;
279+
resources.extend(correlations);
268280
let dashboards = dashboard_titles?;
281+
resources.extend(dashboards);
269282
let filters = filter_titles?;
270-
271-
Ok(HomeSearchResponse {
272-
alerts,
273-
correlations,
274-
dashboards,
275-
filters,
276-
})
283+
resources.extend(filters);
284+
let stream_titles = stream_titles?;
285+
286+
for title in stream_titles {
287+
if title.to_lowercase().contains(query_value) {
288+
resources.push(Resource {
289+
id: title.clone(),
290+
name: title,
291+
resource_type: ResourceType::DataSet,
292+
});
293+
}
294+
}
295+
Ok(HomeSearchResponse { resources })
277296
}
278297

279298
// Helper functions to split the work
@@ -295,59 +314,108 @@ async fn get_stream_titles(key: &SessionKey) -> Result<Vec<String>, PrismHomeErr
295314
Ok(stream_titles)
296315
}
297316

298-
async fn get_alert_titles(key: &SessionKey) -> Result<Vec<TitleAndId>, PrismHomeError> {
299-
let alert_titles = ALERTS
317+
async fn get_alert_titles(
318+
key: &SessionKey,
319+
query_value: &str,
320+
) -> Result<Vec<Resource>, PrismHomeError> {
321+
let alerts = ALERTS
300322
.list_alerts_for_user(key.clone())
301323
.await?
302324
.iter()
303-
.map(|alert| TitleAndId {
304-
title: alert.title.clone(),
305-
id: alert.id.to_string(),
325+
.filter_map(|alert| {
326+
if alert.title.to_lowercase().contains(query_value)
327+
|| alert.id.to_string().to_lowercase().contains(query_value)
328+
{
329+
Some(Resource {
330+
id: alert.id.to_string(),
331+
name: alert.title.clone(),
332+
resource_type: ResourceType::Alert,
333+
})
334+
} else {
335+
None
336+
}
306337
})
307338
.collect_vec();
308339

309-
Ok(alert_titles)
340+
Ok(alerts)
310341
}
311342

312-
async fn get_correlation_titles(key: &SessionKey) -> Result<Vec<TitleAndId>, PrismHomeError> {
313-
let correlation_titles = CORRELATIONS
343+
async fn get_correlation_titles(
344+
key: &SessionKey,
345+
query_value: &str,
346+
) -> Result<Vec<Resource>, PrismHomeError> {
347+
let correlations = CORRELATIONS
314348
.list_correlations(key)
315349
.await?
316350
.iter()
317-
.map(|corr| TitleAndId {
318-
title: corr.title.clone(),
319-
id: corr.id.clone(),
351+
.filter_map(|correlation| {
352+
if correlation.title.to_lowercase().contains(query_value)
353+
|| correlation.id.to_lowercase().contains(query_value)
354+
{
355+
Some(Resource {
356+
id: correlation.id.to_string(),
357+
name: correlation.title.clone(),
358+
resource_type: ResourceType::Correlation,
359+
})
360+
} else {
361+
None
362+
}
320363
})
321364
.collect_vec();
322365

323-
Ok(correlation_titles)
366+
Ok(correlations)
324367
}
325368

326-
async fn get_dashboard_titles(key: &SessionKey) -> Result<Vec<TitleAndId>, PrismHomeError> {
369+
async fn get_dashboard_titles(
370+
key: &SessionKey,
371+
query_value: &str,
372+
) -> Result<Vec<Resource>, PrismHomeError> {
327373
let dashboard_titles = DASHBOARDS
328374
.list_dashboards(key)
329375
.await
330376
.iter()
331-
.map(|dashboard| TitleAndId {
332-
title: dashboard.name.clone(),
333-
id: dashboard.dashboard_id.as_ref().unwrap().clone(),
377+
.filter_map(|dashboard| {
378+
let dashboard_id = dashboard.dashboard_id.as_ref().unwrap().clone();
379+
if dashboard.name.to_lowercase().contains(query_value)
380+
|| dashboard_id.to_lowercase().contains(query_value)
381+
{
382+
Some(Resource {
383+
id: dashboard_id,
384+
name: dashboard.name.clone(),
385+
resource_type: ResourceType::Dashboard,
386+
})
387+
} else {
388+
None
389+
}
334390
})
335391
.collect_vec();
336392

337393
Ok(dashboard_titles)
338394
}
339395

340-
async fn get_filter_titles(key: &SessionKey) -> Result<Vec<TitleAndId>, PrismHomeError> {
396+
async fn get_filter_titles(
397+
key: &SessionKey,
398+
query_value: &str,
399+
) -> Result<Vec<Resource>, PrismHomeError> {
341400
let filter_titles = FILTERS
342401
.list_filters(key)
343402
.await
344403
.iter()
345-
.map(|filter| TitleAndId {
346-
title: filter.filter_name.clone(),
347-
id: filter.filter_id.as_ref().unwrap().clone(),
404+
.filter_map(|filter| {
405+
let filter_id = filter.filter_id.as_ref().unwrap().clone();
406+
if filter.filter_name.to_lowercase().contains(query_value)
407+
|| filter_id.to_lowercase().contains(query_value)
408+
{
409+
Some(Resource {
410+
id: filter_id,
411+
name: filter.filter_name.clone(),
412+
resource_type: ResourceType::Filter,
413+
})
414+
} else {
415+
None
416+
}
348417
})
349418
.collect_vec();
350-
351419
Ok(filter_titles)
352420
}
353421

@@ -363,6 +431,8 @@ pub enum PrismHomeError {
363431
StreamError(#[from] StreamError),
364432
#[error("ObjectStorageError: {0}")]
365433
ObjectStorageError(#[from] ObjectStorageError),
434+
#[error("Invalid query parameter: {0}")]
435+
InvalidQueryParameter(String),
366436
}
367437

368438
impl actix_web::ResponseError for PrismHomeError {
@@ -373,6 +443,7 @@ impl actix_web::ResponseError for PrismHomeError {
373443
PrismHomeError::CorrelationError(e) => e.status_code(),
374444
PrismHomeError::StreamError(e) => e.status_code(),
375445
PrismHomeError::ObjectStorageError(_) => StatusCode::INTERNAL_SERVER_ERROR,
446+
PrismHomeError::InvalidQueryParameter(_) => StatusCode::BAD_REQUEST,
376447
}
377448
}
378449

0 commit comments

Comments
 (0)