-- Ad-hoc analytics queries against query_log_insights. -- All queries default to the last 30 days; adjust the interval as needed. -- ─── 1. Cache hit ratio (db / redis_positive / redis_negative / lock_wait / miss) ─── SELECT cache_source, count(*) AS queries, round(100.0 * count(*) / sum(count(*)) OVER (), 1) AS pct, round(avg(response_time_ms)) AS avg_ms, percentile_cont(0.95) WITHIN GROUP (ORDER BY response_time_ms)::int AS p95_ms FROM query_log_insights WHERE created_at > now() - interval '30 days' GROUP BY cache_source ORDER BY queries DESC; -- ─── 2. Per-source latency & success ───────────────────────────────────────────── SELECT source, count(*) AS queries, round(100.0 * sum((success)::int) / count(*), 1) AS success_pct, round(avg(response_time_ms)) AS avg_ms, percentile_cont(0.50) WITHIN GROUP (ORDER BY response_time_ms)::int AS p50_ms, percentile_cont(0.95) WITHIN GROUP (ORDER BY response_time_ms)::int AS p95_ms, percentile_cont(0.99) WITHIN GROUP (ORDER BY response_time_ms)::int AS p99_ms, max(response_time_ms) AS max_ms FROM query_log_insights WHERE created_at > now() - interval '30 days' AND cache_source = 'miss' -- exclude cache hits for a fair upstream comparison GROUP BY source ORDER BY queries DESC; -- ─── 3. Slowest WMIs (which brand prefixes hurt us most) ───────────────────────── SELECT wmi, count(*) AS queries, round(avg(response_time_ms)) AS avg_ms, percentile_cont(0.95) WITHIN GROUP (ORDER BY response_time_ms)::int AS p95_ms, round(100.0 * sum((NOT success)::int) / count(*), 1) AS fail_pct FROM query_log_insights WHERE created_at > now() - interval '30 days' AND cache_source = 'miss' GROUP BY wmi HAVING count(*) >= 3 ORDER BY p95_ms DESC LIMIT 20; -- ─── 4. Per-stage breakdown when an upstream is to blame ───────────────────────── SELECT source, count(*) AS queries, round(avg(pcat_ms)) AS avg_pcat_ms, round(avg(emex_ms)) AS avg_emex_ms, round(avg(pl24_ms)) AS avg_pl24_ms, round(avg(vin_api_ms)) AS avg_vin_api_ms, round(avg(lock_wait_ms)) AS avg_lock_wait_ms FROM query_log_insights WHERE created_at > now() - interval '7 days' AND cache_source = 'miss' GROUP BY source ORDER BY queries DESC; -- ─── 5. Circuit breaker / abort frequency ──────────────────────────────────────── SELECT date_trunc('hour', created_at) AS hour, count(*) FILTER (WHERE pl24_circuit_open) AS cb_open_when_called, count(*) FILTER (WHERE pl24_skipped) AS pl24_skipped_count, count(*) FILTER (WHERE aborted) AS aborted_count, count(*) AS total FROM query_log_insights WHERE created_at > now() - interval '24 hours' GROUP BY hour ORDER BY hour DESC LIMIT 24; -- ─── 6. Candidate-modal rate (how often does the user have to disambiguate?) ───── SELECT result_kind, count(*) AS queries, round(100.0 * count(*) / sum(count(*)) OVER (), 1) AS pct FROM query_log_insights WHERE created_at > now() - interval '30 days' GROUP BY result_kind ORDER BY queries DESC; -- ─── 7. Top failing VINs (cluster of retries / unsupported VINs) ───────────────── SELECT vin, wmi, count(*) AS attempts, count(*) FILTER (WHERE success) AS ok, count(*) FILTER (WHERE NOT success) AS fail, max(response_time_ms) AS worst_ms, max(created_at) AS last_seen FROM query_log_insights WHERE created_at > now() - interval '30 days' GROUP BY vin, wmi HAVING count(*) FILTER (WHERE NOT success) >= 2 ORDER BY fail DESC, attempts DESC LIMIT 30; -- ─── 8. Dedup effectiveness (lock_wait shows how many requests piggy-backed) ───── SELECT date_trunc('day', created_at) AS day, count(*) FILTER (WHERE cache_source = 'lock_wait') AS dedup_savings, count(*) FILTER (WHERE cache_source = 'miss') AS actual_decodes, count(*) FILTER (WHERE cache_source = 'redis_positive') AS redis_hits, count(*) FILTER (WHERE cache_source = 'redis_negative') AS redis_neg_hits, count(*) FILTER (WHERE cache_source = 'db_hit') AS db_hits, count(*) AS total FROM query_log_insights WHERE created_at > now() - interval '14 days' GROUP BY day ORDER BY day DESC;