Add global report generation
This commit is contained in:
parent
11d6e5e4ba
commit
a3f06fd9e2
3 changed files with 83 additions and 0 deletions
|
@ -24,6 +24,7 @@ python scripts/generate_reports.py hourly
|
|||
python scripts/generate_reports.py daily
|
||||
python scripts/generate_reports.py weekly
|
||||
python scripts/generate_reports.py monthly
|
||||
python scripts/generate_reports.py global
|
||||
|
||||
# Generate reports for each individual domain
|
||||
echo "[INFO] Generating per-domain reports..."
|
||||
|
|
|
@ -101,6 +101,10 @@ def _generate_interval(interval: str, domain: Optional[str] = None) -> None:
|
|||
|
||||
report_list = []
|
||||
for definition in cfg:
|
||||
if "{bucket}" not in definition["query"] or definition.get("global"):
|
||||
# Global reports are generated separately
|
||||
continue
|
||||
|
||||
name = definition["name"]
|
||||
query = definition["query"].replace("{bucket}", bucket)
|
||||
query = query.replace("FROM logs", "FROM logs_view")
|
||||
|
@ -154,6 +158,50 @@ def _generate_root_index() -> None:
|
|||
typer.echo(f"Generated root index at {out_path}")
|
||||
|
||||
|
||||
def _generate_global() -> None:
|
||||
"""Generate reports that do not depend on an interval."""
|
||||
cfg = _load_config()
|
||||
if not cfg:
|
||||
typer.echo("No report definitions found")
|
||||
return
|
||||
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
cur = conn.cursor()
|
||||
|
||||
out_dir = OUTPUT_DIR / "global"
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
report_list = []
|
||||
for definition in cfg:
|
||||
if "{bucket}" in definition["query"] and not definition.get("global"):
|
||||
continue
|
||||
|
||||
name = definition["name"]
|
||||
query = definition["query"]
|
||||
cur.execute(query)
|
||||
rows = cur.fetchall()
|
||||
headers = [c[0] for c in cur.description]
|
||||
data = [dict(zip(headers, row)) for row in rows]
|
||||
json_path = out_dir / f"{name}.json"
|
||||
_save_json(json_path, data)
|
||||
entry = {
|
||||
"name": name,
|
||||
"label": definition.get("label", name.title()),
|
||||
"chart": definition.get("chart", "line"),
|
||||
"json": f"{name}.json",
|
||||
"html": f"{name}.html",
|
||||
}
|
||||
if "color" in definition:
|
||||
entry["color"] = definition["color"]
|
||||
if "colors" in definition:
|
||||
entry["colors"] = definition["colors"]
|
||||
_render_snippet(entry, out_dir)
|
||||
report_list.append(entry)
|
||||
|
||||
_save_json(out_dir / "reports.json", report_list)
|
||||
typer.echo("Generated global reports")
|
||||
|
||||
|
||||
@app.command()
|
||||
def hourly(
|
||||
domain: Optional[str] = typer.Option(
|
||||
|
@ -218,6 +266,12 @@ def monthly(
|
|||
_generate_interval("monthly", domain)
|
||||
|
||||
|
||||
@app.command("global")
|
||||
def global_reports() -> None:
|
||||
"""Generate global reports."""
|
||||
_generate_global()
|
||||
|
||||
|
||||
@app.command()
|
||||
def index() -> None:
|
||||
"""Generate the root index page linking all reports."""
|
||||
|
|
|
@ -80,6 +80,14 @@ def sample_reports(tmp_path):
|
|||
FROM logs
|
||||
GROUP BY bucket
|
||||
ORDER BY bucket
|
||||
- name: domain_totals
|
||||
global: true
|
||||
query: |
|
||||
SELECT host AS bucket,
|
||||
COUNT(*) AS value
|
||||
FROM logs
|
||||
GROUP BY host
|
||||
ORDER BY value DESC
|
||||
"""
|
||||
)
|
||||
return cfg
|
||||
|
@ -161,3 +169,23 @@ def test_generate_root_index(tmp_path, sample_reports, monkeypatch):
|
|||
# check for domain options
|
||||
assert '<option value="foo.com">' in content
|
||||
assert '<option value="bar.com">' in content
|
||||
|
||||
|
||||
def test_global_reports_once(tmp_path, sample_reports, monkeypatch):
|
||||
db_path = tmp_path / "database" / "ngxstat.db"
|
||||
setup_db(db_path)
|
||||
|
||||
monkeypatch.setattr(gr, "DB_PATH", db_path)
|
||||
monkeypatch.setattr(gr, "OUTPUT_DIR", tmp_path / "output")
|
||||
monkeypatch.setattr(gr, "REPORT_CONFIG", sample_reports)
|
||||
monkeypatch.setattr(
|
||||
gr, "TEMPLATE_DIR", Path(__file__).resolve().parents[1] / "templates"
|
||||
)
|
||||
|
||||
gr._generate_global()
|
||||
gr._generate_interval("hourly")
|
||||
|
||||
global_snippet = tmp_path / "output" / "global" / "domain_totals.html"
|
||||
assert global_snippet.exists()
|
||||
assert not (tmp_path / "output" / "hourly" / "domain_totals.html").exists()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue