Structure: - control-plane/: Registries, SIMCO directives, CI/CD templates - projects/: Gamilit, ERP-Suite, Trading-Platform, Betting-Analytics - shared/: Libs catalog, knowledge-base Key features: - Centralized port, domain, database, and service registries - 23 SIMCO directives + 6 fundamental principles - NEXUS agent profiles with delegation rules - Validation scripts for workspace integrity - Dockerfiles for all services - Path aliases for quick reference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
618 lines
15 KiB
SQL
618 lines
15 KiB
SQL
-- =====================================================
|
|
-- GLIT Platform - System Metrics & Alerts Seeds
|
|
-- =====================================================
|
|
-- Schema: audit_logging
|
|
-- Description: Performance metrics, system alerts, user activity logs
|
|
-- Dependencies: auth schema (users)
|
|
-- =====================================================
|
|
|
|
SET search_path TO audit_logging, auth, public;
|
|
|
|
-- =====================================================
|
|
-- PERFORMANCE METRICS: Métricas históricas
|
|
-- =====================================================
|
|
INSERT INTO audit_logging.performance_metrics (
|
|
metric_name, metric_type, metric_metric_value,
|
|
unit, component, environment,
|
|
dimensions, recorded_at, created_at
|
|
) VALUES
|
|
|
|
-- ============ DATABASE METRICS ============
|
|
|
|
(
|
|
'database_connections_active',
|
|
'gauge',
|
|
15.0,
|
|
'connections',
|
|
'postgresql',
|
|
'development',
|
|
'{
|
|
"pool_size": 20,
|
|
"utilization_percentage": 75,
|
|
"idle_connections": 5,
|
|
"waiting_clients": 0
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '10 minutes',
|
|
NOW() - INTERVAL '10 minutes'
|
|
),
|
|
(
|
|
'database_query_avg_duration',
|
|
'histogram',
|
|
45.5,
|
|
'milliseconds',
|
|
'postgresql',
|
|
'development',
|
|
'{
|
|
"queries_sampled": 1250,
|
|
"p50": 25.0,
|
|
"p75": 55.0,
|
|
"p95": 85.0,
|
|
"p99": 150.0,
|
|
"max": 500.0
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '10 minutes',
|
|
NOW() - INTERVAL '10 minutes'
|
|
),
|
|
(
|
|
'database_cache_hit_ratio',
|
|
'gauge',
|
|
98.5,
|
|
'percentage',
|
|
'postgresql',
|
|
'development',
|
|
'{
|
|
"cache_hits": 9850,
|
|
"cache_misses": 150,
|
|
"total_queries": 10000,
|
|
"shared_buffers_mb": 128
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '15 minutes',
|
|
NOW() - INTERVAL '15 minutes'
|
|
),
|
|
(
|
|
'database_transactions_per_second',
|
|
'gauge',
|
|
45.8,
|
|
'transactions',
|
|
'postgresql',
|
|
'development',
|
|
'{
|
|
"commits": 2748,
|
|
"rollbacks": 12,
|
|
"sample_duration_seconds": 60
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '20 minutes',
|
|
NOW() - INTERVAL '20 minutes'
|
|
),
|
|
|
|
-- ============ APPLICATION METRICS ============
|
|
|
|
(
|
|
'api_requests_total',
|
|
'counter',
|
|
5432.0,
|
|
'requests',
|
|
'api_server',
|
|
'development',
|
|
'{
|
|
"endpoint": "/api/exercises",
|
|
"method": "GET",
|
|
"status_2xx": 5200,
|
|
"status_4xx": 200,
|
|
"status_5xx": 32,
|
|
"time_window_hours": 1
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '1 hour',
|
|
NOW() - INTERVAL '1 hour'
|
|
),
|
|
(
|
|
'api_response_time',
|
|
'histogram',
|
|
125.5,
|
|
'milliseconds',
|
|
'api_server',
|
|
'development',
|
|
'{
|
|
"endpoint": "/api/modules",
|
|
"method": "GET",
|
|
"p50": 95.0,
|
|
"p75": 180.0,
|
|
"p95": 250.0,
|
|
"p99": 450.0,
|
|
"requests_count": 850
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '30 minutes',
|
|
NOW() - INTERVAL '30 minutes'
|
|
),
|
|
(
|
|
'api_error_rate',
|
|
'gauge',
|
|
0.8,
|
|
'percentage',
|
|
'api_server',
|
|
'development',
|
|
'{
|
|
"total_requests": 5000,
|
|
"errors": 40,
|
|
"status_5xx": 32,
|
|
"status_4xx": 8,
|
|
"threshold_percentage": 2.0
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '45 minutes',
|
|
NOW() - INTERVAL '45 minutes'
|
|
),
|
|
(
|
|
'websocket_connections_active',
|
|
'gauge',
|
|
12.0,
|
|
'connections',
|
|
'websocket_server',
|
|
'development',
|
|
'{
|
|
"max_connections": 1000,
|
|
"utilization_percentage": 1.2,
|
|
"messages_per_second": 45
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '5 minutes',
|
|
NOW() - INTERVAL '5 minutes'
|
|
),
|
|
|
|
-- ============ USER ACTIVITY METRICS ============
|
|
|
|
(
|
|
'active_users_daily',
|
|
'gauge',
|
|
5.0,
|
|
'users',
|
|
'application',
|
|
'development',
|
|
'{
|
|
"date": "2025-11-02",
|
|
"students": 3,
|
|
"instructors": 1,
|
|
"admins": 1,
|
|
"total_sessions": 8,
|
|
"avg_session_duration_minutes": 45
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '6 hours',
|
|
NOW() - INTERVAL '6 hours'
|
|
),
|
|
(
|
|
'exercises_completed',
|
|
'counter',
|
|
12.0,
|
|
'exercises',
|
|
'application',
|
|
'development',
|
|
'{
|
|
"period": "24h",
|
|
"module_breakdown": {
|
|
"MOD-01-LITERAL": 8,
|
|
"MOD-02-INFERENCIAL": 3,
|
|
"MOD-03-CRITICA": 1
|
|
},
|
|
"avg_score_percentage": 75.5
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '1 hour',
|
|
NOW() - INTERVAL '1 hour'
|
|
),
|
|
(
|
|
'ml_coins_transactions',
|
|
'counter',
|
|
45.0,
|
|
'transactions',
|
|
'gamification',
|
|
'development',
|
|
'{
|
|
"period": "24h",
|
|
"total_earned": 1250,
|
|
"total_spent": 350,
|
|
"net_change": 900,
|
|
"unique_users": 3
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '2 hours',
|
|
NOW() - INTERVAL '2 hours'
|
|
),
|
|
(
|
|
'mission_completion_rate',
|
|
'gauge',
|
|
65.5,
|
|
'percentage',
|
|
'application',
|
|
'development',
|
|
'{
|
|
"missions_assigned": 20,
|
|
"missions_completed": 13,
|
|
"missions_in_progress": 5,
|
|
"missions_overdue": 2
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '3 hours',
|
|
NOW() - INTERVAL '3 hours'
|
|
),
|
|
|
|
-- ============ SYSTEM RESOURCES ============
|
|
|
|
(
|
|
'memory_usage',
|
|
'gauge',
|
|
512.5,
|
|
'megabytes',
|
|
'system',
|
|
'development',
|
|
'{
|
|
"total_mb": 2048,
|
|
"utilization_percentage": 25,
|
|
"heap_used_mb": 380,
|
|
"heap_total_mb": 512,
|
|
"rss_mb": 650
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '5 minutes',
|
|
NOW() - INTERVAL '5 minutes'
|
|
),
|
|
(
|
|
'cpu_usage',
|
|
'gauge',
|
|
35.2,
|
|
'percentage',
|
|
'system',
|
|
'development',
|
|
'{
|
|
"cores": 4,
|
|
"load_average": [1.2, 1.5, 1.3],
|
|
"user_percentage": 25.5,
|
|
"system_percentage": 9.7
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '5 minutes',
|
|
NOW() - INTERVAL '5 minutes'
|
|
),
|
|
(
|
|
'disk_usage',
|
|
'gauge',
|
|
1024.0,
|
|
'megabytes',
|
|
'system',
|
|
'development',
|
|
'{
|
|
"total_gb": 50,
|
|
"used_gb": 1.0,
|
|
"available_gb": 49.0,
|
|
"utilization_percentage": 2.0
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '10 minutes',
|
|
NOW() - INTERVAL '10 minutes'
|
|
),
|
|
(
|
|
'network_throughput',
|
|
'gauge',
|
|
2.5,
|
|
'megabytes_per_second',
|
|
'system',
|
|
'development',
|
|
'{
|
|
"inbound_mbps": 1.8,
|
|
"outbound_mbps": 0.7,
|
|
"packets_per_second": 1250,
|
|
"errors": 0
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '5 minutes',
|
|
NOW() - INTERVAL '5 minutes'
|
|
),
|
|
|
|
-- ============ CACHE METRICS ============
|
|
|
|
(
|
|
'cache_hit_rate',
|
|
'gauge',
|
|
85.5,
|
|
'percentage',
|
|
'redis',
|
|
'development',
|
|
'{
|
|
"total_requests": 5000,
|
|
"hits": 4275,
|
|
"misses": 725,
|
|
"evictions": 12
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '15 minutes',
|
|
NOW() - INTERVAL '15 minutes'
|
|
),
|
|
(
|
|
'cache_memory_usage',
|
|
'gauge',
|
|
128.5,
|
|
'megabytes',
|
|
'redis',
|
|
'development',
|
|
'{
|
|
"max_memory_mb": 256,
|
|
"utilization_percentage": 50.2,
|
|
"keys_count": 1250,
|
|
"expired_keys": 45
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '10 minutes',
|
|
NOW() - INTERVAL '10 minutes'
|
|
)
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
-- =====================================================
|
|
-- SYSTEM ALERTS: Alertas generadas
|
|
-- =====================================================
|
|
INSERT INTO audit_logging.system_alerts (
|
|
alert_type, severity, title, message,
|
|
component, threshold_metric_value, current_metric_value,
|
|
status, triggered_at, resolved_at,
|
|
dimensions, created_at, updated_at
|
|
) VALUES
|
|
|
|
-- ============ RESOLVED ALERTS ============
|
|
|
|
-- High memory usage (resolved)
|
|
(
|
|
'resource',
|
|
'warning',
|
|
'High Memory Usage Detected',
|
|
'Memory usage exceeded 80% threshold',
|
|
'system',
|
|
80.0,
|
|
85.5,
|
|
'resolved',
|
|
NOW() - INTERVAL '2 hours',
|
|
NOW() - INTERVAL '1 hour',
|
|
'{
|
|
"actions_taken": [
|
|
"Memory cache cleared",
|
|
"Garbage collection forced",
|
|
"Unused connections closed"
|
|
],
|
|
"resolution_time_minutes": 60,
|
|
"peak_memory_mb": 1740,
|
|
"final_memory_mb": 512
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '2 hours',
|
|
NOW() - INTERVAL '1 hour'
|
|
),
|
|
|
|
-- Failed login attempts (resolved)
|
|
(
|
|
'security',
|
|
'info',
|
|
'Multiple Failed Login Attempts',
|
|
'User exceeded login attempt threshold',
|
|
'authentication',
|
|
5.0,
|
|
6.0,
|
|
'resolved',
|
|
NOW() - INTERVAL '3 hours',
|
|
NOW() - INTERVAL '2 hours 55 minutes',
|
|
'{
|
|
"user_email": "test@example.com",
|
|
"ip_address": "203.0.113.42",
|
|
"actions_taken": [
|
|
"Account locked for 15 minutes",
|
|
"Security notification sent"
|
|
],
|
|
"resolution": "User successfully logged in after password reset",
|
|
"lockout_duration_minutes": 15
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '3 hours',
|
|
NOW() - INTERVAL '2 hours 55 minutes'
|
|
),
|
|
|
|
-- Database backup success (acknowledged)
|
|
(
|
|
'maintenance',
|
|
'info',
|
|
'Automated Backup Completed',
|
|
'Daily database backup completed successfully',
|
|
'database',
|
|
NULL,
|
|
NULL,
|
|
'acknowledged',
|
|
NOW() - INTERVAL '6 hours',
|
|
NOW() - INTERVAL '6 hours',
|
|
'{
|
|
"backup_size_mb": 450,
|
|
"duration_seconds": 45,
|
|
"location": "/backups/glit_dev_2025-11-02.sql.gz",
|
|
"compression_ratio": 4.5,
|
|
"integrity_check": "passed"
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '6 hours',
|
|
NOW() - INTERVAL '6 hours'
|
|
),
|
|
|
|
-- ============ ACTIVE ALERTS ============
|
|
|
|
-- Slow API endpoint (active)
|
|
(
|
|
'performance',
|
|
'warning',
|
|
'Slow API Response Time',
|
|
'Endpoint /api/leaderboards exceeding SLA',
|
|
'api_server',
|
|
200.0,
|
|
450.0,
|
|
'active',
|
|
NOW() - INTERVAL '15 minutes',
|
|
NULL,
|
|
'{
|
|
"endpoint": "/api/leaderboards",
|
|
"method": "GET",
|
|
"sla_ms": 200,
|
|
"p99_ms": 450,
|
|
"requests_affected": 25,
|
|
"suggested_actions": [
|
|
"Add database index on leaderboards.student_id",
|
|
"Implement Redis caching for leaderboard data",
|
|
"Consider pagination for large result sets"
|
|
]
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '15 minutes',
|
|
NOW()
|
|
),
|
|
|
|
-- High error rate (active)
|
|
(
|
|
'performance',
|
|
'error',
|
|
'High API Error Rate',
|
|
'Error rate exceeded 2% threshold',
|
|
'api_server',
|
|
2.0,
|
|
3.5,
|
|
'active',
|
|
NOW() - INTERVAL '25 minutes',
|
|
NULL,
|
|
'{
|
|
"total_requests": 1000,
|
|
"errors": 35,
|
|
"error_breakdown": {
|
|
"500_internal_error": 20,
|
|
"503_service_unavailable": 10,
|
|
"504_gateway_timeout": 5
|
|
},
|
|
"affected_endpoints": [
|
|
"/api/exercises/submit",
|
|
"/api/ml-coins/transactions"
|
|
],
|
|
"investigating": true
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '25 minutes',
|
|
NOW()
|
|
),
|
|
|
|
-- ============ ACKNOWLEDGED ALERTS ============
|
|
|
|
-- SSL certificate expiry warning (acknowledged)
|
|
(
|
|
'security',
|
|
'warning',
|
|
'SSL Certificate Expiring Soon',
|
|
'SSL certificate will expire in 30 days',
|
|
'security',
|
|
30.0,
|
|
30.0,
|
|
'acknowledged',
|
|
NOW() - INTERVAL '1 day',
|
|
NOW() - INTERVAL '1 day',
|
|
'{
|
|
"domain": "*.glit.edu.mx",
|
|
"expiry_date": "2025-12-02",
|
|
"days_remaining": 30,
|
|
"renewal_initiated": true,
|
|
"auto_renewal": true
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '1 day',
|
|
NOW() - INTERVAL '1 day'
|
|
),
|
|
|
|
-- Disk space warning (acknowledged)
|
|
(
|
|
'resource',
|
|
'info',
|
|
'Disk Space Usage',
|
|
'Disk usage reached 70% threshold',
|
|
'system',
|
|
70.0,
|
|
72.5,
|
|
'acknowledged',
|
|
NOW() - INTERVAL '8 hours',
|
|
NOW() - INTERVAL '8 hours',
|
|
'{
|
|
"mount_point": "/var/lib/postgresql",
|
|
"total_gb": 100,
|
|
"used_gb": 72.5,
|
|
"available_gb": 27.5,
|
|
"cleanup_scheduled": true,
|
|
"retention_policy": "90 days"
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '8 hours',
|
|
NOW() - INTERVAL '8 hours'
|
|
)
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
-- =====================================================
|
|
-- USER ACTIVITY LOGS: Actividad de usuarios
|
|
-- =====================================================
|
|
|
|
DO $$
|
|
DECLARE
|
|
student_record RECORD;
|
|
activity_types TEXT[] := ARRAY['page_view', 'exercise_start', 'exercise_complete', 'mission_view', 'leaderboard_view', 'store_visit', 'achievement_view'];
|
|
pages TEXT[] := ARRAY['/modules', '/missions', '/leaderboard', '/ml-store', '/profile', '/achievements'];
|
|
BEGIN
|
|
-- Generar activity logs para cada estudiante
|
|
FOR student_record IN
|
|
SELECT user_id, email FROM auth.users WHERE role = 'student' LIMIT 3
|
|
LOOP
|
|
-- 5 actividades por estudiante
|
|
FOR i IN 1..5 LOOP
|
|
INSERT INTO audit_logging.user_activity_logs (
|
|
user_id, activity_type, activity_description,
|
|
ip_address, user_agent, session_id,
|
|
dimensions, created_at
|
|
) VALUES (
|
|
student_record.user_id,
|
|
activity_types[1 + floor(random() * array_length(activity_types, 1))::int],
|
|
'User activity: ' || pages[1 + floor(random() * array_length(pages, 1))::int],
|
|
'192.168.1.' || (50 + i)::TEXT,
|
|
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120.0.0.0',
|
|
gen_random_uuid(),
|
|
jsonb_build_object(
|
|
'page', pages[1 + floor(random() * array_length(pages, 1))::int],
|
|
'duration_seconds', 30 + floor(random() * 120)::int,
|
|
'interactions', 1 + floor(random() * 5)::int,
|
|
'referrer', '/dashboard',
|
|
'device_type', CASE WHEN random() > 0.7 THEN 'mobile' ELSE 'desktop' END
|
|
),
|
|
NOW() - (random() * INTERVAL '24 hours')
|
|
)
|
|
ON CONFLICT DO NOTHING;
|
|
END LOOP;
|
|
END LOOP;
|
|
|
|
-- Logs específicos adicionales
|
|
INSERT INTO audit_logging.user_activity_logs (
|
|
user_id, activity_type, activity_description,
|
|
ip_address, user_agent, session_id,
|
|
dimensions, created_at
|
|
)
|
|
SELECT
|
|
u.user_id,
|
|
'logout',
|
|
'User logged out',
|
|
'192.168.1.45',
|
|
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120.0.0.0',
|
|
gen_random_uuid(),
|
|
'{
|
|
"session_duration_minutes": 45,
|
|
"activities_count": 12,
|
|
"logout_type": "manual"
|
|
}'::jsonb,
|
|
NOW() - INTERVAL '30 minutes'
|
|
FROM auth.users u
|
|
WHERE u.email = 'estudiante1@demo.glit.edu.mx'
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
END $$;
|
|
|
|
-- =====================================================
|
|
-- SUMMARY
|
|
-- =====================================================
|
|
|
|
DO $$
|
|
DECLARE
|
|
metrics_count INT;
|
|
alerts_count INT;
|
|
activity_count INT;
|
|
BEGIN
|
|
SELECT COUNT(*) INTO metrics_count FROM audit_logging.performance_metrics;
|
|
SELECT COUNT(*) INTO alerts_count FROM audit_logging.system_alerts;
|
|
SELECT COUNT(*) INTO activity_count FROM audit_logging.user_activity_logs;
|
|
|
|
RAISE NOTICE 'System metrics seeds completed successfully';
|
|
RAISE NOTICE '- % performance_metrics inserted', metrics_count;
|
|
RAISE NOTICE '- % system_alerts inserted', alerts_count;
|
|
RAISE NOTICE '- % user_activity_logs inserted', activity_count;
|
|
END $$;
|