A production-style observability experiment built using a Laravel API that emits ML-ready telemetry and integrates with a full monitoring stack (Prometheus + Grafana).
The system simulates realistic production behavior, generates structured logs, exposes RED metrics, and runs a controlled traffic experiment with anomaly injection to produce datasets suitable for AIOps analysis.
The observability stack is deployed using Docker Compose and consists of four main components:
| Component | Technology | Role |
|---|---|---|
| API Service | Laravel 10 + PHP 8.2 | Handles requests and emits structured telemetry |
| Metrics Backend | Prometheus | Scrapes /api/metrics and stores time-series metrics |
| Visualization | Grafana | Displays monitoring dashboards |
| Traffic Generator | Python (aiohttp) | Generates controlled load and anomaly injection |
All services run on a shared Docker network.
Each request generates a structured JSON log containing 17 standardized fields including:
- correlation ID (
request_id) - request latency (
latency_ms) - error category
- HTTP status
- request metadata
- build version
- host information
Logs are written to:
api/storage/logs/aiops.log
and later exported as a machine-learning dataset.
Every request receives a unique X-Request-Id.
- If provided by the client → reused
- If missing → generated automatically (UUID v4)
This allows request tracing across distributed systems.
All failures are normalized into five categories:
| Category | Trigger |
|---|---|
| VALIDATION_ERROR | Request validation failure |
| DATABASE_ERROR | Database query failure |
| SYSTEM_ERROR | Runtime exceptions |
| TIMEOUT_ERROR | Latency greater than 4000ms |
| UNKNOWN | Unexpected errors |
This structure simplifies anomaly detection and ML analysis.
The API exposes multiple endpoints designed to simulate different behaviors.
| Endpoint | Description |
|---|---|
GET /api/normal |
Fast successful response |
GET /api/slow |
Delayed response (1–2 seconds) |
GET /api/slow?hard=1 |
Heavy latency (5–7 seconds) |
GET /api/error |
Always throws a runtime exception |
GET /api/random |
Random mix of responses |
GET /api/db |
Executes a SQLite query |
GET /api/db?fail=1 |
Simulated database failure |
POST /api/validate |
Request validation testing |
GET /api/metrics |
Prometheus metrics endpoint |
| `POST /api/anomaly-window?active=1 | 0` |
Metrics are exposed through:
GET /api/metrics
| Metric | Type | Purpose |
|---|---|---|
http_requests_total |
Counter | Total requests handled |
http_errors_total |
Counter | Errors grouped by category |
http_request_duration_seconds |
Histogram | Latency distribution |
anomaly_window_active |
Gauge | Ground-truth anomaly marker |
Histogram buckets:
0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, +Inf
The monitoring dashboard includes five observability panels:
- Request rate per endpoint
- Error rate percentage
- Latency percentiles (P50 / P95 / P99)
- Error category distribution
- Anomaly window marker
Dashboard configuration is stored in:
grafana_dashboard.json
The Python traffic generator simulates production load and injects controlled anomalies.
Run:
python traffic_generator.py| Endpoint | Traffic Share |
|---|---|
| normal | 70% |
| slow | 15% |
| slow-hard | 5% |
| error | 5% |
| db | 3% |
| validate | 2% |
During a 2-minute anomaly window, the system injects an error spike:
/api/error increases from 5% → 40%
Ground truth timestamps are stored in:
ground_truth.json
After running the traffic generator, logs can be converted into a structured dataset.
Run:
php export_logs.phpThis parses:
api/storage/logs/aiops.log
and exports:
logs.json
Schema validation ensures all 17 fields are present in every record.
docker-compose up --build| Service | URL |
|---|---|
| API | http://localhost:8000 |
| Prometheus | http://localhost:9090 |
| Grafana | http://localhost:3000 |
Grafana credentials:
admin / admin
aiops-observability-lab
│
├── api/
│ └── storage/logs/aiops.log
│
├── docker-compose.yml
├── prometheus.yml
├── grafana_dashboard.json
├── traffic_generator.py
├── export_logs.php
│
├── logs.json
├── ground_truth.json
└── engineering_report.md
The repository includes the following artifacts:
- Structured telemetry logs (
aiops.log) - ML dataset (
logs.json) - Ground truth anomaly dataset (
ground_truth.json) - Monitoring configuration (
prometheus.yml) - Grafana dashboard (
grafana_dashboard.json) - Traffic generator (
traffic_generator.py) - Engineering report (
engineering_report.md)
Lab Work 2 adds active anomaly detection on top of the observability stack from Lab Work 1.
The detector is implemented as a long-running Artisan command:
cd api
php artisan aiops:detect --interval=20- Queries Prometheus metrics per endpoint
- Updates baseline behavior per endpoint (EMA)
- Detects multi-signal anomalies
- Correlates signals into one high-level incident
- Saves incidents to JSON
- Emits deduplicated alerts
| Requirement | Implementation |
|---|---|
| Detection command | api/app/Console/Commands/AIOpsDetect.php |
| Prometheus API client | api/app/Services/PrometheusClient.php |
| Baseline modeling | api/app/Services/BaselineComputer.php |
| Multi-signal anomaly rules | api/app/Services/AnomalyDetector.php |
| Event correlation | api/app/Services/EventCorrelator.php |
| Incident generation | api/app/Services/IncidentManager.php |
| Alerting + deduplication | api/app/Services/AlertManager.php |
- Incidents:
api/storage/aiops/incidents.json - Alerts:
api/storage/aiops/alerts.json - Alert fingerprints:
api/storage/aiops/alerted_fingerprints.json - Baselines:
api/storage/aiops/baselines.json
Lab Work 2 report is available at:
engineering_report.md
It explains:
- baseline design
- anomaly detection rules
- event correlation strategy
- alert suppression logic
- Start the stack
docker-compose up -dExpected output (example):
... app-1 Up
... prometheus-1 Up
... grafana-1 Up
- Start the detector (Terminal A)
cd api
php artisan aiops:detect --interval=20Expected output (healthy cycle example):
Cycle #N ...
Querying Prometheus metrics...
Baselines updated for 5 endpoint(s).
No anomalies detected — system healthy.
- Trigger short anomaly traffic (Terminal B, repo root)
python traffic_generator.pyExpected output (example):
Starting traffic generation at ...
Anomaly window: ... to ...
Requests dispatched: 250
Traffic generation complete.
- Show generated incidents and alerts
type api\storage\aiops\incidents.json
type api\storage\aiops\alerts.jsonExpected output (detector Terminal A):
⚑ GROUND-TRUTH anomaly window is ACTIVE
Detected ... anomalous signal(s)
Correlation -> ERROR_STORM [CRITICAL]
Incident saved: INC-...
Alert suppressed — same pattern alerted recently (deduplication).
Expected JSON fields in incidents.json:
incident_id, incident_type, severity, status, detected_at,
affected_service, affected_endpoints, triggering_signals,
baseline_values, observed_values, summary
Lab Work 3 adds a machine learning anomaly detection pipeline that learns normal behavior from telemetry windows and identifies anomalous windows automatically.
Run from repo root:
c:/Users/merna/OneDrive/Desktop/aiops-observability-lab/.venv/Scripts/python.exe lab3_ml_anomaly_detection.py- Training and inference script:
lab3_ml_anomaly_detection.py - Engineered telemetry dataset:
aiops_dataset.csv - Window anomaly predictions:
anomaly_predictions.csv - Metrics summary:
lab3_metrics_summary.json - Engineering report:
engineering_report.md
- Model used:
IsolationForest - Train-only period: windows before anomaly start (normal behavior only)
- Feature set:
avg_latencymax_latencyrequest_rateerror_ratelatency_stderrors_per_windowendpoint_frequency
- Dataset source remains telemetry generated by Labs 1 and 2 (
logs.json+ derived operational rates). - Predictions include required fields:
timestamp,anomaly_score,is_anomaly. - Ground-truth overlap checks are included in
lab3_metrics_summary.json.
Lab Work 5 adds an automated response layer that reacts to incidents generated by the detector.
Run from api/:
php artisan aiops:respondUseful options:
php artisan aiops:respond --once
php artisan aiops:respond --interval=20Policies are defined in:
api/config/aiops_response_policies.php
Default policy mappings:
LATENCY_SPIKE->RESTART_SERVICEERROR_STORM->SEND_ALERTTRAFFIC_SURGE->SCALE_SERVICESERVICE_DEGRADATION->THROTTLE_TRAFFICLOCALIZED_ENDPOINT_FAILURE->RESTART_SERVICE
The automation engine simulates execution for:
- service restart
- operator alerting
- service scaling
- traffic throttling
- incident escalation
Actions are simulated but always logged.
Response records are written to:
api/storage/aiops/responses.json
Each record includes:
incident_idaction_takentimestampresultnotes
The engine escalates to CRITICAL_ALERT when either condition is true:
- automated action fails
- anomaly persists (based on configured thresholds)
- Start detector (if not already running):
php artisan aiops:detect --interval=20- Run automation engine in a second terminal:
php artisan aiops:respond --once- Show response evidence:
type storage\aiops\responses.json
