airbrake_tools 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - ree
3
+ - 1.9.2
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ gem "bump"
5
+ gem "rake"
6
+ gem "rspec", "~>2"
7
+ gem "airbrake-api", ">= 4.2.2"
8
+
data/Gemfile.lock ADDED
@@ -0,0 +1,44 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ airbrake_tools (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ airbrake-api (4.2.2)
10
+ faraday_middleware (~> 0.8)
11
+ hashie
12
+ mash
13
+ multi_xml
14
+ parallel (~> 0.5.0)
15
+ bump (0.3.5)
16
+ diff-lcs (1.1.3)
17
+ faraday (0.8.4)
18
+ multipart-post (~> 1.1)
19
+ faraday_middleware (0.9.0)
20
+ faraday (>= 0.7.4, < 0.9)
21
+ hashie (1.2.0)
22
+ mash (0.1.1)
23
+ multi_xml (0.5.1)
24
+ multipart-post (1.1.5)
25
+ parallel (0.5.19)
26
+ rake (0.9.2.2)
27
+ rspec (2.11.0)
28
+ rspec-core (~> 2.11.0)
29
+ rspec-expectations (~> 2.11.0)
30
+ rspec-mocks (~> 2.11.0)
31
+ rspec-core (2.11.1)
32
+ rspec-expectations (2.11.3)
33
+ diff-lcs (~> 1.1.3)
34
+ rspec-mocks (2.11.3)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ airbrake-api (>= 4.2.2)
41
+ airbrake_tools!
42
+ bump
43
+ rake
44
+ rspec (~> 2)
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "bump/tasks"
3
+
4
+ task :default do
5
+ sh "rspec spec/"
6
+ end
data/Readme.md ADDED
@@ -0,0 +1,18 @@
1
+ Power tools for Airbrake
2
+
3
+ Install
4
+ =======
5
+
6
+ gem install airbrake_tools
7
+
8
+ Usage
9
+ =====
10
+
11
+ CODE EXAMPLE
12
+
13
+ Author
14
+ ======
15
+ [Jonathan Cheatham](http://github.com/jcheatham)<br/>
16
+ coaxis@gmail.com<br/>
17
+ License: MIT<br/>
18
+ [![Build Status](https://travis-ci.org/jcheatham/airbrake_tools.png)](https://travis-ci.org/jcheatham/airbrake_tools)
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+ name = "airbrake_tools"
3
+ require "#{name}/version"
4
+
5
+ Gem::Specification.new name, AirbrakeTools::VERSION do |s|
6
+ s.summary = "Power tools for Airbrake"
7
+ s.authors = ["Jonathan Cheatham"]
8
+ s.email = "coaxis@gmail.com"
9
+ s.homepage = "http://github.com/jcheatham/#{name}"
10
+ s.files = `git ls-files`.split("\n")
11
+ s.license = "MIT"
12
+ end
@@ -0,0 +1,3 @@
1
+ module AirbrakeTools
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,117 @@
1
+ require "airbrake_tools/version"
2
+ require "airbrake-api"
3
+
4
+ module AirbrakeTools
5
+ class << self
6
+ def cli(argv)
7
+ options = extract_options(argv)
8
+
9
+ AirbrakeAPI.account = ARGV[0]
10
+ AirbrakeAPI.auth_token = ARGV[1]
11
+ AirbrakeAPI.secure = true
12
+
13
+ if AirbrakeAPI.account.to_s.empty? || AirbrakeAPI.auth_token.to_s.empty?
14
+ puts "Usage instructions: airbrake-tools --help"
15
+ return 1
16
+ end
17
+
18
+ hot(options) || 0
19
+ end
20
+
21
+ def hot(options)
22
+ puts "Calling hot with #{AirbrakeAPI.account}, #{AirbrakeAPI.auth_token}, #{options.inspect}"
23
+
24
+ pages = 1
25
+
26
+ errors = []
27
+ pages.times do |i|
28
+ errors.concat (AirbrakeAPI.errors(:page => i+1) || []).select{|e| e.rails_env == "production" }
29
+ end
30
+
31
+ errors = Parallel.map(errors, :in_threads => 10) do |error|
32
+ begin
33
+ notices = AirbrakeAPI.notices(error.id, :pages => 1, :raw => true).compact
34
+ print "."
35
+ [error, notices]
36
+ rescue Faraday::Error::ParsingError
37
+ $stderr.puts "Ignoring #{summary(error)}, got 500 from http://#{AirbrakeAPI.account}.airbrake.io/errors/#{error.id}"
38
+ end
39
+ end.compact
40
+
41
+ $stderr.puts
42
+
43
+ errors.sort_by{|e,n| frequency(n) }.reverse.each_with_index do |(error, notices), index|
44
+ puts "##{(index+1).to_s.ljust(2)} #{frequency(notices).to_s.rjust(8)}/hour #{error.notices_count.to_s.rjust(6)}:total #{sparkline(notices, :slots => 60, :interval => 60)}"
45
+ puts " --> id: #{error.id} -- first: #{error.created_at} -- #{error.error_class} -- #{error.error_message}"
46
+ end
47
+
48
+ return 0
49
+ end
50
+
51
+ private
52
+
53
+ def frequency(notices)
54
+ hour = 60 * 60
55
+ sum_of_ages = notices.map { |n| Time.now - n.created_at }.inject(&:+)
56
+ average_age = sum_of_ages / notices.size
57
+ time_to_error = average_age / notices.size
58
+ rate = 1 / time_to_error
59
+ (rate * hour).round(1)
60
+ end
61
+
62
+ def summary(error)
63
+ "id:#{error.id} -- first:#{error.created_at} -- #{error.error_class} -- #{error.error_message}"
64
+ end
65
+
66
+ def extract_options(argv)
67
+ options = {
68
+ }
69
+ OptionParser.new do |opts|
70
+ opts.banner = <<-BANNER.gsub(" "*12, "")
71
+ Get the hotest airbrake errors
72
+
73
+ Usage:
74
+ airbrake-tools subdomain token [options]
75
+ token: go to airbrake -> settings, copy your auth token
76
+
77
+ Options:
78
+ BANNER
79
+ opts.on("-h", "--help", "Show this.") { puts opts; exit }
80
+ opts.on("-v", "--version", "Show Version"){ puts "airbrake-tools #{VERSION}"; exit }
81
+ end.parse!(argv)
82
+ options
83
+ end
84
+
85
+ def run(cmd)
86
+ all = ""
87
+ puts cmd
88
+ IO.popen(cmd) do |pipe|
89
+ while str = pipe.gets
90
+ all << str
91
+ puts str
92
+ end
93
+ end
94
+ [$?.success?, all]
95
+ end
96
+
97
+ def run!(command)
98
+ raise "Command failed #{command}" unless run(command).first
99
+ end
100
+
101
+ def sparkline_data(notices, options)
102
+ last = notices.last.created_at
103
+ now = Time.now
104
+ Array.new(options[:slots]).each_with_index.map do |_, i|
105
+ slot_end = now - (i * options[:interval])
106
+ slot_start = slot_end - 1 * options[:interval]
107
+ next if last > slot_end # do not show empty lines when we actually have no data
108
+ notices.select { |n| n.created_at.between?(slot_start, slot_end) }.size
109
+ end
110
+ end
111
+
112
+ def sparkline(notices, options)
113
+ `#{File.expand_path('../../spark.sh',__FILE__)} #{sparkline_data(notices, options).join(" ")}`.strip
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,52 @@
1
+ require 'yaml'
2
+
3
+ ROOT = File.expand_path('../../', __FILE__)
4
+
5
+ describe "airbrake-tools" do
6
+ def run(command, options={})
7
+ result = `#{command} 2>&1`
8
+ message = (options[:fail] ? "SUCCESS BUT SHOULD FAIL" : "FAIL")
9
+ raise "[#{message}] #{result} [#{command}]" if $?.success? == !!options[:fail]
10
+ result
11
+ end
12
+
13
+ def airbrake_tools(args, options={})
14
+ run "#{ROOT}/bin/airbrake-tools #{args}", options
15
+ end
16
+
17
+ let(:config) { YAML.load(File.read("spec/fixtures.yml")) }
18
+
19
+ before do
20
+ Dir.chdir ROOT
21
+ end
22
+
23
+ describe "basics" do
24
+ it "shows its usage without arguments" do
25
+ airbrake_tools("", :fail => true).should include("Usage")
26
+ end
27
+
28
+ it "shows its usage with -h" do
29
+ airbrake_tools("-h").should include("Usage")
30
+ end
31
+
32
+ it "shows its usage with --help" do
33
+ airbrake_tools("--help").should include("Usage")
34
+ end
35
+
36
+ it "shows its version with -v" do
37
+ airbrake_tools("-v").should =~ /^airbrake-tools \d+\.\d+\.\d+$/
38
+ end
39
+
40
+ it "shows its version with --version" do
41
+ airbrake_tools("-v").should =~ /^airbrake-tools \d+\.\d+\.\d+$/
42
+ end
43
+ end
44
+
45
+ describe "hot" do
46
+ it "kinda works" do
47
+ output = airbrake_tools("#{config["subdomain"]} #{config["auth_token"]}")
48
+ output.should =~ /#\d+\s+\d+\.\d+\/hour\s+\d+:total/
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1 @@
1
+ require "airbrake_tools"
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: airbrake_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jonathan Cheatham
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-07 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email: coaxis@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .travis.yml
21
+ - Gemfile
22
+ - Gemfile.lock
23
+ - Rakefile
24
+ - Readme.md
25
+ - airbrake_tools.gemspec
26
+ - lib/airbrake_tools.rb
27
+ - lib/airbrake_tools/version.rb
28
+ - spec/airbrake_tools_spec.rb
29
+ - spec/spec_helper.rb
30
+ homepage: http://github.com/jcheatham/airbrake_tools
31
+ licenses:
32
+ - MIT
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.23
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Power tools for Airbrake
55
+ test_files: []