194_channel_monitor_v2.sql 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. -- Passive channel monitor V2. This migration creates empty rollup tables only;
  2. -- backfill is intentionally handled by a bounded background worker.
  3. CREATE TABLE IF NOT EXISTS channel_monitor_v2_config (
  4. id SMALLINT PRIMARY KEY DEFAULT 1 CHECK (id = 1),
  5. version INTEGER NOT NULL DEFAULT 1,
  6. enabled BOOLEAN NOT NULL DEFAULT TRUE,
  7. refresh_interval_seconds INTEGER NOT NULL DEFAULT 60
  8. CHECK (refresh_interval_seconds IN (60, 300)),
  9. platforms JSONB NOT NULL DEFAULT '[{"platform":"anthropic","enabled":true,"models":[]},{"platform":"openai","enabled":true,"models":[]},{"platform":"grok","enabled":true,"models":[]},{"platform":"kiro","enabled":true,"models":[]},{"platform":"gemini","enabled":true,"models":[]},{"platform":"antigravity","enabled":true,"models":[]}]'::jsonb,
  10. group_ids BIGINT[] NOT NULL DEFAULT '{}',
  11. updated_by BIGINT,
  12. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  13. );
  14. INSERT INTO channel_monitor_v2_config (id) VALUES (1)
  15. ON CONFLICT (id) DO NOTHING;
  16. CREATE TABLE IF NOT EXISTS channel_monitor_v2_metrics_1m (
  17. bucket_start TIMESTAMPTZ NOT NULL,
  18. platform TEXT NOT NULL,
  19. group_id BIGINT NOT NULL DEFAULT 0,
  20. model TEXT NOT NULL,
  21. success_requests BIGINT NOT NULL DEFAULT 0,
  22. error_requests BIGINT NOT NULL DEFAULT 0,
  23. upstream_affected_requests BIGINT NOT NULL DEFAULT 0,
  24. upstream_attempt_count BIGINT NOT NULL DEFAULT 0,
  25. input_tokens BIGINT NOT NULL DEFAULT 0,
  26. output_tokens BIGINT NOT NULL DEFAULT 0,
  27. cache_creation_tokens BIGINT NOT NULL DEFAULT 0,
  28. cache_read_tokens BIGINT NOT NULL DEFAULT 0,
  29. ttft_sum_ms BIGINT NOT NULL DEFAULT 0,
  30. ttft_count BIGINT NOT NULL DEFAULT 0,
  31. duration_sum_ms BIGINT NOT NULL DEFAULT 0,
  32. duration_count BIGINT NOT NULL DEFAULT 0,
  33. computed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  34. PRIMARY KEY (bucket_start, platform, group_id, model)
  35. );
  36. CREATE INDEX IF NOT EXISTS idx_channel_monitor_v2_metrics_platform_time
  37. ON channel_monitor_v2_metrics_1m (platform, bucket_start DESC);
  38. CREATE INDEX IF NOT EXISTS idx_channel_monitor_v2_metrics_group_time
  39. ON channel_monitor_v2_metrics_1m (group_id, bucket_start DESC);
  40. CREATE INDEX IF NOT EXISTS idx_channel_monitor_v2_metrics_model_time
  41. ON channel_monitor_v2_metrics_1m (model, bucket_start DESC);
  42. CREATE TABLE IF NOT EXISTS channel_monitor_v2_user_metrics_1m (
  43. bucket_start TIMESTAMPTZ NOT NULL,
  44. platform TEXT NOT NULL,
  45. group_id BIGINT NOT NULL DEFAULT 0,
  46. model TEXT NOT NULL,
  47. user_id BIGINT NOT NULL,
  48. success_requests BIGINT NOT NULL DEFAULT 0,
  49. error_requests BIGINT NOT NULL DEFAULT 0,
  50. input_tokens BIGINT NOT NULL DEFAULT 0,
  51. output_tokens BIGINT NOT NULL DEFAULT 0,
  52. cache_creation_tokens BIGINT NOT NULL DEFAULT 0,
  53. cache_read_tokens BIGINT NOT NULL DEFAULT 0,
  54. ttft_sum_ms BIGINT NOT NULL DEFAULT 0,
  55. ttft_count BIGINT NOT NULL DEFAULT 0,
  56. duration_sum_ms BIGINT NOT NULL DEFAULT 0,
  57. duration_count BIGINT NOT NULL DEFAULT 0,
  58. computed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  59. PRIMARY KEY (bucket_start, platform, group_id, model, user_id)
  60. );
  61. CREATE INDEX IF NOT EXISTS idx_channel_monitor_v2_user_metrics_user_time
  62. ON channel_monitor_v2_user_metrics_1m (user_id, bucket_start DESC);
  63. CREATE INDEX IF NOT EXISTS idx_channel_monitor_v2_user_metrics_time
  64. ON channel_monitor_v2_user_metrics_1m (bucket_start DESC);
  65. CREATE TABLE IF NOT EXISTS channel_monitor_v2_error_metrics_1m (
  66. bucket_start TIMESTAMPTZ NOT NULL,
  67. platform TEXT NOT NULL,
  68. group_id BIGINT NOT NULL DEFAULT 0,
  69. model TEXT NOT NULL,
  70. error_category TEXT NOT NULL,
  71. taxonomy_version SMALLINT NOT NULL,
  72. error_requests BIGINT NOT NULL DEFAULT 0,
  73. PRIMARY KEY (bucket_start, platform, group_id, model, error_category, taxonomy_version)
  74. );
  75. CREATE INDEX IF NOT EXISTS idx_channel_monitor_v2_errors_time
  76. ON channel_monitor_v2_error_metrics_1m (bucket_start DESC);
  77. CREATE INDEX IF NOT EXISTS idx_channel_monitor_v2_errors_category_time
  78. ON channel_monitor_v2_error_metrics_1m (error_category, bucket_start DESC);
  79. CREATE TABLE IF NOT EXISTS channel_monitor_v2_latency_histograms_1m (
  80. bucket_start TIMESTAMPTZ NOT NULL,
  81. platform TEXT NOT NULL,
  82. group_id BIGINT NOT NULL DEFAULT 0,
  83. model TEXT NOT NULL,
  84. user_id BIGINT NOT NULL DEFAULT 0,
  85. metric TEXT NOT NULL CHECK (metric IN ('ttft', 'duration')),
  86. upper_bound_ms INTEGER NOT NULL,
  87. sample_count BIGINT NOT NULL DEFAULT 0,
  88. PRIMARY KEY (bucket_start, platform, group_id, model, user_id, metric, upper_bound_ms)
  89. );
  90. CREATE INDEX IF NOT EXISTS idx_channel_monitor_v2_histograms_time
  91. ON channel_monitor_v2_latency_histograms_1m (bucket_start DESC, metric);
  92. CREATE TABLE IF NOT EXISTS channel_monitor_v2_watermarks (
  93. id SMALLINT PRIMARY KEY DEFAULT 1 CHECK (id = 1),
  94. usage_coverage_start TIMESTAMPTZ,
  95. error_coverage_start TIMESTAMPTZ,
  96. data_through TIMESTAMPTZ,
  97. last_successful_at TIMESTAMPTZ,
  98. backfill_cursor TIMESTAMPTZ,
  99. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  100. );
  101. INSERT INTO channel_monitor_v2_watermarks (id) VALUES (1)
  102. ON CONFLICT (id) DO NOTHING;
  103. COMMENT ON TABLE channel_monitor_v2_metrics_1m IS
  104. 'One-minute passive channel health facts derived from real user requests; never from active probes.';
  105. COMMENT ON COLUMN channel_monitor_v2_error_metrics_1m.taxonomy_version IS
  106. 'Version of the ordered error classification rules used for this aggregate.';