Module: QueryOwl::Detector
- Defined in:
- lib/query_owl/detector.rb
Constant Summary collapse
- NORMALIZE_PATTERNS =
[ [/'[^']*'/, "?"], [/\b[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}\b/i, "?"], [/\$\d+/, "?"], [/\b\d+\.?\d*\b/, "?"], [/\bIN\s*\(\s*\?(?:\s*,\s*\?)*\s*\)/i, "IN (?)"], [/"([^"]+)"/, '\1'], [/`([^`]+)`/, '\1'], [/\s+/, " "] ].freeze
Class Method Summary collapse
- .detect_n_plus_one(queries) ⇒ Object
- .detect_slow_queries(queries) ⇒ Object
- .detect_unused_eager_loads(eager_data) ⇒ Object
- .normalize(sql) ⇒ Object
Class Method Details
.detect_n_plus_one(queries) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/query_owl/detector.rb', line 15 def detect_n_plus_one(queries) threshold = QueryOwl.config.n_plus_one_threshold queries .reject { |q| q[:cached] } .group_by { |q| normalize(q[:sql]) } .filter_map do |normalized_sql, group| next if group.length < threshold { type: :n_plus_one, sql: normalized_sql, count: group.length, backtrace: group.first[:backtrace] } end end |
.detect_slow_queries(queries) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/query_owl/detector.rb', line 33 def detect_slow_queries(queries) threshold = QueryOwl.config.slow_query_threshold_ms queries.filter_map do |q| next if q[:cached] next if q[:duration_ms] < threshold { type: :slow_query, sql: normalize(q[:sql]), duration_ms: q[:duration_ms], backtrace: q[:backtrace] } end end |
.detect_unused_eager_loads(eager_data) ⇒ Object
49 50 51 52 53 54 55 56 57 |
# File 'lib/query_owl/detector.rb', line 49 def detect_unused_eager_loads(eager_data) preloaded = eager_data[:preloaded] || [] accessed = eager_data[:accessed] || Set.new preloaded .uniq { |e| "#{e[:model]}##{e[:association]}" } .reject { |e| accessed.include?("#{e[:model]}##{e[:association]}") } .map { |e| { type: :unused_eager_load, model: e[:model], association: e[:association] } } end |
.normalize(sql) ⇒ Object
59 60 61 62 63 |
# File 'lib/query_owl/detector.rb', line 59 def normalize(sql) NORMALIZE_PATTERNS .reduce(sql.to_s) { |s, (pattern, replacement)| s.gsub(pattern, replacement) } .strip end |