honeycomb-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e4126edc89b123ee4b3e97d5a11f71f7870dc780
4
+ data.tar.gz: 73d1591815b66f612c8b8ef83623b0d4285d6ba1
5
+ SHA512:
6
+ metadata.gz: 0a97d7fe16561fec60e4065aed9de06af9486581e662b3ab919cdd83748c7ff26a836c5fbcbfc66e7c6311b5eb118708811afc820570911af75638d11a4c69a8
7
+ data.tar.gz: f80b392f7e5561b075ce73824a7dbe729123af30224a5a4fc711282d5e3da8340e60142f0a81278213d9422e0af2eb1823875a6c34ceec7a73a9ff3315c5c29f
@@ -0,0 +1,39 @@
1
+ # honeycomb-rails
2
+
3
+ Easily instrument your Rails apps with [Honeycomb](https://honeycomb.io).
4
+
5
+ ## Getting started
6
+
7
+ Add the following to your Gemfile:
8
+
9
+ ```ruby
10
+ gem 'honeycomb-rails'
11
+ ```
12
+
13
+ Then create a file in your application repo called `config/initializers/honeycomb.rb` with the following contents:
14
+
15
+ ```ruby
16
+ HoneycombRails.configure do |conf|
17
+ conf.writekey = 'your honeycomb writekey here'
18
+ conf.dataset = 'your app name'
19
+ conf.db_dataset = 'your app name-activerecord'
20
+ end
21
+ ```
22
+
23
+ Now check out our [guide](https://honeycomb.io/docs/guides/rails/) to see what kind of visibility you can get from your app.
24
+
25
+ ## Configuration
26
+
27
+ See [docs](http://www.rubydoc.info/gems/honeycomb-rails/HoneycombRails/Config) for available config options.
28
+
29
+ ## Documentation
30
+
31
+ See [rubydoc](http://www.rubydoc.info/gems/honeycomb-rails/) for gem documentation.
32
+
33
+ ## Contributions
34
+
35
+ Features, bug fixes and other changes are gladly accepted. Please
36
+ open issues or a pull request with your change. Remember to add your name to the
37
+ CONTRIBUTORS file!
38
+
39
+ All contributions will be released under the Apache License 2.0.
@@ -0,0 +1,27 @@
1
+ if !defined?(Rails)
2
+ raise LoadError, 'honeycomb-rails requires Rails (maybe you meant libhoney?)'
3
+ end
4
+
5
+ require 'honeycomb-rails/config'
6
+
7
+ module HoneycombRails
8
+ class << self
9
+ # Run this at app initialization time to configure honeycomb-rails. e.g.
10
+ #
11
+ # HoneycombRails.configure do |conf|
12
+ # conf.writekey = 'abc123def'
13
+ # end
14
+ #
15
+ # See {Config} for available options.
16
+ #
17
+ # @yield [Config] the singleton config.
18
+ def configure
19
+ raise "Please pass a block to #{name}#configure" unless block_given?
20
+
21
+ yield config
22
+ config
23
+ end
24
+ end
25
+ end
26
+
27
+ require 'honeycomb-rails/railtie'
@@ -0,0 +1,53 @@
1
+ module HoneycombRails
2
+ # Configuration for the Honeycomb Rails integration.
3
+ #
4
+ # Specify this at app initialization time via {configure}.
5
+ class Config
6
+ def initialize
7
+ @dataset = 'rails'
8
+ @db_dataset = 'active_record'
9
+ @record_flash = true
10
+ @record_user = :detect
11
+ end
12
+
13
+ # Whether to record flash messages (default: true).
14
+ attr_writer :record_flash
15
+ # Whether to record flash messages (default: true).
16
+ def record_flash?
17
+ !!@record_flash
18
+ end
19
+
20
+ # If set, determines how to record the current user during request processing (default: :detect). Set to nil or false to disable.
21
+ #
22
+ # Valid values:
23
+ #
24
+ # * :devise - if your app uses Devise for authentication
25
+ # * :detect - autodetect how to determine the current user
26
+ # * nil, false - disable recording current user
27
+ #
28
+ # You can also pass a Proc, which will be called with the current controller
29
+ # instance during each request, and which should return a hash of metadata
30
+ # about the current user.
31
+ attr_accessor :record_user
32
+
33
+ # The Honeycomb dataset to send request events to (default: 'rails').
34
+ attr_accessor :dataset
35
+ # The Honeycomb dataset to send ActiveRecord query events to (default: 'active_record').
36
+ attr_accessor :db_dataset
37
+ # The Honeycomb write key for your team (must be specified).
38
+ attr_accessor :writekey
39
+ end
40
+
41
+ class << self
42
+ # @api private
43
+ def config
44
+ @config ||= Config.new
45
+ end
46
+
47
+ # For test use only
48
+ # @api private
49
+ def reset_config_to_default!
50
+ @config = Config.new
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,6 @@
1
+ module HoneycombRails
2
+ module Constants
3
+ # @api private
4
+ EVENT_METADATA_KEY = :honeycomb_metadata
5
+ end
6
+ end
@@ -0,0 +1 @@
1
+ require 'honeycomb-rails/extensions/action_controller'
@@ -0,0 +1,30 @@
1
+ module HoneycombRails
2
+ module Extensions
3
+ module ActionController
4
+ module InstanceMethods
5
+ def self.included(controller_class)
6
+ super
7
+
8
+ controller_class.before_action do
9
+ honeycomb_initialize
10
+ end
11
+ end
12
+
13
+ def honeycomb_initialize
14
+ @honeycomb_metadata = {}
15
+ end
16
+
17
+ # Hash of metadata to be added to the event we will send to Honeycomb
18
+ # for the current request.
19
+ #
20
+ # To annotate the event with custom information (e.g. from a particular
21
+ # controller action), just add data to this hash: e.g.
22
+ #
23
+ # honeycomb_metadata[:num_posts] = @posts.size
24
+ #
25
+ # @return [Hash<String=>Any>]
26
+ attr_reader :honeycomb_metadata
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1 @@
1
+ require 'honeycomb-rails/overrides/action_controller_instrumentation'
@@ -0,0 +1,69 @@
1
+ require 'honeycomb-rails/config'
2
+ require 'honeycomb-rails/constants'
3
+
4
+ module HoneycombRails
5
+ module Overrides
6
+ module ActionControllerInstrumentation
7
+ def append_info_to_payload(payload)
8
+ super
9
+
10
+ metadata = honeycomb_metadata
11
+
12
+ metadata.merge!(honeycomb_user_metadata)
13
+
14
+ if HoneycombRails.config.record_flash?
15
+ flash.each do |k, v|
16
+ metadata[:"flash_#{k}"] = v
17
+ end
18
+ end
19
+
20
+ # Attach to ActiveSupport::Instrumentation payload for consumption by
21
+ # subscribers/process_action.rb
22
+ payload[Constants::EVENT_METADATA_KEY] = metadata
23
+ end
24
+
25
+ def honeycomb_user_metadata
26
+ if defined?(@honeycomb_user_proc)
27
+ return @honeycomb_user_proc.call(self)
28
+ end
29
+
30
+ case HoneycombRails.config.record_user
31
+ when :detect
32
+ honeycomb_detect_user_methods!
33
+ honeycomb_user_metadata
34
+ when :devise
35
+ honeycomb_user_metadata_devise
36
+ when Proc
37
+ @honeycomb_user_proc = HoneycombRails.config.record_user
38
+ honeycomb_user_metadata
39
+ when nil, false
40
+ {}
41
+ else
42
+ raise "Invalid value for HoneycombRails.config.record_user: #{HoneycombRails.config.record_user.inspect}"
43
+ end
44
+ end
45
+
46
+ def honeycomb_user_metadata_devise
47
+ if current_user
48
+ {
49
+ current_user_id: current_user.id,
50
+ current_user_email: current_user.email,
51
+ current_user_admin: !!current_user.try(:admin?),
52
+ }
53
+ else
54
+ {}
55
+ end
56
+ end
57
+
58
+ def honeycomb_detect_user_methods!
59
+ if respond_to?(:current_user)
60
+ # This could be more sophisticated, but it'll do for now
61
+ HoneycombRails.config.record_user = :devise
62
+ else
63
+ logger.error "HoneycombRails.config.record_user = :detect but couldn't detect user methods; disabling user recording."
64
+ HoneycombRails.config.record_user = false
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,35 @@
1
+ require 'honeycomb-rails/extensions'
2
+ require 'honeycomb-rails/overrides'
3
+ require 'honeycomb-rails/subscribers'
4
+
5
+ require 'libhoney'
6
+
7
+ module HoneycombRails
8
+ class Railtie < ::Rails::Railtie
9
+ initializer 'honeycomb.action_controller_extensions', after: :action_controller do
10
+ ::ActionController::Base.include(Extensions::ActionController::InstanceMethods)
11
+ end
12
+
13
+ initializer 'honeycomb.action_controller_overrides', after: :action_controller do
14
+ ::ActionController::Base.include(Overrides::ActionControllerInstrumentation)
15
+ end
16
+
17
+ # set up libhoney after application initialization so that any config in
18
+ # the app's config/initializers has taken effect.
19
+ config.after_initialize do
20
+ writekey = HoneycombRails.config.writekey
21
+ dataset = HoneycombRails.config.dataset
22
+ @libhoney = Libhoney::Client.new(writekey: writekey, dataset: dataset)
23
+ end
24
+
25
+ config.after_initialize do
26
+ db_builder = @libhoney.builder
27
+ db_builder.dataset = HoneycombRails.config.db_dataset
28
+
29
+ [
30
+ Subscribers::ProcessAction.new(@libhoney),
31
+ Subscribers::ActiveRecord.new(db_builder),
32
+ ].each(&:subscribe!)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,2 @@
1
+ require 'honeycomb-rails/subscribers/active_record'
2
+ require 'honeycomb-rails/subscribers/process_action'
@@ -0,0 +1,36 @@
1
+ require 'active_support/core_ext/hash'
2
+ require 'active_support/notifications'
3
+ require 'rails'
4
+
5
+ module HoneycombRails
6
+ module Subscribers
7
+ class ActiveRecord
8
+ def initialize(honeybuilder)
9
+ @honeybuilder = honeybuilder
10
+ end
11
+
12
+ def subscribe!
13
+ ::ActiveSupport::Notifications.subscribe(/sql.active_record/) do |*args|
14
+ call(*args)
15
+ end
16
+ end
17
+
18
+ def call(*args)
19
+ event = ActiveSupport::Notifications::Event.new(*args)
20
+ data = event.payload.slice(:name, :connection_id)
21
+ data[:sql] = event.payload[:sql].strip
22
+ event.payload[:binds].each do |b|
23
+ data["bind_#{ b.name }".to_sym] = b.value
24
+ end
25
+ data[:duration] = event.duration
26
+
27
+ # NOTE: Backtraces can be very verbose! Keep an eye on the data that gets sent
28
+ # into Honeycomb and, if needed, experiment with BacktraceCleaner's
29
+ # filters and silencers to trim down the noise.
30
+ data[:local_stack] = Rails.backtrace_cleaner.clean(caller)
31
+
32
+ @honeybuilder.send_now(data)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,44 @@
1
+ require 'honeycomb-rails/constants'
2
+
3
+ require 'active_support/core_ext/hash'
4
+ require 'active_support/notifications'
5
+
6
+ module HoneycombRails
7
+ module Subscribers
8
+ class ProcessAction
9
+ def initialize(libhoney)
10
+ @libhoney = libhoney
11
+ end
12
+
13
+ def subscribe!
14
+ ::ActiveSupport::Notifications.subscribe(/process_action.action_controller/) do |*args|
15
+ call(*args)
16
+ end
17
+ end
18
+
19
+ def call(*args)
20
+ event = ::ActiveSupport::Notifications::Event.new(*args)
21
+
22
+ # These are the keys we're interested in! Skipping noisy keys (:headers, :params) for now.
23
+ data = event.payload.slice(:controller, :action, :method, :path, :format,
24
+ :status, :db_runtime, :view_runtime)
25
+
26
+ # Massage data to return "all" as the :format if not set
27
+ if !data[:format] || data[:format] == "format:*/*"
28
+ data[:format] = "all"
29
+ end
30
+
31
+ # Pull top-level attributes off of the ActiveSupport Event.
32
+ data[:duration_ms] = event.duration
33
+
34
+ # Add anything we added in our controller-level instrumentation (see
35
+ # overrides/action_controller_instrumentation.rb)
36
+ if event.payload.key?(Constants::EVENT_METADATA_KEY)
37
+ data.merge!(event.payload[Constants::EVENT_METADATA_KEY])
38
+ end
39
+
40
+ @libhoney.send_now(data)
41
+ end
42
+ end
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: honeycomb-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sam Stokes
8
+ - Christine Yen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-11-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: libhoney
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 1.3.2
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: 1.3.2
28
+ - !ruby/object:Gem::Dependency
29
+ name: rails
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 3.0.0
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 3.0.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: yard
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: libhoney
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 1.4.0
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 1.4.0
98
+ description: |2
99
+ Get fine-grained visibility into the behavior and performance of your
100
+ Rails web app. This gem instruments your app to send events to Honeycomb
101
+ (https://honeycomb.io) each time it processes an HTTP request or makes a
102
+ database query.
103
+ email:
104
+ - sam@honeycomb.io
105
+ executables: []
106
+ extensions: []
107
+ extra_rdoc_files: []
108
+ files:
109
+ - README.md
110
+ - lib/honeycomb-rails.rb
111
+ - lib/honeycomb-rails/config.rb
112
+ - lib/honeycomb-rails/constants.rb
113
+ - lib/honeycomb-rails/extensions.rb
114
+ - lib/honeycomb-rails/extensions/action_controller.rb
115
+ - lib/honeycomb-rails/overrides.rb
116
+ - lib/honeycomb-rails/overrides/action_controller_instrumentation.rb
117
+ - lib/honeycomb-rails/railtie.rb
118
+ - lib/honeycomb-rails/subscribers.rb
119
+ - lib/honeycomb-rails/subscribers/active_record.rb
120
+ - lib/honeycomb-rails/subscribers/process_action.rb
121
+ homepage: https://github.com/honeycombio/honeycomb-rails
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: 2.0.0
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.6.11
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Easily instrument your Rails apps with Honeycomb
145
+ test_files: []