pages per period

This commit is contained in:
2026-08-11 19:11:40 +02:00
parent 7fe7bb02fb
commit a82de89fca
2 changed files with 35 additions and 16 deletions
+3 -2
View File
@@ -39,8 +39,9 @@ the new values. If the RRD has already been created, do not change the order of
mountpoints unless you intentionally want the historical graph labels to refer mountpoints unless you intentionally want the historical graph labels to refer
to different disks. to different disks.
The generated PNG files and a responsive, auto-refreshing `index.html` are The generated PNG files and four responsive, auto-refreshing dashboard pages
placed in `/var/www/html/system-monitor` by default. are placed in `/var/www/html/system-monitor` by default. `index.html` shows
the last 3 hours and links to the 1-day, 2-week, and 1-year pages.
With a web server installed, such as nginx or Apache, they can be served With a web server installed, such as nginx or Apache, they can be served
directly; otherwise they can simply be opened or copied as PNG files. directly; otherwise they can simply be opened or copied as PNG files.
+29 -11
View File
@@ -80,22 +80,40 @@ def main() -> None:
graph(output_dir / f"{filename}-{period_name}.png", rrd, start, graph(output_dir / f"{filename}-{period_name}.png", rrd, start,
f"{title}{period_name}", unit, series, logarithmic, f"{title}{period_name}", unit, series, logarithmic,
stacked, disk_memory, network_mixed) stacked, disk_memory, network_mixed)
page_files = {
"3hours": "index.html",
"1day": "1day.html",
"2weeks": "2weeks.html",
"1year": "1year.html",
}
period_labels = {
"3hours": "3 hours",
"1day": "1 day",
"2weeks": "2 weeks",
"1year": "1 year",
}
for period in PERIODS:
cards = "\n".join( cards = "\n".join(
f'<section><h2>{html.escape(title)}</h2>' + "".join( f'<section><h2>{html.escape(title)}</h2>'
f'<figure><figcaption>{period}</figcaption>' f'<img src="{filename}-{period}.png" '
f'<img src="{filename}-{period}.png" alt="{html.escape(title)}, {period}"></figure>' f'alt="{html.escape(title)}, {period_labels[period]}"></section>'
for period in PERIODS for filename, title, *_rest in definitions
) + "</section>" )
for filename, title, _unit, _series, _logarithmic, _stacked, _disk_memory, _network_mixed in definitions navigation = " ".join(
f'<a href="{page_files[item]}"'
f'{" class=active" if item == period else ""}>'
f'{period_labels[item]}</a>'
for item in PERIODS
) )
page = f"""<!doctype html> page = f"""<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"> <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width">
<meta http-equiv="refresh" content="300"><title>System monitor</title> <meta http-equiv="refresh" content="300"><title>System monitor{period_labels[period]}</title>
<style>body{{font:16px system-ui;margin:auto;max-width:1100px;padding:1rem;background:#f8fafc;color:#172033}} <style>body{{font:16px system-ui;margin:auto;max-width:1100px;padding:1rem;background:#f8fafc;color:#172033}}
section{{background:white;padding:1rem;margin:1rem 0;border-radius:.5rem;box-shadow:0 1px 4px #0002}} nav{{display:flex;gap:.5rem;flex-wrap:wrap}} nav a{{padding:.5rem .75rem;background:#e2e8f0;color:#172033;text-decoration:none;border-radius:.35rem}}
figure{{margin:1rem 0}} img{{width:100%;height:auto}} figcaption{{font-weight:600}}</style> nav a.active{{background:#2563eb;color:white}} section{{background:white;padding:1rem;margin:1rem 0;border-radius:.5rem;box-shadow:0 1px 4px #0002}}
</head><body><h1>System monitor</h1>{cards}</body></html>""" img{{width:100%;height:auto}}</style>
(output_dir / "index.html").write_text(page) </head><body><h1>System monitor — {period_labels[period]}</h1><nav>{navigation}</nav>{cards}</body></html>"""
(output_dir / page_files[period]).write_text(page)
if __name__ == "__main__": if __name__ == "__main__":