influxdb-rails 0.0.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.
Files changed (45) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +95 -0
  4. data/README.md +3 -0
  5. data/Rakefile +34 -0
  6. data/config.ru +7 -0
  7. data/gemfiles/Gemfile.rails-3.0.x +8 -0
  8. data/gemfiles/Gemfile.rails-3.0.x.lock +94 -0
  9. data/gemfiles/Gemfile.rails-3.1.x +8 -0
  10. data/gemfiles/Gemfile.rails-3.1.x.lock +121 -0
  11. data/gemfiles/Gemfile.rails-3.2.x +8 -0
  12. data/gemfiles/Gemfile.rails-3.2.x.lock +104 -0
  13. data/gemfiles/Gemfile.rails-4.0.x +8 -0
  14. data/gemfiles/Gemfile.rails-4.0.x.lock +109 -0
  15. data/generators/influxdb/influxdb_generator.rb +48 -0
  16. data/generators/influxdb/templates/initializer.rb +5 -0
  17. data/influxdb-rails.gemspec +33 -0
  18. data/lib/influxdb-rails.rb +82 -0
  19. data/lib/influxdb/rails/air_traffic_controller.rb +39 -0
  20. data/lib/influxdb/rails/backtrace.rb +44 -0
  21. data/lib/influxdb/rails/configuration.rb +117 -0
  22. data/lib/influxdb/rails/exception_presenter.rb +90 -0
  23. data/lib/influxdb/rails/instrumentation.rb +27 -0
  24. data/lib/influxdb/rails/logger.rb +13 -0
  25. data/lib/influxdb/rails/middleware/hijack_render_exception.rb +21 -0
  26. data/lib/influxdb/rails/middleware/hijack_rescue_action_everywhere.rb +32 -0
  27. data/lib/influxdb/rails/rack.rb +28 -0
  28. data/lib/influxdb/rails/rails.rb +39 -0
  29. data/lib/influxdb/rails/railtie.rb +67 -0
  30. data/lib/influxdb/rails/version.rb +5 -0
  31. data/lib/rails/generators/influxdb/influxdb_generator.rb +52 -0
  32. data/lib/rails/generators/influxdb/templates/initializer.rb +4 -0
  33. data/spec/controllers/widgets_controller_spec.rb +15 -0
  34. data/spec/integration/exceptions_spec.rb +37 -0
  35. data/spec/integration/integration_helper.rb +1 -0
  36. data/spec/spec_helper.rb +29 -0
  37. data/spec/suite.sh +42 -0
  38. data/spec/support/rails3/app.rb +24 -0
  39. data/spec/support/rails3/log/test.log +1120 -0
  40. data/spec/support/rails4/app.rb +27 -0
  41. data/spec/unit/backtrace_spec.rb +88 -0
  42. data/spec/unit/configuration_spec.rb +29 -0
  43. data/spec/unit/exception_presenter_spec.rb +69 -0
  44. data/spec/unit/influxdb_rails_spec.rb +67 -0
  45. metadata +226 -0
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'actionpack', '~> 4.0.0'
4
+ gem 'activesupport', '~> 4.0.0'
5
+ gem 'activemodel', '~> 4.0.0'
6
+ gem 'rspec-rails', '>= 2.0'
7
+
8
+ gemspec :path => '../'
@@ -0,0 +1,109 @@
1
+ PATH
2
+ remote: /Users/todd/Projects/errplane/errplane-ruby
3
+ specs:
4
+ errplane (1.0.6)
5
+ json
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionpack (4.0.0)
11
+ activesupport (= 4.0.0)
12
+ builder (~> 3.1.0)
13
+ erubis (~> 2.7.0)
14
+ rack (~> 1.5.2)
15
+ rack-test (~> 0.6.2)
16
+ activemodel (4.0.0)
17
+ activesupport (= 4.0.0)
18
+ builder (~> 3.1.0)
19
+ activesupport (4.0.0)
20
+ i18n (~> 0.6, >= 0.6.4)
21
+ minitest (~> 4.2)
22
+ multi_json (~> 1.3)
23
+ thread_safe (~> 0.1)
24
+ tzinfo (~> 0.3.37)
25
+ atomic (1.1.10)
26
+ builder (3.1.4)
27
+ coderay (1.0.9)
28
+ diff-lcs (1.2.4)
29
+ erubis (2.7.0)
30
+ fakeweb (1.3.0)
31
+ ffi (1.9.0)
32
+ formatador (0.2.4)
33
+ guard (1.8.1)
34
+ formatador (>= 0.2.4)
35
+ listen (>= 1.0.0)
36
+ lumberjack (>= 1.0.2)
37
+ pry (>= 0.9.10)
38
+ thor (>= 0.14.6)
39
+ guard-rspec (3.0.2)
40
+ guard (>= 1.8)
41
+ rspec (~> 2.13)
42
+ i18n (0.6.4)
43
+ json (1.8.0)
44
+ listen (1.2.2)
45
+ rb-fsevent (>= 0.9.3)
46
+ rb-inotify (>= 0.9)
47
+ rb-kqueue (>= 0.2)
48
+ lumberjack (1.0.4)
49
+ method_source (0.8.1)
50
+ minitest (4.7.5)
51
+ multi_json (1.7.7)
52
+ pry (0.9.12.2)
53
+ coderay (~> 1.0.5)
54
+ method_source (~> 0.8)
55
+ slop (~> 3.4)
56
+ rack (1.5.2)
57
+ rack-test (0.6.2)
58
+ rack (>= 1.0)
59
+ railties (4.0.0)
60
+ actionpack (= 4.0.0)
61
+ activesupport (= 4.0.0)
62
+ rake (>= 0.8.7)
63
+ thor (>= 0.18.1, < 2.0)
64
+ rake (10.1.0)
65
+ rb-fsevent (0.9.3)
66
+ rb-inotify (0.9.0)
67
+ ffi (>= 0.5.0)
68
+ rb-kqueue (0.2.0)
69
+ ffi (>= 0.5.0)
70
+ rdoc (4.0.1)
71
+ json (~> 1.4)
72
+ rspec (2.14.1)
73
+ rspec-core (~> 2.14.0)
74
+ rspec-expectations (~> 2.14.0)
75
+ rspec-mocks (~> 2.14.0)
76
+ rspec-core (2.14.4)
77
+ rspec-expectations (2.14.0)
78
+ diff-lcs (>= 1.1.3, < 2.0)
79
+ rspec-mocks (2.14.1)
80
+ rspec-rails (2.14.0)
81
+ actionpack (>= 3.0)
82
+ activesupport (>= 3.0)
83
+ railties (>= 3.0)
84
+ rspec-core (~> 2.14.0)
85
+ rspec-expectations (~> 2.14.0)
86
+ rspec-mocks (~> 2.14.0)
87
+ slop (3.4.6)
88
+ thor (0.18.1)
89
+ thread_safe (0.1.2)
90
+ atomic
91
+ tzinfo (0.3.37)
92
+
93
+ PLATFORMS
94
+ ruby
95
+
96
+ DEPENDENCIES
97
+ actionpack (~> 4.0.0)
98
+ activemodel (~> 4.0.0)
99
+ activesupport (~> 4.0.0)
100
+ bundler (>= 1.0.0)
101
+ errplane!
102
+ fakeweb
103
+ guard
104
+ guard-rspec
105
+ rake
106
+ rdoc
107
+ rspec
108
+ rspec-rails (>= 2.0)
109
+ tzinfo
@@ -0,0 +1,48 @@
1
+ class InfluxDBGenerator < Rails::Generator::Base
2
+ def add_options!(option)
3
+ option.on("-k", "--api-key=API_KEY", String, "API key for your InfluxDB organization") {|v| options[:api_key] = v}
4
+ option.on("-a", "--application-id=APP_ID", String, "Your InfluxDB application id (optional)") {|v| options[:application_id] = v}
5
+ end
6
+
7
+ def manifest
8
+ if options[:api_key].blank?
9
+ puts "You must provide an API key using -k or --api-key."
10
+ exit
11
+ end
12
+
13
+ begin
14
+ puts "Contacting InfluxDB API"
15
+ application_name = "ApplicationName"
16
+ api_key = options[:api_key]
17
+
18
+ connection = Net::HTTP.new("influxdb.com", 443)
19
+ connection.use_ssl = true
20
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
21
+ url = "/api/v1/applications?api_key=#{api_key}&name=#{application_name}"
22
+ response = connection.post(url, nil)
23
+
24
+ @application = JSON.parse(response.body)
25
+
26
+ unless response.is_a?(Net::HTTPSuccess)
27
+ raise "The InfluxDB API returned an error: #{response.inspect}"
28
+ end
29
+ rescue => e
30
+ puts "We ran into a problem creating your application via the API!"
31
+ puts "If this issue persists, contact us at support@influxdb.com with the following details:"
32
+ puts "API Key: #{e.class}: #{options[:api_key]}"
33
+ puts "#{e.class}: #{e.message}"
34
+ end
35
+
36
+ record do |m|
37
+ m.template "initializer.rb", "config/initializers/influxdb.rb",
38
+ :assigns => {
39
+ :application_id => options[:application_id] || @application["key"] || secure_random.hex(4),
40
+ :api_key => options[:api_key]
41
+ }
42
+ end
43
+ end
44
+
45
+ def secure_random
46
+ defined?(SecureRandom) ? SecureRandom : ActiveSupport::SecureRandom
47
+ end
48
+ end
@@ -0,0 +1,5 @@
1
+ require "influxdb"
2
+
3
+ InfluxDB::Rails.configure do |config|
4
+
5
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "influxdb/rails/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "influxdb-rails"
7
+ s.version = InfluxDB::Rails::VERSION
8
+ s.authors = ["Todd Persen"]
9
+ s.email = ["todd@influxdb.com"]
10
+ s.homepage = "http://influxdb.com"
11
+ s.summary = %q{InfluxDB bindings for Ruby on Rails.}
12
+ s.description = %q{This gem automatically instruments your Ruby on Rails 3.x/4.x applications using InfluxDB for storage.}
13
+
14
+ s.rubyforge_project = "influxdb-rails"
15
+
16
+ s.files = Dir.glob('**/*')
17
+ s.test_files = Dir.glob('test/**/*') + Dir.glob('spec/**/*') + Dir.glob('features/**/*')
18
+ s.executables = Dir.glob('bin/**/*').map {|f| File.basename(f)}
19
+ s.require_paths = ["lib"]
20
+
21
+ s.licenses = ['MIT']
22
+
23
+ s.add_runtime_dependency 'influxdb'
24
+ s.add_runtime_dependency 'railties'
25
+
26
+ s.add_development_dependency 'bundler', ['>= 1.0.0']
27
+ s.add_development_dependency 'fakeweb', ['>= 0']
28
+ s.add_development_dependency 'rake', ['>= 0']
29
+ s.add_development_dependency 'rdoc', ['>= 0']
30
+ s.add_development_dependency 'rspec', ['>= 0']
31
+ s.add_development_dependency 'rspec-rails', ['>= 0']
32
+ s.add_development_dependency 'tzinfo', ['>= 0']
33
+ end
@@ -0,0 +1,82 @@
1
+ require "net/http"
2
+ require "net/https"
3
+ require "rubygems"
4
+ require "socket"
5
+ require "thread"
6
+
7
+ require "influxdb/rails/version"
8
+ require "influxdb/rails/logger"
9
+ require "influxdb/rails/exception_presenter"
10
+ require "influxdb/rails/configuration"
11
+ require "influxdb/rails/backtrace"
12
+ require "influxdb/rails/rack"
13
+
14
+ require "influxdb/rails/railtie" if defined?(Rails::Railtie)
15
+
16
+ module InfluxDB
17
+ module Rails
18
+ class << self
19
+ include InfluxDB::Rails::Logger
20
+
21
+ attr_writer :configuration
22
+ attr_accessor :client
23
+
24
+ def configure(silent = false)
25
+ yield(configuration)
26
+ self.client = InfluxDB::Client.new
27
+ end
28
+
29
+ def configuration
30
+ @configuration ||= InfluxDB::Rails::Configuration.new
31
+ end
32
+
33
+ def report_exception_unless_ignorable(e, env = {})
34
+ report_exception(e, env) unless ignorable_exception?(e)
35
+ end
36
+ alias_method :transmit_unless_ignorable, :report_exception_unless_ignorable
37
+
38
+ def report_exception(e, env = {})
39
+ begin
40
+ env = influxdb_request_data if env.empty? && defined? influxdb_request_data
41
+ exception_presenter = ExceptionPresenter.new(e, env)
42
+ log :info, "Exception: #{exception_presenter.to_json[0..512]}..."
43
+
44
+ InfluxDB::Rails.client.write_point "rails.exceptions",
45
+ :context => exception_presenter.context,
46
+ :dimensions => exception_presenter.dimensions
47
+
48
+ rescue => e
49
+ log :info, "[InfluxDB] Something went terribly wrong. Exception failed to take off! #{e.class}: #{e.message}"
50
+ end
51
+ end
52
+ alias_method :transmit, :report_exception
53
+
54
+ def current_timestamp
55
+ Time.now.utc.to_i
56
+ end
57
+
58
+ def ignorable_exception?(e)
59
+ configuration.ignore_current_environment? ||
60
+ !!configuration.ignored_exception_messages.find{ |msg| /.*#{msg}.*/ =~ e.message } ||
61
+ configuration.ignored_exceptions.include?(e.class.to_s)
62
+ end
63
+
64
+ def rescue(&block)
65
+ block.call
66
+ rescue StandardError => e
67
+ if configuration.ignore_current_environment?
68
+ raise(e)
69
+ else
70
+ transmit_unless_ignorable(e)
71
+ end
72
+ end
73
+
74
+ def rescue_and_reraise(&block)
75
+ block.call
76
+ rescue StandardError => e
77
+ transmit_unless_ignorable(e)
78
+ raise(e)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,39 @@
1
+ module InfluxDB
2
+ module Rails
3
+ module AirTrafficController
4
+ def influxdb_request_data
5
+ unfiltered_params = params.to_hash
6
+ if respond_to?(:filter_parameters)
7
+ filtered_params = filter_parameters(unfiltered_params)
8
+ elsif defined? request.filtered_parameters
9
+ filtered_params = request.filtered_parameters
10
+ else
11
+ filtered_params = unfiltered_params.except(:password, :password_confirmation)
12
+ end
13
+
14
+ {
15
+ :params => filtered_params,
16
+ :session_data => influxdb_session_data,
17
+ :controller => params[:controller],
18
+ :action => params[:action],
19
+ :request_url => influxdb_request_url,
20
+ :user_agent => request.env["HTTP_USER_AGENT"],
21
+ :remote_ip => request.remote_ip,
22
+ :referer => request.referer,
23
+ :current_user => (current_user rescue nil)
24
+ }
25
+ end
26
+
27
+ private
28
+ def influxdb_session_data
29
+ session.respond_to?(:to_hash) ? session.to_hash : session.data
30
+ end
31
+
32
+ def influxdb_request_url
33
+ url = "#{request.protocol}#{request.host}"
34
+ url << ":#{request.port}" unless [80, 443].include?(request.port)
35
+ url << request.fullpath
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,44 @@
1
+ module InfluxDB
2
+ module Rails
3
+ class Backtrace
4
+ class Line
5
+ FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}.freeze
6
+
7
+ attr_reader :file
8
+ attr_reader :number
9
+ attr_reader :method
10
+
11
+ def initialize(line)
12
+ _, @file, @number, @method = line.match(FORMAT).to_a
13
+ end
14
+
15
+ def to_s
16
+ "#{file}:#{number} in `#{method}'"
17
+ end
18
+
19
+ def inspect
20
+ "<Line: #{to_s}>"
21
+ end
22
+ end
23
+
24
+ attr_reader :lines
25
+
26
+ def initialize(backtrace)
27
+ @lines = Array(backtrace).each.collect do |line|
28
+ InfluxDB::Rails.configuration.backtrace_filters.each do |filter|
29
+ line = filter.call(line)
30
+ end
31
+ Line.new(line)
32
+ end
33
+ end
34
+
35
+ def to_a
36
+ lines.map(&:to_s)
37
+ end
38
+
39
+ def inspect
40
+ "<Backtrace: " + lines.collect { |line| line.to_s }.join(", ") + ">"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,117 @@
1
+ module InfluxDB
2
+ module Rails
3
+ class Configuration
4
+ attr_accessor :influxdb_host
5
+ attr_accessor :influxdb_port
6
+ attr_accessor :application_id
7
+ attr_accessor :application_name
8
+ attr_accessor :application_root
9
+
10
+ attr_accessor :logger
11
+ attr_accessor :environment
12
+ attr_accessor :framework
13
+ attr_accessor :framework_version
14
+ attr_accessor :language
15
+ attr_accessor :language_version
16
+ attr_accessor :ignored_exceptions
17
+ attr_accessor :ignored_exception_messages
18
+ attr_accessor :ignored_reports
19
+ attr_accessor :ignored_environments
20
+ attr_accessor :ignored_user_agents
21
+ attr_accessor :backtrace_filters
22
+ attr_accessor :aggregated_exception_classes
23
+ attr_accessor :environment_variables
24
+ attr_accessor :environment_variable_filters
25
+
26
+ attr_accessor :instrumentation_enabled
27
+ attr_accessor :debug
28
+ attr_accessor :reraise_global_exceptions
29
+
30
+ DEFAULTS = {
31
+ :influxdb_host => "localhost",
32
+ :influxdb_port => 8086,
33
+ :ignored_exceptions => %w{ActiveRecord::RecordNotFound
34
+ ActionController::RoutingError},
35
+ :ignored_exception_messages => [],
36
+ :ignored_reports => [],
37
+ :ignored_environments => %w{test cucumber selenium},
38
+ :ignored_user_agents => %w{GoogleBot},
39
+ :environment_variable_filters => [
40
+ /password/i,
41
+ /key/i,
42
+ /secret/i,
43
+ /ps1/i,
44
+ /rvm_.*_clr/i,
45
+ /color/i
46
+ ],
47
+ :backtrace_filters => [
48
+ lambda { |line| line.gsub(/^\.\//, "") },
49
+ lambda { |line|
50
+ return line if InfluxDB::Rails.configuration.application_root.to_s.empty?
51
+ line.gsub(/#{InfluxDB::Rails.configuration.application_root}/, "[APP_ROOT]")
52
+ },
53
+ lambda { |line|
54
+ if defined?(Gem) && !Gem.path.nil? && !Gem.path.empty?
55
+ Gem.path.each { |path| line = line.gsub(/#{path}/, "[GEM_ROOT]") }
56
+ end
57
+ line
58
+ }
59
+ ]
60
+ }
61
+
62
+ def initialize
63
+ @influxdb_host = DEFAULTS[:influxdb_host]
64
+ @influxdb_port = DEFAULTS[:influxdb_port]
65
+ @ignored_exceptions = DEFAULTS[:ignored_exceptions].dup
66
+ @ignored_exception_messages = DEFAULTS[:ignored_exception_messages].dup
67
+ @ignored_reports = DEFAULTS[:ignored_reports].dup
68
+ @ignored_environments = DEFAULTS[:ignored_environments].dup
69
+ @ignored_user_agents = DEFAULTS[:ignored_user_agents].dup
70
+ @backtrace_filters = DEFAULTS[:backtrace_filters].dup
71
+ @environment_variable_filters = DEFAULTS[:environment_variable_filters]
72
+ @aggregated_exception_classes = []
73
+ @debug = false
74
+ @rescue_global_exceptions = false
75
+ @instrumentation_enabled = true
76
+ end
77
+
78
+ def debug?
79
+ !!@debug
80
+ end
81
+
82
+ def instrumentation_enabled?
83
+ !!@instrumentation_enabled
84
+ end
85
+
86
+ def reraise_global_exceptions?
87
+ !!@reraise_global_exceptions
88
+ end
89
+
90
+ def ignore_user_agent?(incoming_user_agent)
91
+ return false if self.ignored_user_agents.nil?
92
+ self.ignored_user_agents.any? {|agent| incoming_user_agent =~ /#{agent}/}
93
+ end
94
+
95
+ def ignore_current_environment?
96
+ self.ignored_environments.include?(self.environment)
97
+ end
98
+
99
+ def define_custom_exception_data(&block)
100
+ @custom_exception_data_handler = block
101
+ end
102
+
103
+ def add_custom_exception_data(exception_presenter)
104
+ @custom_exception_data_handler.call(exception_presenter) if @custom_exception_data_handler
105
+ end
106
+
107
+ def database_name
108
+ @application_id.to_s + @environment.to_s
109
+ end
110
+
111
+ private
112
+ def initialize_http_connection
113
+ Net::HTTP.new(@app_host, "80")
114
+ end
115
+ end
116
+ end
117
+ end