188 lines
4.8 KiB
Rust
188 lines
4.8 KiB
Rust
const LIVE_LOG_COLUMNS: &[&str] = &[
|
|
"time",
|
|
"request",
|
|
"host",
|
|
"source_ip",
|
|
"vhost",
|
|
"backend",
|
|
"status",
|
|
"duration",
|
|
"cache",
|
|
"outcome",
|
|
"transport",
|
|
"websocket",
|
|
"upstream_error",
|
|
];
|
|
const FILE_LOG_COLUMN_MAX: usize = 64;
|
|
const BACKEND_TABLE_COLUMNS: &[&str] = &[
|
|
"vhost",
|
|
"backend",
|
|
"status",
|
|
"active",
|
|
"requests",
|
|
"errors",
|
|
"latency",
|
|
"traffic",
|
|
"generation",
|
|
"generationRequests",
|
|
"generationAge",
|
|
"rotations",
|
|
"lastFailure",
|
|
"lastRecovery",
|
|
];
|
|
const VHOST_LIST_SORT_COLUMNS: &[&str] = &[
|
|
"id",
|
|
"hostname",
|
|
"status",
|
|
"listeners",
|
|
"certificate",
|
|
"backends",
|
|
];
|
|
const DOCKER_VHOST_SORT_COLUMNS: &[&str] = &[
|
|
"service",
|
|
"hostname",
|
|
"status",
|
|
"backend",
|
|
"scheme",
|
|
"published",
|
|
];
|
|
const REDIRECT_LIST_SORT_COLUMNS: &[&str] = &[
|
|
"id",
|
|
"name",
|
|
"hostname",
|
|
"status",
|
|
"target",
|
|
"rules",
|
|
"listeners",
|
|
"certificate",
|
|
];
|
|
const NOTFOUND_LIST_SORT_COLUMNS: &[&str] = &[
|
|
"id",
|
|
"name",
|
|
"hostname",
|
|
"status",
|
|
"mode",
|
|
"listeners",
|
|
"certificate",
|
|
];
|
|
const STREAM_LIST_SORT_COLUMNS: &[&str] = &[
|
|
"name",
|
|
"id",
|
|
"protocol",
|
|
"listen",
|
|
"upstream",
|
|
"status",
|
|
"maxConnections",
|
|
"idleTimeout",
|
|
];
|
|
#[derive(serde::Deserialize)]
|
|
struct DashboardWidgetDefinition {
|
|
id: String,
|
|
default_hidden: bool,
|
|
display_type: String,
|
|
}
|
|
static DASHBOARD_WIDGETS: std::sync::LazyLock<Vec<DashboardWidgetDefinition>> =
|
|
std::sync::LazyLock::new(|| {
|
|
serde_json::from_str(include_str!("web/dashboard-widgets.json"))
|
|
.expect("invalid bundled Overview Cards registry")
|
|
});
|
|
|
|
#[derive(serde::Deserialize)]
|
|
#[serde(deny_unknown_fields)]
|
|
struct DashboardDefaultPreset {
|
|
dashboard_widgets: Vec<String>,
|
|
dashboard_hidden_widgets: Vec<String>,
|
|
dashboard_density: String,
|
|
overview_samples: u16,
|
|
}
|
|
static DASHBOARD_DEFAULT_PRESET: std::sync::LazyLock<DashboardDefaultPreset> =
|
|
std::sync::LazyLock::new(|| {
|
|
let preset: DashboardDefaultPreset =
|
|
serde_json::from_str(include_str!("web/dashboard-defaults.json"))
|
|
.expect("invalid factory Overview layout preset");
|
|
let registry = DASHBOARD_WIDGETS
|
|
.iter()
|
|
.map(|w| w.id.as_str())
|
|
.collect::<std::collections::HashSet<_>>();
|
|
let order = preset
|
|
.dashboard_widgets
|
|
.iter()
|
|
.map(String::as_str)
|
|
.collect::<std::collections::HashSet<_>>();
|
|
let hidden = preset
|
|
.dashboard_hidden_widgets
|
|
.iter()
|
|
.map(String::as_str)
|
|
.collect::<std::collections::HashSet<_>>();
|
|
assert_eq!(
|
|
order.len(),
|
|
preset.dashboard_widgets.len(),
|
|
"duplicate factory widget ID"
|
|
);
|
|
assert_eq!(
|
|
hidden.len(),
|
|
preset.dashboard_hidden_widgets.len(),
|
|
"duplicate hidden factory widget ID"
|
|
);
|
|
assert!(
|
|
order.is_subset(®istry) && hidden.is_subset(&order),
|
|
"unknown widget in factory layout"
|
|
);
|
|
assert!(
|
|
matches!(
|
|
preset.dashboard_density.as_str(),
|
|
"normal" | "compact" | "ultra"
|
|
),
|
|
"invalid factory density"
|
|
);
|
|
assert!(
|
|
matches!(preset.overview_samples, 60 | 120 | 300 | 600),
|
|
"invalid factory sample count"
|
|
);
|
|
preset
|
|
});
|
|
|
|
fn valid_dashboard_span(display_type: &str, span: u8) -> bool {
|
|
match display_type {
|
|
"table" => matches!(span, 6 | 12),
|
|
"panel" => matches!(span, 4 | 6 | 12),
|
|
"chart" => matches!(span, 3 | 4 | 6 | 12),
|
|
_ => matches!(span, 2 | 3 | 4 | 6 | 12),
|
|
}
|
|
}
|
|
|
|
fn valid_dashboard_sizes(sizes: &Option<std::collections::BTreeMap<String, u8>>) -> bool {
|
|
sizes.as_ref().is_none_or(|sizes| {
|
|
sizes.len() <= DASHBOARD_WIDGETS.len()
|
|
&& sizes.iter().all(|(id, span)| {
|
|
DASHBOARD_WIDGETS.iter().any(|widget| {
|
|
widget.id == *id && valid_dashboard_span(&widget.display_type, *span)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
fn default_hidden_dashboard_widgets() -> Vec<String> {
|
|
let mut hidden = DASHBOARD_DEFAULT_PRESET.dashboard_hidden_widgets.clone();
|
|
for widget in DASHBOARD_WIDGETS.iter() {
|
|
if !DASHBOARD_DEFAULT_PRESET
|
|
.dashboard_widgets
|
|
.contains(&widget.id)
|
|
&& widget.default_hidden
|
|
{
|
|
hidden.push(widget.id.clone());
|
|
}
|
|
}
|
|
hidden
|
|
}
|
|
|
|
fn default_admin_dashboard_widgets() -> Vec<String> {
|
|
let mut order = DASHBOARD_DEFAULT_PRESET.dashboard_widgets.clone();
|
|
for widget in DASHBOARD_WIDGETS.iter() {
|
|
if !order.contains(&widget.id) {
|
|
order.push(widget.id.clone());
|
|
}
|
|
}
|
|
order
|
|
}
|