appygram-rails 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/appygram.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/appygram/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = %q{appygram-rails}
6
+ gem.version = Appygram::VERSION
7
+ gem.authors = ["rfc2616"]
8
+ gem.summary = %q{ appygram is a hosted service for sending messages from mobile/web apps }
9
+ gem.description = %q{Appygram is the Ruby gem for communicating with http://appygram.com (hosted messaging service). It supports an exception reporting mechanism similar to http://exceptional.io, and this Ruby gem, forked from the Exceptional gem, emulates Exceptional functionality.}
10
+ gem.email = %q{heittman.rob@gmail.com}
11
+ gem.files = Dir['lib/**/*'] + Dir['spec/**/*'] + Dir['spec/**/*'] + Dir['rails/**/*'] + Dir['tasks/**/*'] + Dir['*.rb'] + ["appygram.gemspec"]
12
+ gem.homepage = %q{http://appygram.com/}
13
+ gem.require_paths = ["lib"]
14
+ gem.requirements << "json_pure, json-jruby or json gem required"
15
+ gem.add_dependency 'rack'
16
+ end
data/init.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'appygram'
2
+
3
+ # If old plugin still installed then we don't want to install this one.
4
+ # In production environments we should continue to work as before, but in development/test we should
5
+ # advise how to correct the problem and exit
6
+ if (defined?(Appygram::VERSION::STRING) rescue nil) && %w(development test).include?(RAILS_ENV)
7
+ message = %Q(
8
+ ***********************************************************************
9
+ You seem to still have an old version of the Appygram plugin installed.
10
+ Remove it from /vendor/plugins and try again.
11
+ ***********************************************************************
12
+ )
13
+ puts message
14
+ exit -1
15
+ else
16
+ begin
17
+
18
+ if (Rails::VERSION::MAJOR < 3)
19
+ Appygram::Config.load(File.join(RAILS_ROOT, "/config/Appygram.yml"))
20
+ if Appygram::Config.should_send_to_api?
21
+ Appygram.logger.info("Loading Appygram #{Appygram::VERSION} for #{Rails::VERSION::STRING}")
22
+ require File.join('Appygram', 'integration', 'rails')
23
+ require File.join('Appygram', 'integration', 'dj') if defined?(Delayed::Job)
24
+ end
25
+ else
26
+ Appygram::Config.load(File.join(Rails.root, "/config/Appygram.yml"))
27
+
28
+ if Appygram::Config.should_send_to_api?
29
+ Appygram.logger.info("Loading Appygram #{Appygram::VERSION} for #{Rails::VERSION::STRING}")
30
+ Rails.configuration.middleware.use "Rack::RailsAppygram"
31
+ require File.join('Appygram', 'integration', 'dj') if defined?(Delayed::Job)
32
+ end
33
+ end
34
+ rescue => e
35
+ STDERR.puts "Problem starting Appygram Plugin. Your app will run as normal. #{e.message}"
36
+ Appygram.logger.error(e.message)
37
+ Appygram.logger.error(e.backtrace)
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module Appygram
2
+ class AlertData < ExceptionData
3
+ # Overwrite backtrace, since it is irrelevant
4
+ def extra_data
5
+ {
6
+ 'exception' => {
7
+ 'exception_class' => @exception.class.to_s,
8
+ 'message' => @exception.message,
9
+ 'backtrace' => "",
10
+ 'occurred_at' => Time.now
11
+ }
12
+ }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ require 'digest/md5'
2
+
3
+ module Appygram
4
+ class ApplicationEnvironment
5
+ def self.to_hash(framework)
6
+ {
7
+ 'client' => {
8
+ 'name' => Appygram::CLIENT_NAME,
9
+ 'version' => Appygram::VERSION,
10
+ 'protocol_version' => Appygram::PROTOCOL_VERSION
11
+ },
12
+ 'application_environment' => {
13
+ 'host' => get_hostname,
14
+ 'run_as_user' => get_username,
15
+ 'application_root_directory' => (application_root.to_s.respond_to?(:force_encoding) ? application_root.to_s.force_encoding("UTF-8") : application_root),
16
+ 'language' => 'ruby',
17
+ 'language_version' => language_version_string,
18
+ 'framework' => framework,
19
+ 'libraries_loaded' => libraries_loaded
20
+ }
21
+ }
22
+ end
23
+
24
+ def self.environment
25
+ Config.application_environment
26
+ end
27
+
28
+ def self.application_root
29
+ Config.application_root
30
+ end
31
+
32
+ def self.get_hostname
33
+ require 'socket' unless defined?(Socket)
34
+ Socket.gethostname
35
+ rescue
36
+ 'UNKNOWN'
37
+ end
38
+
39
+ def self.language_version_string
40
+ "#{RUBY_VERSION rescue '?.?.?'} p#{RUBY_PATCHLEVEL rescue '???'} #{RUBY_RELEASE_DATE rescue '????-??-??'} #{RUBY_PLATFORM rescue '????'}"
41
+ end
42
+
43
+ def self.get_username
44
+ ENV['LOGNAME'] || ENV['USER'] || ENV['USERNAME'] || ENV['APACHE_RUN_USER'] || 'UNKNOWN'
45
+ end
46
+
47
+ def self.libraries_loaded
48
+ begin
49
+ return Hash[*Gem.loaded_specs.map{|name, gem_specification| [name, gem_specification.version.to_s]}.flatten]
50
+ rescue
51
+ end
52
+ {}
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ module Appygram
2
+ class Catcher
3
+ class << self
4
+ def handle_with_controller(exception, controller=nil, request=nil)
5
+ if Config.should_send_to_api?
6
+ data = ControllerExceptionData.new(exception, controller, request)
7
+ Remote.error(data)
8
+ else
9
+ raise exception
10
+ end
11
+ end
12
+
13
+ # unspeced
14
+ def handle_with_rack(exception, environment, request)
15
+ if Config.should_send_to_api?
16
+ data = RackExceptionData.new(exception, environment, request)
17
+ Remote.error(data)
18
+ else
19
+ raise exception
20
+ end
21
+ end
22
+
23
+ # unspeced
24
+ def handle(exception, name=nil)
25
+ if Config.should_send_to_api?
26
+ data = ExceptionData.new(exception, name)
27
+ Remote.error(data)
28
+ else
29
+ raise exception
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,63 @@
1
+ require 'yaml'
2
+
3
+ module Appygram
4
+ class Config
5
+ class ConfigurationException < StandardError; end
6
+
7
+ class << self
8
+ DEFAULTS = {
9
+ :ssl => false,
10
+ :remote_host_http => 'api.appygram.com',
11
+ :http_open_timeout => 2,
12
+ :http_read_timeout => 4,
13
+ :disabled_by_default => %w(development test)
14
+ }
15
+
16
+ attr_accessor :api_key, :enabled
17
+ attr_accessor :http_proxy_host, :http_proxy_port, :http_proxy_username, :http_proxy_password
18
+ attr_writer :ssl
19
+
20
+ def api_key
21
+ return @api_key unless @api_key.nil?
22
+ @api_key ||= ENV['EXCEPTIONAL_API_KEY'] unless ENV['EXCEPTIONAL_API_KEY'].nil?
23
+ end
24
+
25
+ def application_environment
26
+ ENV['RACK_ENV'] || ENV['RAILS_ENV']|| 'development'
27
+ end
28
+
29
+ def should_send_to_api?
30
+ return @enabled unless @enabled.nil?
31
+ @enabled = !(DEFAULTS[:disabled_by_default].include?(application_environment))
32
+ end
33
+
34
+ def application_root
35
+ (defined?(Rails) && Rails.respond_to?(:root)) ? Rails.root : Dir.pwd
36
+ end
37
+
38
+ def ssl?
39
+ @ssl ||= DEFAULTS[:ssl]
40
+ end
41
+
42
+ def remote_host
43
+ @remote_host ||= DEFAULTS[:remote_host_http]
44
+ end
45
+
46
+ def remote_port
47
+ @remote_port ||= ssl? ? 443 : 80
48
+ end
49
+
50
+ def reset
51
+ @enabled = @ssl = @remote_host = @remote_port = @api_key = nil
52
+ end
53
+
54
+ def http_open_timeout
55
+ @http_open_timeout ||= DEFAULTS[:http_open_timeout]
56
+ end
57
+
58
+ def http_read_timeout
59
+ @http_read_timeout ||= DEFAULTS[:http_read_timeout]
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,75 @@
1
+ require 'digest/md5'
2
+
3
+ module Appygram
4
+ class ControllerExceptionData < ExceptionData
5
+ def initialize(exception, controller=nil, request=nil)
6
+ super(exception)
7
+ @request = request
8
+ @controller = controller
9
+ end
10
+
11
+ def framework
12
+ "rails"
13
+ end
14
+
15
+ def extra_stuff
16
+ return {} if @request.nil?
17
+ e = {
18
+ 'request' => {
19
+ 'url' => (@request.respond_to?(:url) ? @request.url : "#{@request.protocol}#{@request.host}#{@request.request_uri}"),
20
+ 'controller' => @controller.class.to_s,
21
+ 'action' => (@request.respond_to?(:parameters) ? @request.parameters['action'] : @request.params['action']),
22
+ 'parameters' => filter_parameters(@request.respond_to?(:parameters) ? @request.parameters : @request.params),
23
+ 'request_method' => @request.request_method.to_s,
24
+ 'remote_ip' => (@request.respond_to?(:remote_ip) ? @request.remote_ip : @request.ip),
25
+ 'headers' => extract_http_headers(@request.env),
26
+ 'session' => self.class.sanitize_session(@request)
27
+ }
28
+ }
29
+ if @controller.respond_to?(:current_user)
30
+ cu = @controller.current_user
31
+ if cu and cu.email
32
+ e['request']['current_user'] = {
33
+ 'id' => cu.id,
34
+ 'email'=> cu.email
35
+ }
36
+ end
37
+ end
38
+ return e
39
+ end
40
+
41
+ def filter_hash(keys_to_filter, hash)
42
+ keys_to_filter.map! {|x| x.to_s}
43
+ if keys_to_filter.is_a?(Array) && !keys_to_filter.empty?
44
+ hash.each do |key, value|
45
+ if key_match?(key, keys_to_filter)
46
+ hash[key] = "[FILTERED]"
47
+ elsif value.respond_to?(:to_hash)
48
+ filter_hash(keys_to_filter, hash[key])
49
+ end
50
+ end
51
+ end
52
+ hash
53
+ end
54
+
55
+ # Closer alignment to latest filtered_params:
56
+ # https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/parameter_filter.rb
57
+ # https://github.com/exceptional/exceptional/issues/20
58
+ def key_match?(key, keys_to_filter)
59
+ keys_to_filter.any? { |k|
60
+ regexp = k.is_a?(Regexp)? k : Regexp.new(k, true)
61
+ key =~ regexp
62
+ }
63
+ end
64
+
65
+ def filter_parameters(hash)
66
+ if @request.respond_to?(:env) && @request.env["action_dispatch.parameter_filter"]
67
+ filter_hash(@request.env["action_dispatch.parameter_filter"], hash)
68
+ elsif @controller.respond_to?(:filter_parameters)
69
+ @controller.send(:filter_parameters, hash)
70
+ else
71
+ hash
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,108 @@
1
+ require 'digest/md5'
2
+ require 'time'
3
+
4
+ module Appygram
5
+ class ExceptionData
6
+
7
+ def initialize(exception, name=nil)
8
+ @exception = exception
9
+ @name = name
10
+ end
11
+
12
+ def to_hash
13
+ hash = ::Appygram::ApplicationEnvironment.to_hash(framework)
14
+ hash.merge!({
15
+ 'exception' => {
16
+ 'exception_class' => @exception.class.to_s,
17
+ 'message' => @exception.message,
18
+ 'backtrace' => @exception.backtrace,
19
+ 'occurred_at' => Time.now.utc.iso8601
20
+ }
21
+ })
22
+ hash.merge!(extra_stuff)
23
+ hash.merge!(context_stuff)
24
+ self.class.sanitize_hash(hash)
25
+ end
26
+
27
+ def extra_stuff
28
+ { 'rescue_block' => { 'name' => @name} }
29
+ end
30
+
31
+ def context_stuff
32
+ context = Thread.current[:appygram_context]
33
+ (context.nil? || context.empty?) ? {} : {'context' => context}
34
+ end
35
+
36
+ def to_json
37
+ begin
38
+ to_hash.to_json
39
+ rescue NoMethodError
40
+ begin
41
+ require 'json'
42
+ return to_hash.to_json
43
+ rescue StandardError => e
44
+ Appygram.logger.error(e.message)
45
+ Appygram.logger.error(e.backtrace)
46
+ raise StandardError.new("You need a json gem/library installed to send errors to Appygram (Object.to_json not defined). \nInstall json_pure, yajl-ruby, json-jruby, or the c-based json gem")
47
+ end
48
+ end
49
+ end
50
+
51
+ def framework
52
+ nil
53
+ end
54
+
55
+ def uniqueness_hash
56
+ return nil if (@exception.backtrace.nil? || @exception.backtrace.empty?)
57
+ Digest::MD5.hexdigest(@exception.backtrace.join)
58
+ end
59
+
60
+ def self.sanitize_hash(hash)
61
+
62
+ case hash
63
+ when Hash
64
+ hash.inject({}) do |result, (key, value)|
65
+ result.update(key => sanitize_hash(value))
66
+ end
67
+ when Array
68
+ hash.collect{|value| sanitize_hash(value)}
69
+ when Fixnum, String, Bignum
70
+ hash
71
+ else
72
+ hash.to_s
73
+ end
74
+ rescue Exception => e
75
+ Appygram.logger.error(hash)
76
+ Appygram.logger.error(e.message)
77
+ Appygram.logger.error(e.backtrace)
78
+ {}
79
+ end
80
+
81
+ def extract_http_headers(env)
82
+ headers = {}
83
+ env.select{|k, v| k =~ /^HTTP_/}.each do |name, value|
84
+ proper_name = name.sub(/^HTTP_/, '').split('_').map{|upper_case| upper_case.capitalize}.join('-')
85
+ headers[proper_name] = value
86
+ end
87
+ unless headers['Cookie'].nil?
88
+ headers['Cookie'] = headers['Cookie'].sub(/_session=\S+/, '_session=[FILTERED]')
89
+ end
90
+ headers
91
+ end
92
+
93
+ def self.sanitize_session(request)
94
+ session_hash = {'session_id' => "", 'data' => {}}
95
+
96
+ if request.respond_to?(:session)
97
+ session = request.session
98
+ session_hash['session_id'] = request.session_options ? request.session_options[:id] : nil
99
+ session_hash['session_id'] ||= session.respond_to?(:session_id) ? session.session_id : session.instance_variable_get("@session_id")
100
+ session_hash['data'] = session.respond_to?(:to_hash) ? session.to_hash : session.instance_variable_get("@data") || {}
101
+ session_hash['session_id'] ||= session_hash['data'][:session_id]
102
+ session_hash['data'].delete(:session_id)
103
+ end
104
+
105
+ self.sanitize_hash(session_hash)
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,11 @@
1
+ module Appygram
2
+ class Alert <StandardError;
3
+ end
4
+
5
+ module Integration
6
+ def self.alert(msg, env={})
7
+ return Appygram::Remote.error(Appygram::AlertData.new(Alert.new(msg), "Alert"))
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,16 @@
1
+ module Appygram
2
+ module DebugExceptions
3
+
4
+ def self.included(base)
5
+ base.send(:alias_method_chain,:render_exception,:appygram)
6
+ end
7
+
8
+ def render_exception_with_appygram(env,exception)
9
+ ::Appygram::Catcher.handle_with_controller(exception,
10
+ env['action_controller.instance'],
11
+ Rack::Request.new(env))
12
+ render_exception_without_appygram(env,exception)
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'rack'
3
+
4
+ module Rack
5
+ class Appygram
6
+
7
+ def initialize(app, api_key = nil)
8
+ @app = app
9
+ if api_key.nil?
10
+ appygram_config = "config/appygram.yml"
11
+ ::Appygram::Config.load(appygram_config)
12
+ else
13
+ ::Appygram.configure(api_key)
14
+ ::Appygram::Config.enabled = true
15
+ ::Appygram.logger.info "Enabling Appygram for Rack"
16
+ end
17
+ end
18
+
19
+ def call(env)
20
+ begin
21
+ status, headers, body = @app.call(env)
22
+ rescue Exception => e
23
+ ::Appygram::Catcher.handle_with_rack(e,env, Rack::Request.new(env))
24
+ raise(e)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'rack'
3
+
4
+ module Rack
5
+ class RailsAppygram
6
+
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ begin
13
+ body = @app.call(env)
14
+ rescue Exception => e
15
+ ::Appygram::Catcher.handle_with_controller(e,env['action_controller.instance'], Rack::Request.new(env))
16
+ raise
17
+ end
18
+
19
+ if env['rack.exception']
20
+ ::Appygram::Catcher.handle_with_controller(env['rack.exception'],env['action_controller.instance'], Rack::Request.new(env))
21
+ end
22
+
23
+ body
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ require 'logger'
2
+
3
+ module Appygram
4
+ class LogFactory
5
+ def self.logger
6
+ @logger ||= create_logger_with_fallback
7
+ end
8
+
9
+ private
10
+ def self.create_logger_with_fallback
11
+ begin
12
+ log_dir = File.join(Config.application_root, 'log')
13
+ Dir.mkdir(log_dir) unless File.directory?(log_dir)
14
+ log_path = File.join(log_dir, "/appygram.log")
15
+ log = Logger.new(log_path)
16
+ log.level = Logger::INFO
17
+ def log.format_message(severity, timestamp, progname, msg)
18
+ "[#{severity.upcase}] (#{[Kernel.caller[2].split('/').last]}) #{timestamp.utc.to_s} - #{msg2str(msg).gsub(/\n/, '').lstrip}\n"
19
+ end
20
+ def log.msg2str(msg)
21
+ case msg
22
+ when ::String
23
+ msg
24
+ when ::Exception
25
+ "#{ msg.message } (#{ msg.class }): " <<
26
+ (msg.backtrace || []).join(" | ")
27
+ else
28
+ msg.inspect
29
+ end
30
+ end
31
+ log
32
+ rescue
33
+ return Rails.logger if defined?(Rails) && defined?(Rails.logger)
34
+ return RAILS_DEFAULT_LOGGER if defined?(RAILS_DEFAULT_LOGGER)
35
+ return Logger.new(STDERR)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,10 @@
1
+ class Regexp
2
+ def to_json(options = {})
3
+ "\"#{self.to_s}\""
4
+ end
5
+ end
6
+ class Fixnum
7
+ def to_json(options = {})
8
+ to_s
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ require 'digest/md5'
2
+
3
+ module Appygram
4
+ class RackExceptionData < ExceptionData
5
+ def initialize(exception, environment, request)
6
+ super(exception)
7
+ @environment = environment
8
+ @request = request
9
+ end
10
+
11
+ def framework
12
+ "rack"
13
+ end
14
+
15
+ def extra_stuff
16
+ return {} if @request.nil?
17
+ {
18
+ 'request' => {
19
+ 'url' => "#{@request.url}",
20
+ 'parameters' => @request.params,
21
+ 'request_method' => @request.request_method.to_s,
22
+ 'remote_ip' => @request.ip,
23
+ 'headers' => extract_http_headers(@environment),
24
+ 'session' => self.class.sanitize_session(@request)
25
+ }
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ require 'appygram'
2
+ require 'rails'
3
+
4
+ module Appygram
5
+ class Railtie < Rails::Railtie
6
+
7
+ initializer "appygram.middleware" do |app|
8
+
9
+ if Appygram::Config.should_send_to_api?
10
+ Appygram.logger.info("Loading Appygram #{Appygram::VERSION} for #{Rails::VERSION::STRING}")
11
+ if defined?(ActionDispatch::DebugExceptions)
12
+ ActionDispatch::DebugExceptions.send(:include,Appygram::DebugExceptions)
13
+ else
14
+ app.config.middleware.use "Rack::RailsAppygram"
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,48 @@
1
+ require 'zlib'
2
+ require 'cgi'
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'digest/md5'
6
+
7
+ module Appygram
8
+ class Remote
9
+ class << self
10
+ def startup_announce(startup_data)
11
+ #FIXME this is a noop based on an Exceptional behavior Appygram doesn't have
12
+ Appygram.logger.info 'Appygram remote exception forwarding started'
13
+ end
14
+
15
+ def error(exception_data)
16
+ url = "/api/exceptions?api_key=#{::Appygram::Config.api_key}"
17
+ call_remote(url, exception_data.to_json)
18
+ end
19
+
20
+ def call_remote(url, data)
21
+ config = Appygram::Config
22
+ optional_proxy = Net::HTTP::Proxy(config.http_proxy_host,
23
+ config.http_proxy_port,
24
+ config.http_proxy_username,
25
+ config.http_proxy_password)
26
+ client = optional_proxy.new(config.remote_host, config.remote_port)
27
+ client.open_timeout = config.http_open_timeout
28
+ client.read_timeout = config.http_read_timeout
29
+ client.use_ssl = config.ssl?
30
+ client.verify_mode = OpenSSL::SSL::VERIFY_NONE if config.ssl?
31
+ begin
32
+ response = client.post(url, data)
33
+ case response
34
+ when Net::HTTPSuccess
35
+ Appygram.logger.info( "#{url} - #{response.message}")
36
+ return true
37
+ else
38
+ Appygram.logger.error("#{url} - #{response.code} - #{response.message}")
39
+ end
40
+ rescue Exception => e
41
+ Appygram.logger.error('Problem notifying Appygram about the error')
42
+ Appygram.logger.error(e)
43
+ end
44
+ nil
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,14 @@
1
+ module Appygram
2
+ class StartupException < StandardError;
3
+ end
4
+ class Startup
5
+ class << self
6
+ def announce
7
+ if Config.api_key.blank?
8
+ raise StartupException, 'API Key must be configured'
9
+ end
10
+ Remote.startup_announce(::Appygram::ApplicationEnvironment.to_hash('rails'))
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module Appygram
2
+ VERSION = '0.9.1'
3
+ end
data/lib/appygram.rb ADDED
@@ -0,0 +1,71 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'appygram/monkeypatches'
4
+ require 'appygram/catcher'
5
+ require 'appygram/startup'
6
+ require 'appygram/log_factory'
7
+ require 'appygram/config'
8
+ require 'appygram/application_environment'
9
+ require 'appygram/exception_data'
10
+ require 'appygram/controller_exception_data'
11
+ require 'appygram/rack_exception_data'
12
+ require 'appygram/alert_data'
13
+ require 'appygram/remote'
14
+ require 'appygram/integration/rack'
15
+ require 'appygram/integration/rack_rails'
16
+ require 'appygram/integration/alerter'
17
+ require 'appygram/version'
18
+ require 'appygram/integration/debug_exceptions'
19
+
20
+ require 'appygram/railtie' if defined?(Rails::Railtie)
21
+
22
+ module Appygram
23
+ PROTOCOL_VERSION = 5
24
+ CLIENT_NAME = 'appygram-rails'
25
+ ENVIRONMENT_FILTER = []
26
+
27
+ def self.logger
28
+ ::Appygram::LogFactory.logger
29
+ end
30
+
31
+ def self.configure(api_key)
32
+ Appygram::Config.api_key = api_key
33
+ end
34
+
35
+ def self.handle(exception, name=nil)
36
+ Appygram::Catcher.handle(exception, name)
37
+ end
38
+
39
+ def self.rescue(name=nil, context=nil, &block)
40
+ begin
41
+ self.context(context) unless context.nil?
42
+ block.call
43
+ rescue Exception => e
44
+ Appygram::Catcher.handle(e,name)
45
+ ensure
46
+ self.clear!
47
+ end
48
+ end
49
+
50
+ def self.rescue_and_reraise(name=nil, context=nil, &block)
51
+ begin
52
+ self.context(context) unless context.nil?
53
+ block.call
54
+ rescue Exception => e
55
+ Appygram::Catcher.handle(e,name)
56
+ raise(e)
57
+ ensure
58
+ self.clear!
59
+ end
60
+ end
61
+
62
+ def self.clear!
63
+ Thread.current[:appygram_context] = nil
64
+ end
65
+
66
+ def self.context(hash = {})
67
+ Thread.current[:appygram_context] ||= {}
68
+ Thread.current[:appygram_context].merge!(hash)
69
+ self
70
+ end
71
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__) , '../init.rb')
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: appygram-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - rfc2616
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: &70216562368600 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70216562368600
25
+ description: Appygram is the Ruby gem for communicating with http://appygram.com (hosted
26
+ messaging service). It supports an exception reporting mechanism similar to http://exceptional.io,
27
+ and this Ruby gem, forked from the Exceptional gem, emulates Exceptional functionality.
28
+ email: heittman.rob@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/appygram/alert_data.rb
34
+ - lib/appygram/application_environment.rb
35
+ - lib/appygram/catcher.rb
36
+ - lib/appygram/config.rb
37
+ - lib/appygram/controller_exception_data.rb
38
+ - lib/appygram/exception_data.rb
39
+ - lib/appygram/integration/alerter.rb
40
+ - lib/appygram/integration/debug_exceptions.rb
41
+ - lib/appygram/integration/rack.rb
42
+ - lib/appygram/integration/rack_rails.rb
43
+ - lib/appygram/log_factory.rb
44
+ - lib/appygram/monkeypatches.rb
45
+ - lib/appygram/rack_exception_data.rb
46
+ - lib/appygram/railtie.rb
47
+ - lib/appygram/remote.rb
48
+ - lib/appygram/startup.rb
49
+ - lib/appygram/version.rb
50
+ - lib/appygram.rb
51
+ - rails/init.rb
52
+ - init.rb
53
+ - appygram.gemspec
54
+ homepage: http://appygram.com/
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements:
73
+ - json_pure, json-jruby or json gem required
74
+ rubyforge_project:
75
+ rubygems_version: 1.8.17
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: appygram is a hosted service for sending messages from mobile/web apps
79
+ test_files: []
80
+ has_rdoc: