Last active
June 12, 2016 17:21
-
-
Save potomak/485a3fcb46f854845cffa0c8a8f95ba9 to your computer and use it in GitHub Desktop.
Collect and show Airbrake errors metrics with Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
require 'open-uri' | |
class AirbrakeFetcher | |
BASE_URL = 'https://airbrake.io' | |
DEFAULT_LIMIT = 100 | |
def initialize(api_key, project_id) | |
@api_key = api_key | |
@project_id = project_id | |
end | |
def fetch_all_groups | |
page = 1 | |
loop do | |
response = fetch_groups(page, DEFAULT_LIMIT) | |
yield response | |
page += 1 | |
break if page > tot_pages(response['count'], DEFAULT_LIMIT) | |
end | |
end | |
# Airbrake API docs: https://airbrake.io/docs/#groups-v4 | |
def fetch_groups(page, limit) | |
response_body = open(groups_url(page, limit)).read | |
JSON.parse(response_body) | |
rescue => err | |
puts "Error trying to fetch page #{page}: #{err}" | |
end | |
private | |
def groups_url(page, limit) | |
url = "#{BASE_URL}/api/v4/projects/#{@project_id}/groups" | |
params = { key: @api_key, page: page, limit: limit } | |
"#{url}?#{query_string(params)}" | |
end | |
def query_string(params) | |
params.to_a.map{ |i| i.join('=') }.join('&') | |
end | |
def tot_pages(count, limit) | |
(count / limit.to_f).ceil | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BarChart | |
MAX_BAR_WIDTH = 60 | |
MAX_LABEL_WIDTH = 40 | |
BAR_CHAR = '*' | |
# Initialize the bar chart with a list of lists of size 2: [label, value] | |
def initialize(data) | |
@data = data | |
end | |
def draw | |
w = label_width | |
t = total_value | |
m = max_value | |
s = scale_factor(m) | |
lines = @data.map do |l, v| | |
"#{draw_label(l, w)} (#{draw_value(v, t, m)}) #{draw_bar(v, s)}" | |
end | |
lines.join("\n") | |
end | |
private | |
def max_value | |
_, max = @data.max_by { |_, v| v } | |
max | |
end | |
def scale_factor(max) | |
MAX_BAR_WIDTH / max.to_f | |
end | |
def longest_label | |
label, _ = @data.max_by { |l, _| l.to_s.size } | |
label | |
end | |
def label_width | |
[longest_label.to_s.size, MAX_LABEL_WIDTH].min | |
end | |
def total_value | |
@data.reduce(0) { |s, (_, v)| s + v } | |
end | |
def draw_value(value, total, max) | |
"#{value}/#{total}".rjust(total.to_s.size + max.to_s.size + 1) | |
end | |
def draw_label(label, width) | |
label.ljust(width).slice(0, width) | |
end | |
def draw_bar(value, scale) | |
BAR_CHAR * (value * scale).round | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require './airbrake_fetcher' | |
require './bar_chart' | |
api_key = 'xxx' | |
project_id = 123 | |
errors_by_type_acc = {} | |
airbrake_fetcher = AirbrakeFetcher.new(api_key, project_id) | |
airbrake_fetcher.fetch_all_groups do |response| | |
# select errors objects | |
errors = response['groups'].map { |g| g['errors'] }.flatten | |
# remove errors without a type | |
errors = errors.select { |e| !e['type'].nil? } | |
# group errors by type | |
errors_by_type = errors.group_by { |e| e['type'] } | |
# accumulate errors number by type | |
errors_by_type_acc = errors_by_type.inject(errors_by_type_acc) do |acc, (t, es)| | |
acc[t] = acc[t].nil? ? es.size : acc[t] + es.size | |
acc | |
end | |
end | |
# sort by descending number of errors | |
errors_by_type_acc = errors_by_type_acc.sort_by { |k, es| es }.reverse | |
puts '---------------------------------' | |
puts 'Errors by type' | |
puts | |
puts BarChart.new(errors_by_type_acc).draw | |
puts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--------------------------------- | |
Errors by type | |
NoMethodError (334/1108) ************************************************************ | |
RuntimeError ( 94/1108) ***************** | |
NameError ( 81/1108) *************** | |
ActiveRecord::RecordInvalid ( 50/1108) ********* | |
ArgumentError ( 43/1108) ******** | |
ActiveRecord::StatementInvalid ( 42/1108) ******** | |
StandardError ( 38/1108) ******* | |
ActionController::RoutingError ( 32/1108) ****** | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment