ListAlerts api

This commit is contained in:
mbecker20
2023-08-20 17:16:20 -04:00
parent 080ecf9fd9
commit ec47fa42b8
8 changed files with 237 additions and 69 deletions
+54
View File
@@ -46,6 +46,10 @@ impl State {
}
let server = server.unwrap();
let server_alerts = alerts.get(&ResourceTarget::Server(v.id.clone()));
// ===================
// SERVER HEALTH
// ===================
let health_alert = server_alerts
.as_ref()
.and_then(|alerts| alerts.get(&AlertDataVariant::ServerUnreachable));
@@ -74,6 +78,56 @@ impl State {
}
_ => {}
}
if v.health.is_none() {
continue;
}
let health = v.health.as_ref().unwrap();
// ===================
// SERVER CPU
// ===================
let cpu_alert = server_alerts
.as_ref()
.and_then(|alerts| alerts.get(&AlertDataVariant::ServerCpu));
match (health.cpu, cpu_alert) {
(SeverityLevel::Warning | SeverityLevel::Critical, None) => {
// open alert
}
(SeverityLevel::Warning | SeverityLevel::Critical, Some(alert)) => {
// modify alert level
}
(SeverityLevel::Ok, Some(alert)) => {
// resolve alert
}
_ => {}
}
// ===================
// SERVER MEM
// ===================
let mem_alert = server_alerts
.as_ref()
.and_then(|alerts| alerts.get(&AlertDataVariant::ServerMem));
match (health.mem, mem_alert) {
(SeverityLevel::Warning | SeverityLevel::Critical, None) => {
// open alert
}
(SeverityLevel::Warning | SeverityLevel::Critical, Some(alert)) => {
// modify alert level
}
(SeverityLevel::Ok, Some(alert)) => {
// resolve alert
}
_ => {}
}
// ===================
// SERVER DISK
// ===================
// alerts possible on multiple disks make this complicated (multiple ServerDisk alerts possible on same server)
}
tokio::join!(
+62
View File
@@ -0,0 +1,62 @@
use anyhow::Context;
use async_trait::async_trait;
use monitor_types::{
entities::server::Server,
requests::read::{ListAlerts, ListAlertsResponse},
};
use mungos::mongodb::{
bson::{doc, Document},
options::FindOptions,
};
use resolver_api::Resolve;
use crate::{auth::RequestUser, helpers::resource::StateResource, state::State};
const NUM_ALERTS_PER_PAGE: u64 = 10;
#[async_trait]
impl Resolve<ListAlerts, RequestUser> for State {
async fn resolve(
&self,
ListAlerts {
page,
include_resolved,
}: ListAlerts,
user: RequestUser,
) -> anyhow::Result<ListAlertsResponse> {
let mut query = Document::new();
if !include_resolved {
query.insert("resolved", true);
}
if !user.is_admin {
let server_ids =
<State as StateResource<Server>>::get_resource_ids_for_non_admin(self, &user.id)
.await?;
query.insert("target.type", "Server");
query.insert("target.id", doc! { "$in": server_ids });
}
let alerts = self
.db
.alerts
.get_some(
query,
FindOptions::builder()
.sort(doc! { "ts": -1 })
.limit(NUM_ALERTS_PER_PAGE as i64)
.skip(page * NUM_ALERTS_PER_PAGE)
.build(),
)
.await
.context("failed to get alerts from db")?;
let next_page = if alerts.len() < NUM_ALERTS_PER_PAGE as usize {
None
} else {
Some((page + 1) as i64)
};
let res = ListAlertsResponse { next_page, alerts };
Ok(res)
}
}
+4
View File
@@ -26,6 +26,7 @@ mod server;
mod tag;
mod update;
mod user;
mod alert;
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Resolver)]
@@ -98,6 +99,9 @@ enum ReadRequest {
GetUpdate(GetUpdate),
ListUpdates(ListUpdates),
// ==== ALERT ====
ListAlerts(ListAlerts),
// ==== SERVER STATS ====
#[to_string_resolver]
GetAllSystemStats(GetAllSystemStats),
+2 -1
View File
@@ -25,6 +25,7 @@ function fix_types() {
const contents = readFileSync(types_path);
const fixed = contents
.toString()
.replaceAll("ResourceTargetVariant", 'ResourceTarget["type"]');
.replaceAll("ResourceTargetVariant", 'ResourceTarget["type"]')
.replaceAll("AlertDataVariant", 'AlertData["type"]');
writeFileSync(types_path, fixed);
}
+3
View File
@@ -74,6 +74,9 @@ export type ReadResponses = {
GetUpdate: Types.Update;
ListUpdates: Types.ListUpdatesResponse;
// ==== ALERT ====
ListAlerts: Types.ListAlertsResponse;
// ==== SERVER STATS ====
GetAllSystemStats: Types.AllSystemStats;
GetBasicSystemStats: Types.BasicSystemStats;
+88 -68
View File
@@ -259,6 +259,78 @@ export type _PartialServerConfig = Partial<ServerConfig>;
export type _PartialCustomTag = Partial<CustomTag>;
export enum SeverityLevel {
Ok = "OK",
Warning = "WARNING",
Critical = "CRITICAL",
}
export type ResourceTarget =
| { type: "System", id: string }
| { type: "Build", id: string }
| { type: "Builder", id: string }
| { type: "Deployment", id: string }
| { type: "Server", id: string }
| { type: "Repo", id: string }
| { type: "Alerter", id: string };
export type AlertData =
| { type: "ServerUnreachable", data: {
id: string;
name: string;
region?: string;
}}
| { type: "ServerCpu", data: {
id: string;
name: string;
region?: string;
percentage: number;
top_procs: SystemProcess[];
}}
| { type: "ServerMem", data: {
id: string;
name: string;
region?: string;
used_gb: number;
total_gb: number;
top_procs: SystemProcess[];
}}
| { type: "ServerDisk", data: {
id: string;
name: string;
region?: string;
path: string;
used_gb: number;
total_gb: number;
}}
| { type: "ServerTemp", data: {
id: string;
name: string;
region?: string;
temp: number;
max: number;
}}
| { type: "ContainerStateChange", data: {
id: string;
name: string;
server: string;
from: DockerContainerState;
to: DockerContainerState;
}}
| { type: "None", data: {
}};
export interface Alert {
_id?: MongoId;
ts: I64;
resolved: boolean;
level: SeverityLevel;
target: ResourceTarget;
variant: AlertData["type"];
data: AlertData;
resolved_ts?: I64;
}
export interface CustomAlerterConfig {
url: string;
}
@@ -525,18 +597,12 @@ export interface AllSystemStats {
refresh_list_ts: I64;
}
export enum StatsState {
Ok = "OK",
Warning = "WARNING",
Critical = "CRITICAL",
}
export interface ServerHealth {
cpu: StatsState;
mem: StatsState;
disk: StatsState;
disks: Record<string, StatsState>;
temps: Record<string, StatsState>;
cpu: SeverityLevel;
mem: SeverityLevel;
disk: SeverityLevel;
disks: Record<string, SeverityLevel>;
temps: Record<string, SeverityLevel>;
}
export enum TagColor {
@@ -598,15 +664,6 @@ export enum Operation {
AutoPull = "AutoPull",
}
export type ResourceTarget =
| { type: "System", id: string }
| { type: "Build", id: string }
| { type: "Builder", id: string }
| { type: "Deployment", id: string }
| { type: "Server", id: string }
| { type: "Repo", id: string }
| { type: "Alerter", id: string };
export interface Log {
stage: string;
command: string;
@@ -769,6 +826,16 @@ export interface PruneDockerContainers {
server_id: string;
}
export interface ListAlerts {
page?: U64;
include_resolved?: boolean;
}
export interface ListAlertsResponse {
alerts: Alert[];
next_page?: I64;
}
export interface GetAlerter {
id: string;
}
@@ -1391,6 +1458,7 @@ export type ReadRequest =
| { type: "ListTags", params: ListTags }
| { type: "GetUpdate", params: GetUpdate }
| { type: "ListUpdates", params: ListUpdates }
| { type: "ListAlerts", params: ListAlerts }
| { type: "GetAllSystemStats", params: GetAllSystemStats }
| { type: "GetBasicSystemStats", params: GetBasicSystemStats }
| { type: "GetCpuUsage", params: GetCpuUsage }
@@ -1439,54 +1507,6 @@ export type WriteRequest =
| { type: "DeleteTag", params: DeleteTag }
| { type: "UpdateTag", params: UpdateTag };
export type Alert =
| { type: "ServerUnreachable", data: {
id: string;
name: string;
region?: string;
}}
| { type: "ServerCpu", data: {
id: string;
name: string;
region?: string;
state: StatsState;
percentage: number;
top_procs: SystemProcess[];
}}
| { type: "ServerMem", data: {
id: string;
name: string;
region?: string;
state: StatsState;
used_gb: number;
total_gb: number;
top_procs: SystemProcess[];
}}
| { type: "ServerDisk", data: {
id: string;
name: string;
region?: string;
state: StatsState;
path: string;
used_gb: number;
total_gb: number;
}}
| { type: "ServerTemp", data: {
id: string;
name: string;
region?: string;
state: StatsState;
temp: number;
max: number;
}}
| { type: "ContainerStateChange", data: {
id: string;
name: string;
server: string;
from: DockerContainerState;
to: DockerContainerState;
}};
export type Tag =
| { type: "ResourceType", params: {
resource: ResourceTarget["type"];
+22
View File
@@ -0,0 +1,22 @@
use resolver_api::derive::Request;
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
use crate::{entities::alert::Alert, I64, U64};
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
#[response(ListAlertsResponse)]
pub struct ListAlerts {
#[serde(default)]
pub page: U64,
#[serde(default)]
pub include_resolved: bool,
}
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ListAlertsResponse {
pub alerts: Vec<Alert>,
pub next_page: Option<I64>,
}
+2
View File
@@ -2,6 +2,7 @@ use resolver_api::derive::Request;
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
mod alert;
mod alerter;
mod build;
mod builder;
@@ -12,6 +13,7 @@ mod server;
mod tag;
mod update;
pub use alert::*;
pub use alerter::*;
pub use build::*;
pub use builder::*;