7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
# File 'lib/profiler/mcp/resources/n1_patterns.rb', line 7
def self.call
profiles = Profiler.storage.list(limit: 100)
pattern_map = Hash.new { |h, k| h[k] = [] }
profiles.each do |profile|
db_data = profile.collector_data("database")
next unless db_data && db_data["queries"]
query_groups = db_data["queries"].group_by { |q| normalize_sql(q["sql"]) }
query_groups.each do |normalized_sql, queries|
pattern_map[normalized_sql] << {
token: profile.token,
path: profile.path,
count: queries.size,
timestamp: profile.started_at&.iso8601,
backtrace: (queries.first["backtrace"] || []).first(3)
}
end
end
n1_patterns = pattern_map.select do |_, occurrences|
occurrences.size > 1 || occurrences.any? { |o| o[:count] > 1 }
end
sorted = n1_patterns.map do |sql, occurrences|
total = occurrences.sum { |o| o[:count] }
sample_backtrace = occurrences.find { |o| o[:backtrace].any? }&.dig(:backtrace) || []
{ sql: sql, total_occurrences: total, backtrace: sample_backtrace, profiles: occurrences }
end.sort_by { |p| -p[:total_occurrences] }.first(20)
{
uri: "profiler://n1-patterns",
mimeType: "application/json",
text: JSON.pretty_generate({
scanned_profiles: profiles.size,
total_patterns: sorted.size,
patterns: sorted
})
}
end
|