University of Dundee Industrial Team Project, 2026.
This repository contains a prototype observability platform for ATM operations. It ingests synthetic logs from multiple banking and infrastructure sources, validates and cleans them into SQLite, detects known anomaly patterns, scores unusual behaviour with Isolation Forest, correlates related detections into incidents, and presents the results in a role-based dashboard backed by a documented Flask API.
- Synthetic data generation for seven source systems
- Parser and ingestion flow from source files into raw text exports
- Data cleaning and schema-based loading into SQLite
- Rules-based anomaly detection for A1-A7 patterns
- ML-based anomaly scoring for selected metric sources
- Cross-source incident correlation
- Recommendation generation and feedback capture
- Role-based dashboard with auth, action logging, and live simulation controls
- Swagger-powered API documentation for the Flask backend
- Tests covering parsers, cleaning, analysis, ML, and dashboard endpoints
Synthetic source files
-> src/parsers/ingest.py
-> data/raw/*.txt
-> src/cleaning/data_cleaning.py
-> data/clean/atm_logs.db
-> src/analysis/detect.py
-> analysis_detections
-> src/ml/scorer.py
-> ml_anomaly_scores
-> src/analysis/correlate.py
-> incidents
-> src/dashboard/server.py
-> HTML dashboard + REST API + Swagger docs
The main application entrypoint is main.py. It starts the Flask dashboard and runs the ingestion, cleaning, detection, scoring, and correlation pipeline.
main.py: starts the dashboard server and runs the pipelinesrc/dashboard/server.py: Flask application, HTML views, API endpoints, Swagger docssrc/synthetic/live_agent.py: background synthetic event generator for near-real-time demo updates
src/parsers/: converts synthetic source files into raw tabular exportssrc/cleaning/: validates, normalises, and loads data into SQLitesrc/analysis/: static anomaly detection, taxonomy, correlation, recommendationssrc/ml/: feature extraction, Isolation Forest model, anomaly scoringsrc/dashboard/: backend routes, auth, templates, and frontend assetssrc/synthetic/: synthetic data generation and live injection logic
data/synthetic/: committed synthetic source data used for demo and testingdata/raw/: parser output generated locallydata/clean/: cleaned SQLite databases and related outputsdocs/: schema documentation and architecture decisionstests/: automated test suite mirroring the main project areas
The platform currently models seven synthetic data sources:
| Source | Table | Format | Purpose |
|---|---|---|---|
| ATM Application Log | ATMA |
JSON | ATM client activity, errors, request lifecycle |
| ATM Hardware Sensor Log | ATMH |
JSON | Hardware status, sensor warnings, cash cassette state |
| Terminal Handler App Log | TERM |
JSON | Service-side request handling and runtime failures |
| Kafka ATM Metrics Stream | KAFK |
JSON | Transaction throughput, success rates, and failures |
| Prometheus Metrics | PROM |
CSV | JVM and service metrics |
| Windows OS Metrics | WINOS |
CSV | ATM host CPU, memory, disk, and network telemetry |
| GCP Cloud Metrics | GCP |
CSV | Infrastructure and container-level cloud metrics |
The shared schema reference lives in docs/schema.md.
The rules-based analysis layer currently models these anomaly types:
| ID | Name | Primary Sources |
|---|---|---|
| A1 | Network timeout cascade | ATMA, KAFK, TERM |
| A2 | Cash cassette depletion | ATMH, KAFK |
| A3 | JVM memory leak -> OOM | PROM, GCP, TERM |
| A4 | Container restart loop | GCP, TERM |
| A5 | Performance degradation | KAFK, ATMA |
| A6 | OS memory pressure | WINOS, ATMA |
| A7 | Out-of-order or malformed Kafka event | KAFK |
Static taxonomy data is managed through src/analysis/taxonomy.py.
The dashboard is served by Flask and supports three user roles:
admin: platform-wide readiness, governance, and source coveragemanager: operational queue, issue review, and action follow-upops: ATM-level incidents, technical evidence, and live operational monitoring
Key dashboard features:
- session-based signup and login
- role-specific dashboard routing
- health and system status endpoints
- ATM list, alerts, incidents, trends, taxonomy, ML summary, and recommendations
- feedback capture for recommendation quality
- action logging for manager and ops workflows
- live agent start, stop, status, and anomaly injection controls
Swagger UI is integrated into the Flask app.
- Swagger UI:
/api/docs/ - OpenAPI JSON:
/api/openapi.json
Once the app is running locally, open:
http://127.0.0.1:5000/api/docs/
The docs are generated from route docstrings in src/dashboard/server.py.
The live agent provides a near-real-time demo mode for the dashboard.
- it runs as a background thread
- it writes directly into the cleaned SQLite tables
- it re-runs detection and correlation after each tick
- it can inject selected anomaly types for demo scenarios
Supported injection types currently include A1, A2, A4, A5, A6, and A7.
The design decision and trade-offs are documented in docs/intake_method.md.
src/analysis/recommendations.py provides a rule-driven recommendation layer that:
- maps anomaly types to remediation guidance
- ranks recommendations with a confidence score
- stores user feedback in SQLite
- adjusts recommendation confidence using recorded likes and dislikes
src/ml/scorer.py orchestrates feature extraction and Isolation Forest scoring for:
KAFKWINOSGCPPROM
The ML layer stores results in ml_anomaly_scores and can register dynamic taxonomy entries for detected anomaly clusters.
- Python 3.11+
- a local virtual environment
python -m venv .venv
.venv/bin/pip install -r requirements.txtThis repository already expects a project-local virtual environment at .venv.
.venv/bin/python main.pyBy default the app starts on http://0.0.0.0:5000 using values from config.ini.
- raw parser output:
data/raw - cleaned database:
data/clean/atm_logs.db - auth database:
data/clean/auth.db - cleaning error output:
data/clean/broken_logs.json
config.ini currently defines:
[NETWORK]
port=5000
host=0.0.0.0
[PATHS]
raw_data_dir=data/raw
cleaned_db_path=data/clean/atm_logs.db
error_path=data/clean.venv/bin/python src/dashboard/server.pyThis starts the Flask app directly, without the full pipeline orchestration performed by main.py.
.venv/bin/pip install -r requirements.txt.venv/bin/pytest.venv/bin/ruff check .http://127.0.0.1:5000/api/docs/
The current test suite includes coverage for:
- parser ingestion in
tests/parsers/ - cleaning and filtering in
tests/cleaning/ - taxonomy and incident correlation in
tests/analysis/ - Isolation Forest scoring in
tests/ml/ - dashboard action and documentation endpoints in
tests/dashboard/ - scaffold checks in
tests/test_scaffold.py
The repository includes a railway.toml deployment config.
- start command:
python main.py - health check path:
/health
docs/schema.md: shared schema and anomaly signature referencedocs/intake_method.md: ADR for the real-time ingestion approach
| Name | Area |
|---|---|
| Marcus | Lead, synthetic data generation, ML model, recommendation engine |
| Max | Log parsers and ingestion for all seven sources |
| Emily | Data filtering |
| Olga | Data cleaning pipeline |
| Callum | Rules-based anomaly detection and cross-source correlation |
| Sophina | Dashboard and visualisation |
- Branch from
mainusing<initials>/<issue-number>-<short-description>. - Open a pull request linked to the relevant issue.
- Get at least one teammate review before merging.
- Ensure linting and tests pass.
Schema changes are controlled through docs/schema.md and should only be updated through reviewed pull requests with agreement from affected owners.