Skip to content

Commit fff948f

Browse files
update home response, update dashboards list api
1 parent c67be9a commit fff948f

File tree

4 files changed

+126
-54
lines changed

4 files changed

+126
-54
lines changed

src/alerts/mod.rs

Lines changed: 84 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,53 +1031,101 @@ impl Alerts {
10311031
}
10321032

10331033
#[derive(Debug, Serialize)]
1034-
pub struct AlertsInfo {
1034+
pub struct AlertsSummary {
10351035
total: u64,
1036-
silenced: u64,
1037-
resolved: u64,
1038-
triggered: u64,
1039-
low: u64,
1040-
medium: u64,
1041-
high: u64,
1042-
critical: u64,
1036+
triggered: AlertsInfoByState,
1037+
silenced: AlertsInfoByState,
1038+
resolved: AlertsInfoByState,
1039+
}
1040+
1041+
#[derive(Debug, Serialize)]
1042+
pub struct AlertsInfoByState {
1043+
total: u64,
1044+
alert_info: Vec<AlertsInfo>,
1045+
}
1046+
1047+
#[derive(Debug, Serialize)]
1048+
pub struct AlertsInfo {
1049+
title: String,
1050+
id: Ulid,
1051+
severity: Severity,
10431052
}
10441053

10451054
// TODO: add RBAC
1046-
pub async fn get_alerts_info() -> Result<AlertsInfo, AlertError> {
1055+
pub async fn get_alerts_summary() -> Result<AlertsSummary, AlertError> {
10471056
let alerts = ALERTS.alerts.read().await;
1048-
let mut total = 0;
1049-
let mut silenced = 0;
1050-
let mut resolved = 0;
1057+
let total = alerts.len() as u64;
10511058
let mut triggered = 0;
1052-
let mut low = 0;
1053-
let mut medium = 0;
1054-
let mut high = 0;
1055-
let mut critical = 0;
1059+
let mut resolved = 0;
1060+
let mut silenced = 0;
1061+
let mut triggered_alerts: Vec<AlertsInfo> = Vec::new();
1062+
let mut silenced_alerts: Vec<AlertsInfo> = Vec::new();
1063+
let mut resolved_alerts: Vec<AlertsInfo> = Vec::new();
10561064

1065+
// find total alerts for each state
1066+
// get title, id and state of each alert for that state
10571067
for (_, alert) in alerts.iter() {
1058-
total += 1;
10591068
match alert.state {
1060-
AlertState::Silenced => silenced += 1,
1061-
AlertState::Resolved => resolved += 1,
1062-
AlertState::Triggered => triggered += 1,
1063-
}
1064-
1065-
match alert.severity {
1066-
Severity::Low => low += 1,
1067-
Severity::Medium => medium += 1,
1068-
Severity::High => high += 1,
1069-
Severity::Critical => critical += 1,
1069+
AlertState::Triggered => {
1070+
triggered += 1;
1071+
triggered_alerts.push(AlertsInfo {
1072+
title: alert.title.clone(),
1073+
id: alert.id,
1074+
severity: alert.severity.clone(),
1075+
});
1076+
}
1077+
AlertState::Silenced => {
1078+
silenced += 1;
1079+
silenced_alerts.push(AlertsInfo {
1080+
title: alert.title.clone(),
1081+
id: alert.id,
1082+
severity: alert.severity.clone(),
1083+
});
1084+
}
1085+
AlertState::Resolved => {
1086+
resolved += 1;
1087+
resolved_alerts.push(AlertsInfo {
1088+
title: alert.title.clone(),
1089+
id: alert.id,
1090+
severity: alert.severity.clone(),
1091+
});
1092+
}
10701093
}
10711094
}
10721095

1073-
Ok(AlertsInfo {
1096+
// Sort and limit to top 5 for each state by severity priority
1097+
triggered_alerts.sort_by_key(|alert| get_severity_priority(&alert.severity));
1098+
triggered_alerts.truncate(5);
1099+
1100+
silenced_alerts.sort_by_key(|alert| get_severity_priority(&alert.severity));
1101+
silenced_alerts.truncate(5);
1102+
1103+
resolved_alerts.sort_by_key(|alert| get_severity_priority(&alert.severity));
1104+
resolved_alerts.truncate(5);
1105+
1106+
let alert_summary = AlertsSummary {
10741107
total,
1075-
silenced,
1076-
resolved,
1077-
triggered,
1078-
low,
1079-
medium,
1080-
high,
1081-
critical,
1082-
})
1108+
triggered: AlertsInfoByState {
1109+
total: triggered,
1110+
alert_info: triggered_alerts,
1111+
},
1112+
silenced: AlertsInfoByState {
1113+
total: silenced,
1114+
alert_info: silenced_alerts,
1115+
},
1116+
resolved: AlertsInfoByState {
1117+
total: resolved,
1118+
alert_info: resolved_alerts,
1119+
},
1120+
};
1121+
Ok(alert_summary)
1122+
}
1123+
1124+
fn get_severity_priority(severity: &Severity) -> u8 {
1125+
match severity {
1126+
Severity::Critical => 0,
1127+
Severity::High => 1,
1128+
Severity::Medium => 2,
1129+
Severity::Low => 3,
1130+
}
10831131
}

src/handlers/http/users/dashboards.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,20 @@ use actix_web::{
3232
use http::StatusCode;
3333
use serde_json::Error as SerdeError;
3434

35-
pub async fn list_dashboards() -> Result<impl Responder, DashboardError> {
36-
let dashboards = DASHBOARDS.list_dashboards().await;
35+
pub async fn list_dashboards(req: HttpRequest) -> Result<impl Responder, DashboardError> {
36+
let query_map = web::Query::<HashMap<String, String>>::from_query(req.query_string())
37+
.map_err(|_| DashboardError::InvalidQueryParameter)?;
38+
let mut dashboard_limit = 0;
39+
if !query_map.is_empty() {
40+
if let Some(limit) = query_map.get("limit") {
41+
if let Ok(parsed_limit) = limit.parse::<usize>() {
42+
dashboard_limit = parsed_limit;
43+
} else {
44+
return Err(DashboardError::Metadata("Invalid limit value"));
45+
}
46+
}
47+
}
48+
let dashboards = DASHBOARDS.list_dashboards(dashboard_limit).await;
3749
let dashboard_summaries = dashboards
3850
.iter()
3951
.map(|dashboard| dashboard.to_summary())

src/prism/home/mod.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use serde::Serialize;
2727
use tracing::error;
2828

2929
use crate::{
30-
alerts::{get_alerts_info, AlertError, AlertsInfo, ALERTS},
30+
alerts::{get_alerts_summary, AlertError, AlertsSummary, ALERTS},
3131
correlation::{CorrelationError, CORRELATIONS},
3232
event::format::LogSource,
3333
handlers::http::{cluster::fetch_daily_stats, logstream::error::StreamError},
@@ -44,8 +44,8 @@ type StreamMetadataResponse = Result<(String, Vec<ObjectStoreFormat>, DataSetTyp
4444
pub struct DatedStats {
4545
date: String,
4646
events: u64,
47-
ingestion_size: u64,
48-
storage_size: u64,
47+
ingestion: u64,
48+
storage: u64,
4949
}
5050

5151
#[derive(Debug, Serialize)]
@@ -63,10 +63,10 @@ pub struct DataSet {
6363

6464
#[derive(Debug, Serialize)]
6565
pub struct HomeResponse {
66-
pub alerts_info: AlertsInfo,
66+
pub alerts_summary: AlertsSummary,
6767
pub stats_details: Vec<DatedStats>,
6868
pub datasets: Vec<DataSet>,
69-
pub top_five_ingestion: Vec<(String, Stats)>,
69+
pub top_five_ingestion: HashMap<String, Stats>,
7070
}
7171

7272
#[derive(Debug, Serialize)]
@@ -95,11 +95,11 @@ pub async fn generate_home_response(
9595
include_internal: bool,
9696
) -> Result<HomeResponse, PrismHomeError> {
9797
// Execute these operations concurrently
98-
let (stream_titles_result, alerts_info_result) =
99-
tokio::join!(get_stream_titles(key), get_alerts_info());
98+
let (stream_titles_result, alerts_summary_result) =
99+
tokio::join!(get_stream_titles(key), get_alerts_summary());
100100

101101
let stream_titles = stream_titles_result?;
102-
let alerts_info = alerts_info_result?;
102+
let alerts_summary = alerts_summary_result?;
103103

104104
// Generate dates for date-wise stats
105105
let mut dates = (0..7)
@@ -172,14 +172,14 @@ pub async fn generate_home_response(
172172
Ok(HomeResponse {
173173
stats_details: stream_details,
174174
datasets,
175-
alerts_info,
175+
alerts_summary,
176176
top_five_ingestion,
177177
})
178178
}
179179

180180
fn get_top_5_streams_by_ingestion(
181181
stream_wise_stream_json: &HashMap<String, Vec<ObjectStoreFormat>>,
182-
) -> Vec<(String, Stats)> {
182+
) -> HashMap<String, Stats> {
183183
let mut result: Vec<_> = stream_wise_stream_json
184184
.iter()
185185
.map(|(stream_name, formats)| {
@@ -203,7 +203,7 @@ fn get_top_5_streams_by_ingestion(
203203

204204
result.sort_by_key(|(_, stats)| std::cmp::Reverse(stats.ingestion));
205205
result.truncate(5);
206-
result
206+
result.into_iter().collect()
207207
}
208208

209209
async fn get_stream_metadata(
@@ -275,8 +275,8 @@ async fn stats_for_date(
275275
match result {
276276
Ok((events, ingestion, storage)) => {
277277
details.events += events;
278-
details.ingestion_size += ingestion;
279-
details.storage_size += storage;
278+
details.ingestion += ingestion;
279+
details.storage += storage;
280280
}
281281
Err(e) => {
282282
error!("Failed to get stats for stream: {:?}", e);
@@ -405,7 +405,7 @@ async fn get_correlation_titles(
405405

406406
async fn get_dashboard_titles(query_value: &str) -> Result<Vec<Resource>, PrismHomeError> {
407407
let dashboard_titles = DASHBOARDS
408-
.list_dashboards()
408+
.list_dashboards(0)
409409
.await
410410
.iter()
411411
.filter_map(|dashboard| {

src/users/dashboards.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,20 @@ impl Dashboards {
344344

345345
/// List all dashboards
346346
/// fetch all dashboards from memory
347-
pub async fn list_dashboards(&self) -> Vec<Dashboard> {
348-
self.0.read().await.clone()
347+
pub async fn list_dashboards(&self, limit: usize) -> Vec<Dashboard> {
348+
// limit the number of dashboards returned in order of modified date
349+
// if limit is 0, return all dashboards
350+
let dashboards = self.0.read().await;
351+
let mut sorted_dashboards = dashboards
352+
.iter()
353+
.filter(|d| d.dashboard_id.is_some())
354+
.cloned()
355+
.collect::<Vec<Dashboard>>();
356+
sorted_dashboards.sort_by_key(|d| std::cmp::Reverse(d.modified));
357+
if limit > 0 {
358+
sorted_dashboards.truncate(limit);
359+
}
360+
sorted_dashboards
349361
}
350362

351363
/// List tags from all dashboards

0 commit comments

Comments
 (0)