Status page: what needs attention first, glyphs for what repeats
The page opened with every session in bold green, the normal state, and the brightest numbers on it were the rejection counts, which RPKI doing its job produces by the thousand. The two sessions that were actually down were in the same red, thirty rows down. Now: - A status line at the top says what needs attention, by name and with the reason: sessions down, peers restarting, the kernel behind or refusing routes, RPKI data missing or about to expire. When nothing does, it says so. A second line gives the normal state in grey. - Colour means one thing each. Red: failed, needs a hand. Amber: degraded, worth watching. Green, set small: a system doing its job. Grey: inactive and expected. Normal is black; "Established" is no longer green, and a rejection count no longer red. - Peers that need attention come first, then the others grouped by what they are to us, with a "problems only" switch. Numbers are right aligned with thousands separators; the established time and uptime are one cell; the session's properties are glyphs (v4, v6, GR, ENH, AP, 2B) with the meaning as a tooltip, as are the roles. - Received routes: the best route leads, marked ★; attributes without a column are glyphs (OTC, AA, AGG, AS4, OID, CL); validity is ✓ ✗ –. - Rejected routes: those alike (same prefix, reason and path) are one row with a count and the last time; each peer's reasons are a bar. - Communities with a configured name (community_names, new) are badges with that name, the number as the tooltip: "comrack", "SwissIX", "interconnection 2011" rather than 210036:100:2 and so on. A name for a pattern shows the open part after it. The daemon does nothing with the names but pass them to the page. - One lookup box at the top, which takes a peer's name too; a peer's name anywhere on the page leads to its routes; table headers and the status line stay in view while scrolling. - The host name comes from gethostname(2), not from running `hostname`, which a static binary on a bare machine could not find: comrack said "unknown host". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
23e8b4aadb
commit
1ce7eef27e
12 files changed
+515
-160
No files matched your search
+23
-6
@@ -23,6 +23,7 @@ use bgp_rpki::Rpki;
|
||||
use bgp_server::rejections::RejectionLog;
|
||||
use bgp_server::restart::Restarts;
|
||||
use bgp_server::session::SessionRegistry;
|
||||
use serde::Serialize;
|
||||
use tokio::net::TcpListener;
|
||||
use tracing::info;
|
||||
|
||||
@@ -48,6 +49,18 @@ pub struct RouterInfo {
|
||||
/// Whether large communities of our AS ask for things here
|
||||
/// (`control_communities`), so that the status page can say what.
|
||||
pub control_communities: bool,
|
||||
/// Names for communities, as configured (`community_names`), for the
|
||||
/// status page to show in place of the numbers.
|
||||
pub community_names: Vec<CommunityName>,
|
||||
}
|
||||
|
||||
/// A name for a community, or for a kind of them.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct CommunityName {
|
||||
/// The community, or a pattern of them with `*` for a part left open:
|
||||
/// `64601:100:2`, `64601:102:*`.
|
||||
pub community: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl RouterInfo {
|
||||
@@ -61,9 +74,16 @@ impl RouterInfo {
|
||||
hostname: hostname(),
|
||||
config: None,
|
||||
control_communities: false,
|
||||
community_names: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Records the names configured for communities.
|
||||
pub fn with_community_names(mut self, names: Vec<CommunityName>) -> Self {
|
||||
self.community_names = names;
|
||||
self
|
||||
}
|
||||
|
||||
/// Records whether control communities are acted on.
|
||||
pub fn with_control_communities(mut self, on: bool) -> Self {
|
||||
self.control_communities = on;
|
||||
@@ -80,13 +100,10 @@ impl RouterInfo {
|
||||
/// Best-effort host name without pulling in a dependency: ask the `hostname`
|
||||
/// utility, which exists on every platform we run on.
|
||||
fn hostname() -> String {
|
||||
std::process::Command::new("hostname")
|
||||
.output()
|
||||
nix::unistd::gethostname()
|
||||
.ok()
|
||||
.filter(|o| o.status.success())
|
||||
.and_then(|o| String::from_utf8(o.stdout).ok())
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty())
|
||||
.and_then(|name| name.into_string().ok())
|
||||
.filter(|name| !name.is_empty())
|
||||
.unwrap_or_else(|| "unknown host".into())
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user