Grafana is an open-source visualization and monitoring tool — it turns logs, metrics, and time-series data into dashboards and alerts. We can use it to see how the system is performing its work properly.
Let’s build a IndexCalc → QC → Grafana monitoring pipeline step-by-step to illustrate potential of using it in our workflow.
First the Goal is to Automatically:
- Visualize & alert in Grafana (e.g., if QC fails or job runs late).
- Run your IndexCalc daily at 11:00 AM.
- Perform QC checks after completion.
- Log results (pass/fail, duration, timestamp) into a database.
┌──────────────────────────┐
│ APScheduler Job │
│ (runs IndexCalc at 11AM) │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ IndexCalc Engine │
│ (data fetch + calc) │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ QC Validator │
│ (check completeness, etc.)│
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ Database (SQLite/Postgres) │
│ job_log table: │
│ timestamp, status, reason │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ Grafana │
│ Dashboard + Alert Rules │
└──────────────────────────┘
Now the concrete set up, Step 1. Scheduler + IndexCalc + QC (Python)
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime
import sqlite3
import random
DB_FILE = "indexcalc_jobs.db"
def run_indexcalc():
start = datetime.now()
print(f"[{start}] Running IndexCalc...")
# Simulate index calculation
success = random.choice([True, True, True, False]) # fail sometimes
reason = None if success else "Missing data from source"
# Simulate duration
duration = round(random.uniform(20, 40), 2)
# Log QC result
with sqlite3.connect(DB_FILE) as conn:
conn.execute("""
CREATE TABLE IF NOT EXISTS job_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
status TEXT,
duration REAL,
reason TEXT
)
""")
conn.execute(
"INSERT INTO job_log (timestamp, status, duration, reason) VALUES (?, ?, ?, ?)",
(start.isoformat(), "PASS" if success else "FAIL", duration, reason)
)
conn.commit()
print(f"Job completed: {'PASS' if success else 'FAIL'} (Duration {duration}s)")
scheduler = BlockingScheduler()
scheduler.add_job(run_indexcalc, 'cron', hour=11, minute=0)
print("Scheduler started. Will run at 11:00 AM daily.")
scheduler.start()
Step 2. Connect Grafana Option A: Connect directly to SQLite (via plugin): Grafana supports SQLite with a plugin — install from the Grafana Marketplace: Plugin: frser-sqlite-datasource
Step 3. Create a Dashboard
Example panels:
| Panel | Query | Visualization |
|---|---|---|
| Job Status (Last Run) | SELECT timestamp, status FROM job_log ORDER BY id DESC LIMIT 1 | Stat panel (Green if PASS, Red if FAIL) |
| QC Failures Over Time | SELECT timestamp, COUNT(*) FROM job_log WHERE status='FAIL' GROUP BY timestamp | Bar chart |
| Job Duration | SELECT timestamp, duration FROM job_log | Line chart |
The dashboard is a web-based UI dashboard that Grafana provides. After you install or start Grafana (either self-hosted or cloud), it launches a web server that runs a UI — your dashboards live there.
| Deployment | How to Access the Dashboard |
|---|---|
| Local/self-hosted | Open your browser → http://localhost:3000 |
| Remote server | http://<your-server-ip>:3000 (e.g. http://192.168.1.20:3000) |
| Grafana Cloud | You’ll get a hosted URL, like https://yourorg.grafana.net |
The visual could be
+————————————————————-+
| IndexCalc QC Monitor |
+————————————————————-+
| Last Run: PASS ✅ | Avg Duration: 31.2s | Fail Count: 1 |
+————————————————————-+
| Job Duration (line chart over time) |
| |
| ●●●●●●●●●●●●●●● |
+————————————————————-+
| QC Failures by Reason (bar chart) |
| Missing Data ▇▇▇▇▇▇▇▇▇▇ |
| API Timeout ▇▇▇ |
+————————————————————-+