Skip to content

Commit

Permalink
Merge branch 'benchmark'
Browse files Browse the repository at this point in the history
Conflicts:
	lib/rnotifier.rb
  • Loading branch information
Jiren Patel committed Oct 9, 2013
2 parents a398bcc + 5e2b0ec commit b2acec5
Show file tree
Hide file tree
Showing 43 changed files with 869 additions and 297 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*.gem
*.rbc
*.swp
.DS_Store
.bundle
.config
Expand All @@ -19,3 +20,4 @@ tmp
log
config/
*.diff
diff
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ source 'https://rubygems.org'

gem 'simplecov', require: false, group: :test
gem 'coveralls', require: false, group: :test
gem 'debugger', require: false, group: :test
# Specify your gem's dependencies in rnotifier.gemspec
gemspec
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ Or install it yourself as:

environments: development,test #default is production
capture_code: true #default false
api_host: 'http://yourapp.com' #default http://rnotifier.com
ignore_exceptions: ActiveRecord::RecordNotFound,AbstractController::ActionNotFound,ActionController::RoutingError
ignore_bots: Googlebot

Expand All @@ -36,6 +35,15 @@ Or install it yourself as:
rnotifier test #this will send test exception to rnotifier.


### Send exception with request manually
For this ':request' params require

Rnotifier.exception(exception, {:request => request, other_params => 'value'})

### Add context data to exception

Rnotifier.context({user_email: current_user.email})

### Send events and alerts

Rnotifier.event(:sign_up, {:username => 'Jiren', :email => 'jiren@example.com', :using => 'facebook' })
Expand All @@ -53,7 +61,6 @@ i.e
)



## Contributing

1. Fork it
Expand Down
99 changes: 73 additions & 26 deletions bin/rnotifier
Original file line number Diff line number Diff line change
@@ -1,43 +1,90 @@
#!/usr/bin/env ruby

ARGV[0] = 'help' if ARGV.empty?
require 'optparse'

case ARGV[0]
when 'help'
puts %Q{
---- HELP ----
test #Test rnotifier configuration is correct and send test exception.
class RnotofierCLI
attr_accessor :options

install api-key [environments] #Create config/rnotifier.yaml with api_key and enabled for supplied environments.environments are optionbal, default is production.
}
when 'test'
def initialize
@options = {:type => ARGV[0]}
end

def option_parser
@option_parser ||= OptionParser.new do |opts|
opts.banner = "Usage: rnotifier install -k api-key -i app-id [-e environments]"

opts.on('-h', 'Help') do
puts opts
puts 'i.e rnotifier install -k API-KEY -i APP-ID staging,production'
exit
end

opts.on("-k api_key") do |v|
self.options[:api_key] = v
end

opts.on("-i app_id") do |v|
self.options[:app_id] = v
end

opts.on("-e [environments]") do |v|
self.options[:environments] = v if v
end
end
end

def generate
case options[:type]
when 'install'
install
when 'test'
send_test_exception
else
ARGV[0] = '-h'
option_parser.parse!
end
end

def install
option_parser.parse!

if options[:app_id].nil? || options[:api_key].nil?
ARGV[0] = '-h'
option_parser.parse!
end

Dir.mkdir('config') unless Dir.exists?('config')

File.open('config/rnotifier.yaml', 'w') do |f|
f.puts("apikey: '#{options[:api_key]}'\n")
f.puts("app_id: '#{options[:app_id]}'\n")
f.puts("environments: #{options[:environments]}") if options[:environments]
f.puts("capture_code: false")
f.close
end

puts "Rnotofier configuration written in config/rnotifier.yaml"
end

def send_test_exception
#$:.unshift(File.dirname(__FILE__) + '/../lib/')
require 'rack'
require 'rnotifier'
require 'rnotifier/config_test.rb'

ENV['RACK_ENV'] = 'rnotifier_test'

Rnotifier.load_config('config/rnotifier.yaml')
Rnotifier::Config.environments = [ENV['RACK_ENV']]
Rnotifier::Config.init

if Rnotifier::Config.valid?
Rnotifier::ConfigTest.test
else
puts 'Configuration is invalid. Check api key or config'
end
when 'install'
if (api_key = ARGV[1]).nil?
puts "'api-key' is required. Use like i.e rnotifier install api-key [environments]"
else
environments = ARGV[2..-1]
Dir.mkdir('config') unless Dir.exists?('config')

File.open('config/rnotifier.yaml', 'w') do |f|
f.puts("apikey: #{api_key}\n")
f.puts("environments: #{environments.join(', ')}") unless environments.empty?
f.puts("capture_code: false")
f.close
end

puts "Rnotofier configuration written in config/rnotifier.yaml"
puts 'Configuration is invalid. Check config/rnotifier.yaml'
end
end
end

RnotofierCLI.new.generate

20 changes: 0 additions & 20 deletions lib/generators/rnotifier/rnotifier_generator.rb

This file was deleted.

4 changes: 0 additions & 4 deletions lib/generators/rnotifier/templates/initializer.rb

This file was deleted.

41 changes: 30 additions & 11 deletions lib/rnotifier.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
require 'socket'
require 'thread'
require 'yaml'
require 'digest/md5'
require 'multi_json'
require 'json' unless Object.respond_to?(:to_json)
require 'yajl'
require 'faraday'

require 'rnotifier/version'
require 'rnotifier/config'
require 'rnotifier/rlogger'
require 'rnotifier/notifier'
require 'rnotifier/exception_data'
require 'rnotifier/event_data'
require 'rnotifier/message'
require 'rnotifier/rack_middleware'
require 'rnotifier/parameter_filter'
require 'rnotifier/exception_code'
require 'rnotifier/railtie' if defined?(Rails)
require 'rnotifier/benchmark'
require 'rnotifier/benchmark/core_ext'
require 'rnotifier/benchmark/benchmark_proxy'
require 'rnotifier/benchmark/benchmark_view'
require 'rnotifier/rails/benchmark_filters'
require 'rnotifier/message_store'

module Rnotifier

class RnotifierException < Exception; end

class << self
def config(&block)
yield(Rnotifier::Config) if block_given?
Expand All @@ -28,6 +37,7 @@ def load_config(file)

self.config do |c|
c.api_key = config_yaml['apikey']
c.app_id = config_yaml['app_id']

['environments', 'api_host', 'ignore_exceptions', 'ignore_bots', 'capture_code'].each do |f|
c.send("#{f}=", config_yaml[f]) if config_yaml[f]
Expand All @@ -48,19 +58,28 @@ def clear_context
end

def exception(exception, params = {})
Rnotifier::ExceptionData.new(exception, params, {:type => :rescue}).notify
end
request = (params.delete(:request)|| params.delete('request'))

def event(name, params, tags = {})
if Rnotifier::Config.valid? && params.is_a?(Hash)
Rnotifier::EventData.new(name, Rnotifier::EventData::EVENT, params, tags[:tags]).notify
if request
self.context(params)
Rnotifier::ExceptionData.new(exception, request, params.merge(:type => :rack)).notify
else
Rnotifier::ExceptionData.new(exception, params).notify
end
end

def alert(name, params, tags = {})
if Rnotifier::Config.valid? && params.is_a?(Hash)
Rnotifier::EventData.new(name, Rnotifier::EventData::ALERT, params, tags[:tags]).notify
end
raise RnotifierException.new('params must be a Hash') unless params.is_a?(Hash)
Rnotifier::Message.new(name, Rnotifier::Message::ALERT, params, tags[:tags]).notify
end

def event(name, params, tags = {})
raise RnotifierException.new('params must be a Hash') unless params.is_a?(Hash)
Rnotifier::Message.new(name, Rnotifier::Message::EVENT, params, tags[:tags]).enq
end

def benchmark(bm_name, opts = {}, &block)
Rnotifier::Benchmark.it(bm_name, opts, &block)
end

end
Expand Down
48 changes: 48 additions & 0 deletions lib/rnotifier/benchmark.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Rnotifier
class Benchmark

RnotifierException = Class.new(Exception)

BM_FIELDS = [:exception, :args]

def self.it(bm_name, opts = {}, &block)
output = nil
exception = nil

raise RnotifierException.new("Code block require :#{bm_name} for benchmarking.") unless block_given?

t1 = Time.now
begin
output = yield
rescue Exception => e
exception = e
opts[:exception] = {:message => exception.message, :line => exception.backtrace.first}
end

self._collect(bm_name, Time.now - t1, opts)

raise exception if exception
return output
end

def self._collect(bm_name, time, opts)
return if opts[:time_condition] && opts[:time_condition] >= time

data = { :time => time}
BM_FIELDS.each{|f| data[f] = opts[f] if opts[f]}

bm_name = "#{opts[:class]}##{bm_name}" if opts[:class]

Rnotifier::Message.new(bm_name, Rnotifier::Message::BENCHMARK, data).enq
end

def self.web_request(bm_name, time, request_url, opts)
return if opts[:time_condition] && opts[:time_condition] >= time

data = { :time => time, :request_url => request_url, :type => 'web', :b_token => opts[:b_token] }

Rnotifier::Message.new(bm_name, Rnotifier::Message::BENCHMARK, data).enq
end

end
end
22 changes: 22 additions & 0 deletions lib/rnotifier/benchmark/benchmark_proxy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Rnotifier
class BenchmarkProxy < BasicObject

instance_methods.each do |m|
undef_method(m) if m.to_s !~ /(?:^__|^nil\?$|^send$|^object_id$)/
end

RBenchmark = ::Object.const_get('Rnotifier::Benchmark')
Klass = ::Object.const_get('Class')

def initialize(target, opts = {})
@target = target
@opts = opts
end

def method_missing(method, *args, &block)
@opts[:args] = args if @opts[:args]
@opts[:class] = @target.is_a?(Klass) ? @target.name : @target.class.to_s
RBenchmark.it(method, @opts){ @target.send(method, *args, &block) }
end
end
end
16 changes: 16 additions & 0 deletions lib/rnotifier/benchmark/benchmark_view.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Rnotifier
class BenchmarkView
class << self

def browser_token
Digest::MD5.hexdigest("#{Rnotifier::Config.app_id}#{Process.pid}#{Thread.current.object_id}#{Time.now.to_i}")
end

def tag(token)
q = ["b_token=#{token}", "app_id=#{Rnotifier::Config.app_id}"].join("&")
%Q{<script>$.get('#{Rnotifier::Config.api_host}/#{Rnotifier::Config.browser_path}?#{q}&o_at='+(new Date()).getTime())</script>}
end

end
end
end
7 changes: 7 additions & 0 deletions lib/rnotifier/benchmark/core_ext.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module BenchmarkMethods
def benchmark(opts = {})
Rnotifier::BenchmarkProxy.new(self, opts)
end
end

Object.send(:include, BenchmarkMethods)
Loading

0 comments on commit b2acec5

Please sign in to comment.