QueryInsights.constants.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. export const SUPAMONITOR_EXCLUDED_ROLES = [
  2. 'briven_admin',
  3. 'briven_auth_admin',
  4. 'briven_storage_admin',
  5. 'briven_realtime_admin',
  6. 'pgbouncer',
  7. 'dashboard_user',
  8. ] as const
  9. export const SUPAMONITOR_EXCLUDED_APP_NAMES = ['briven-dashboard', 'mgmt-api'] as const
  10. export const TRANSACTION_CONTROL_REGEX =
  11. /^\s*(BEGIN|COMMIT|ROLLBACK|SET\s|RESET\s|DISCARD|DEALLOCATE|SHOW\s)/i
  12. export const SCHEMA_INTROSPECTION_REGEX =
  13. /\bFROM\s+(?:pg_catalog\.|information_schema\.|pg_class\b|pg_attribute\b|pg_type\b|pg_namespace\b)/i
  14. export const getSupamonitorLogsQuery = (startTime: string, endTime: string) => {
  15. // Validate and canonicalize to ISO 8601 UTC before embedding in SQL.
  16. // new Date().toISOString() throws RangeError on invalid input and always
  17. // produces "YYYY-MM-DDTHH:mm:ss.mmmZ" which contains no SQL special characters.
  18. const safeStart = new Date(startTime).toISOString()
  19. const safeEnd = new Date(endTime).toISOString()
  20. return `
  21. -- This query is run by Briven Query Insights to aggregate pg_stat_statements
  22. -- data collected by the supamonitor extension. It reads from Logflare and groups
  23. -- execution metrics (timing, call counts, percentiles) by query and minute so
  24. -- the dashboard can surface slow queries, high-call patterns, and planning overhead.
  25. -- If you see this query in your logs, it is a read-only analytics query and safe to ignore.
  26. select
  27. TIMESTAMP_TRUNC(sml.timestamp, MINUTE) as timestamp,
  28. CAST(sml_parsed.application_name AS STRING) as application_name,
  29. SUM(sml_parsed.calls) as calls,
  30. CAST(sml_parsed.database_name AS STRING) as database_name,
  31. CAST(sml_parsed.query AS STRING) as query,
  32. sml_parsed.query_id as query_id,
  33. SUM(sml_parsed.total_exec_time) as total_exec_time,
  34. SUM(sml_parsed.total_plan_time) as total_plan_time,
  35. CAST(sml_parsed.user_name AS STRING) as user_name,
  36. CASE WHEN SUM(sml_parsed.calls) > 0
  37. THEN SUM(sml_parsed.total_exec_time) / SUM(sml_parsed.calls)
  38. ELSE 0
  39. END as mean_exec_time,
  40. MIN(NULLIF(sml_parsed.total_exec_time, 0)) as min_exec_time,
  41. MAX(sml_parsed.total_exec_time) as max_exec_time,
  42. CASE WHEN SUM(sml_parsed.calls) > 0
  43. THEN SUM(sml_parsed.total_plan_time) / SUM(sml_parsed.calls)
  44. ELSE 0
  45. END as mean_plan_time,
  46. MIN(NULLIF(sml_parsed.total_plan_time, 0)) as min_plan_time,
  47. MAX(sml_parsed.total_plan_time) as max_plan_time,
  48. APPROX_QUANTILES(sml_parsed.total_exec_time, 100)[OFFSET(50)] as p50_exec_time,
  49. APPROX_QUANTILES(sml_parsed.total_exec_time, 100)[OFFSET(95)] as p95_exec_time,
  50. APPROX_QUANTILES(sml_parsed.total_plan_time, 100)[OFFSET(50)] as p50_plan_time,
  51. APPROX_QUANTILES(sml_parsed.total_plan_time, 100)[OFFSET(95)] as p95_plan_time
  52. from supamonitor_logs as sml
  53. cross join unnest(sml.metadata) as sml_metadata
  54. cross join unnest(sml_metadata.supamonitor) as sml_parsed
  55. WHERE sml.event_message = 'log'
  56. AND sml.timestamp >= CAST('${safeStart}' AS TIMESTAMP)
  57. AND sml.timestamp <= CAST('${safeEnd}' AS TIMESTAMP)
  58. GROUP BY timestamp, user_name, database_name, application_name, query_id, query
  59. ORDER BY timestamp DESC
  60. `.trim()
  61. }