rack-honeycomb 0.2.2 → 0.3.0
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +5 -0
- data/Gemfile.rails3.rb +7 -0
- data/Gemfile.rails4.rb +6 -0
- data/README.md +7 -5
- data/lib/rack-honeycomb/auto_install.rb +54 -14
- data/lib/rack-honeycomb/railtie.rb +26 -0
- data/lib/rack/honeycomb/middleware.rb +82 -6
- data/lib/rack/honeycomb/version.rb +1 -1
- data/rack-honeycomb.gemspec +1 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d71737f6f10436e9df8ccf2589fa626b720baf0eca15dd764496daa6028d3be1
|
4
|
+
data.tar.gz: 132781010ca1cf718553c968961bf10f3ec683b891b53fb800c5539148d357c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e698f60be56541bd891ad9b2e00c897553fd2851127524e9726394ca28d1af80c6929cb01a6ba40286e8fc326d5df21009ace359f7ee718139e42368630738db
|
7
|
+
data.tar.gz: 7aa9fd274977bd1dc31985eb66f37f28ac433aa6d3632f192b8640f897203c3ea80b260a217f6bd562b85cb80eaa830fc54450cdfb36a895fae8b4debca147b9
|
data/.gitignore
CHANGED
@@ -42,7 +42,7 @@ build-iPhoneSimulator/
|
|
42
42
|
|
43
43
|
# for a library or gem, you might want to ignore these files since the code is
|
44
44
|
# intended to run in multiple environments; otherwise, check them in:
|
45
|
-
Gemfile
|
45
|
+
Gemfile*.lock
|
46
46
|
.ruby-version
|
47
47
|
.ruby-gemset
|
48
48
|
|
@@ -50,3 +50,4 @@ Gemfile.lock
|
|
50
50
|
.rvmrc
|
51
51
|
|
52
52
|
*~
|
53
|
+
log
|
data/.travis.yml
CHANGED
data/Gemfile.rails3.rb
ADDED
data/Gemfile.rails4.rb
ADDED
data/README.md
CHANGED
@@ -13,26 +13,28 @@ Attaching the middleware is simple. Inside handlers, you also have the choice of
|
|
13
13
|
require 'sinatra'
|
14
14
|
require 'rack/honeycomb'
|
15
15
|
|
16
|
-
use Rack::Honeycomb::Middleware, writekey: "<YOUR WRITEKEY HERE>", dataset: "<YOUR DATASET NAME HERE>"
|
16
|
+
use Rack::Honeycomb::Middleware, writekey: "<YOUR WRITEKEY HERE>", dataset: "<YOUR DATASET NAME HERE>", is_sinatra: true
|
17
17
|
|
18
18
|
get('/hello') do
|
19
|
-
Rack::Honeycomb.add_field :greeting, 'hello'
|
19
|
+
Rack::Honeycomb.add_field env, :greeting, 'hello'
|
20
20
|
"Hello, world!\n"
|
21
21
|
end
|
22
22
|
```
|
23
23
|
|
24
24
|
## Adding instrumentation to a Rails application
|
25
25
|
|
26
|
-
For more fully-featured Rails support, see [
|
26
|
+
For more fully-featured Rails support, see [beeline-ruby](https://github.com/honeycombio/beeline-ruby).
|
27
27
|
|
28
|
-
|
28
|
+
[beeline-ruby](https://github.com/honeycombio/beeline-ruby) includes this gem along with active record support.
|
29
|
+
|
30
|
+
If beeline-ruby doesn't work for you, you can include this middleware standalone
|
29
31
|
|
30
32
|
```ruby
|
31
33
|
# config/application.rb
|
32
34
|
require 'rack/honeycomb'
|
33
35
|
|
34
36
|
class Application < Rails::Application
|
35
|
-
config.middleware.use Rack::Honeycomb::Middleware, writekey: "<YOUR WRITEKEY HERE>", dataset: "<YOUR DATASET NAME HERE>"
|
37
|
+
config.middleware.use Rack::Honeycomb::Middleware, writekey: "<YOUR WRITEKEY HERE>", dataset: "<YOUR DATASET NAME HERE>", is_rails: true
|
36
38
|
end
|
37
39
|
```
|
38
40
|
|
@@ -4,33 +4,46 @@ module Rack
|
|
4
4
|
module AutoInstall
|
5
5
|
class << self
|
6
6
|
def available?(logger: nil)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
rescue Gem::LoadError => e
|
13
|
-
if e.name == 'sinatra'
|
14
|
-
logger.debug "Couldn't detect web framework, not autoinitialising rack-honeycomb" if logger
|
7
|
+
@logger = logger
|
8
|
+
|
9
|
+
unless has_gem? 'rack'
|
10
|
+
debug 'not autoinitialising rack-honeycomb'
|
11
|
+
return false
|
15
12
|
end
|
16
|
-
|
13
|
+
|
14
|
+
@has_sinatra = has_gem? 'sinatra'
|
15
|
+
@has_rails = has_gem? 'rails'
|
16
|
+
|
17
|
+
unless @has_sinatra || @has_rails
|
18
|
+
debug "Couldn't detect web framework, not autoinitialising rack-honeycomb"
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
true
|
17
23
|
end
|
18
24
|
|
19
25
|
def auto_install!(honeycomb_client:, logger: nil)
|
20
|
-
|
21
|
-
require 'sinatra/base'
|
26
|
+
@logger = logger
|
22
27
|
|
28
|
+
require 'rack'
|
23
29
|
require 'rack-honeycomb'
|
24
30
|
|
31
|
+
auto_install_sinatra!(honeycomb_client, logger) if @has_sinatra
|
32
|
+
auto_install_rails!(honeycomb_client, logger) if @has_rails
|
33
|
+
end
|
34
|
+
|
35
|
+
def auto_install_sinatra!(honeycomb_client, logger)
|
36
|
+
require 'sinatra/base'
|
37
|
+
|
25
38
|
class << ::Sinatra::Base
|
26
39
|
alias build_without_honeycomb build
|
27
40
|
end
|
28
41
|
|
29
42
|
::Sinatra::Base.define_singleton_method(:build) do |*args, &block|
|
30
43
|
if !AutoInstall.already_added
|
31
|
-
|
44
|
+
AutoInstall.debug "Adding Rack::Honeycomb::Middleware to #{self}"
|
32
45
|
|
33
|
-
self.use Rack::Honeycomb::Middleware, client: honeycomb_client, logger: logger
|
46
|
+
self.use Rack::Honeycomb::Middleware, client: honeycomb_client, logger: logger, is_sinatra: true
|
34
47
|
AutoInstall.already_added = true
|
35
48
|
else
|
36
49
|
# In the case of nested Sinatra apps - apps composed of other apps
|
@@ -40,7 +53,7 @@ module Rack
|
|
40
53
|
# middleware reliably - so instead, we just want to warn the user
|
41
54
|
# and avoid doing anything silly.
|
42
55
|
unless AutoInstall.already_warned
|
43
|
-
|
56
|
+
AutoInstall.warn 'Honeycomb auto-instrumentation of Sinatra will probably not work, try manual installation'
|
44
57
|
AutoInstall.already_warned = true
|
45
58
|
end
|
46
59
|
end
|
@@ -54,8 +67,35 @@ module Rack
|
|
54
67
|
end)
|
55
68
|
end
|
56
69
|
|
70
|
+
def auto_install_rails!(honeycomb_client, logger)
|
71
|
+
require 'rack-honeycomb/railtie'
|
72
|
+
::Rack::Honeycomb::Railtie.init(
|
73
|
+
honeycomb_client: honeycomb_client,
|
74
|
+
logger: logger,
|
75
|
+
)
|
76
|
+
debug 'Loaded Railtie'
|
77
|
+
end
|
78
|
+
|
57
79
|
attr_accessor :already_added
|
58
80
|
attr_accessor :already_warned
|
81
|
+
|
82
|
+
def debug(msg)
|
83
|
+
@logger.debug "#{self.name}: #{msg}" if @logger
|
84
|
+
end
|
85
|
+
|
86
|
+
def warn(msg)
|
87
|
+
@logger.warn "#{self.name}: #{msg}" if @logger
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def has_gem?(gem_name)
|
92
|
+
gem gem_name
|
93
|
+
debug "detected #{gem_name}"
|
94
|
+
true
|
95
|
+
rescue Gem::LoadError => e
|
96
|
+
debug "#{gem_name} not detected (#{e.class}: #{e.message})"
|
97
|
+
false
|
98
|
+
end
|
59
99
|
end
|
60
100
|
end
|
61
101
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Honeycomb
|
5
|
+
class Railtie < ::Rails::Railtie
|
6
|
+
class << self
|
7
|
+
attr_reader :honeycomb_client, :logger
|
8
|
+
|
9
|
+
def init(honeycomb_client:, logger: nil)
|
10
|
+
@honeycomb_client = honeycomb_client
|
11
|
+
@logger = logger
|
12
|
+
|
13
|
+
logger.debug "#{self}: initialized with #{honeycomb_client.class}" if logger
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
initializer 'honeycomb.add_rack_middleware' do |app|
|
18
|
+
app.middleware.use ::Rack::Honeycomb::Middleware,
|
19
|
+
client: Railtie.honeycomb_client,
|
20
|
+
logger: Railtie.logger,
|
21
|
+
is_rails: true
|
22
|
+
Railtie.logger.debug "#{Railtie}: Added rack-honeycomb middleware to #{app.class}" if Railtie.logger
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -20,18 +20,38 @@ module Rack
|
|
20
20
|
USER_AGENT_SUFFIX = "rack-honeycomb/#{VERSION}"
|
21
21
|
EVENT_TYPE = 'http_server'.freeze
|
22
22
|
|
23
|
+
RAILS_SPECIAL_PARAMS = %w(controller action).freeze
|
24
|
+
|
23
25
|
##
|
24
26
|
# @param [#call] app
|
25
27
|
# @param [Hash{Symbol => Object}] options
|
26
28
|
# @option options [String] :writekey (nil)
|
27
29
|
# @option options [String] :dataset (nil)
|
28
30
|
# @option options [String] :api_host (nil)
|
31
|
+
# @option options [Boolean] :is_sinatra (false)
|
32
|
+
# @option options [Boolean] :is_rails (false)
|
29
33
|
def initialize(app, options = {})
|
30
34
|
@app, @options = app, options
|
31
35
|
|
32
36
|
@logger = options.delete(:logger)
|
33
37
|
@logger ||= ::Honeycomb.logger if defined?(::Honeycomb.logger)
|
34
38
|
|
39
|
+
@is_sinatra = options.delete(:is_sinatra)
|
40
|
+
debug 'Enabling Sinatra-specific fields' if @is_sinatra
|
41
|
+
@is_rails = options.delete(:is_rails)
|
42
|
+
debug 'Enabling Rails-specific fields' if @is_rails
|
43
|
+
|
44
|
+
# report meta.package = rack only if we have no better information
|
45
|
+
package = 'rack'
|
46
|
+
package_version = RACK_VERSION
|
47
|
+
if @is_rails
|
48
|
+
package = 'rails'
|
49
|
+
package_version = ::Rails::VERSION::STRING
|
50
|
+
elsif @is_sinatra
|
51
|
+
package = 'sinatra'
|
52
|
+
package_version = ::Sinatra::VERSION
|
53
|
+
end
|
54
|
+
|
35
55
|
honeycomb = if client = options.delete(:client)
|
36
56
|
debug "initialized with #{client.class.name} via :client option"
|
37
57
|
client
|
@@ -44,13 +64,11 @@ module Rack
|
|
44
64
|
end
|
45
65
|
@builder = honeycomb.builder.
|
46
66
|
add(
|
47
|
-
'meta.package' =>
|
48
|
-
'meta.package_version' =>
|
67
|
+
'meta.package' => package,
|
68
|
+
'meta.package_version' => package_version,
|
49
69
|
'type' => EVENT_TYPE,
|
50
70
|
'meta.local_hostname' => Socket.gethostname,
|
51
71
|
)
|
52
|
-
|
53
|
-
@service_name = options.delete(:service_name) || :rack
|
54
72
|
end
|
55
73
|
|
56
74
|
def call(env)
|
@@ -63,8 +81,6 @@ module Rack
|
|
63
81
|
@app.call(env)
|
64
82
|
end
|
65
83
|
|
66
|
-
add_app_fields(ev, env)
|
67
|
-
|
68
84
|
add_response_fields(ev, status, headers, body)
|
69
85
|
|
70
86
|
[status, headers, body]
|
@@ -79,6 +95,11 @@ module Rack
|
|
79
95
|
finish = Time.now
|
80
96
|
ev.add_field('duration_ms', (finish - start) * 1000)
|
81
97
|
|
98
|
+
add_sinatra_fields(ev, env) if @is_sinatra
|
99
|
+
add_rails_fields(ev, env) if @is_rails
|
100
|
+
|
101
|
+
add_app_fields(ev, env)
|
102
|
+
|
82
103
|
ev.send
|
83
104
|
end
|
84
105
|
end
|
@@ -90,6 +111,8 @@ module Rack
|
|
90
111
|
|
91
112
|
def add_request_fields(event, env)
|
92
113
|
event.add_field('name', "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}")
|
114
|
+
# N.B. 'name' may be overwritten later by add_sinatra_fields or
|
115
|
+
# add_rails_fields
|
93
116
|
|
94
117
|
event.add_field('request.method', env['REQUEST_METHOD'])
|
95
118
|
event.add_field('request.path', env['PATH_INFO'])
|
@@ -105,6 +128,59 @@ module Rack
|
|
105
128
|
event.add_field('request.header.user_agent', env['HTTP_USER_AGENT'])
|
106
129
|
end
|
107
130
|
|
131
|
+
def add_sinatra_fields(event, env)
|
132
|
+
route = env['sinatra.route']
|
133
|
+
event.add_field('request.route', route)
|
134
|
+
# overwrite 'name' (previously set in add_request_fields)
|
135
|
+
event.add_field('name', route)
|
136
|
+
end
|
137
|
+
|
138
|
+
def add_rails_fields(event, env)
|
139
|
+
rails_params = env['action_dispatch.request.parameters']
|
140
|
+
unless rails_params.kind_of? Hash
|
141
|
+
debug "Got unexpected type #{rails_params.class} for env['action_dispatch.request.parameters']"
|
142
|
+
return
|
143
|
+
end
|
144
|
+
|
145
|
+
rails_params.each do |param, value|
|
146
|
+
if RAILS_SPECIAL_PARAMS.include?(param)
|
147
|
+
event.add_field("request.#{param}", value)
|
148
|
+
else
|
149
|
+
event.add_field("request.params.#{param}", value)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# overwrite 'name' (previously set in add_request_fields)
|
154
|
+
event.add_field('name', "#{rails_params[:controller]}##{rails_params[:action]}")
|
155
|
+
|
156
|
+
event.add_field('request.route', extract_rails_route(env))
|
157
|
+
end
|
158
|
+
|
159
|
+
def extract_rails_route(env)
|
160
|
+
# egregious and probably slow hack to get the formatted route
|
161
|
+
# TODO there must be a better way
|
162
|
+
routes = env['action_dispatch.routes']
|
163
|
+
request = ::ActionDispatch::Request.new(env)
|
164
|
+
|
165
|
+
formatted_route = nil
|
166
|
+
|
167
|
+
routes.router.recognize(request) do |route, _|
|
168
|
+
# make a hash where each param ("part") in the route is given its
|
169
|
+
# own name as a value, e.g. {:id => ":id"}
|
170
|
+
symbolic_params = {}
|
171
|
+
route.required_parts.each do |part|
|
172
|
+
symbolic_params[part] = ":#{part}"
|
173
|
+
end
|
174
|
+
# then ask the route to format itself using those param "values"
|
175
|
+
formatted_route = route.format(symbolic_params)
|
176
|
+
end
|
177
|
+
|
178
|
+
"#{env['REQUEST_METHOD']} #{formatted_route}"
|
179
|
+
rescue StandardError => e
|
180
|
+
debug "couldn't extract named route for request: #{e.class}: #{e}"
|
181
|
+
nil
|
182
|
+
end
|
183
|
+
|
108
184
|
def add_app_fields(event, env)
|
109
185
|
# Pull arbitrary metadata off `env` if the caller attached
|
110
186
|
# anything inside the Rack handler.
|
data/rack-honeycomb.gemspec
CHANGED
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_runtime_dependency 'libhoney', '>= 1.5.0'
|
35
35
|
spec.add_development_dependency 'rspec'
|
36
36
|
spec.add_development_dependency 'rack-test'
|
37
|
+
spec.add_development_dependency 'rails'
|
37
38
|
spec.add_development_dependency 'sinatra'
|
38
39
|
spec.add_development_dependency 'yard'
|
39
40
|
spec.add_development_dependency 'pry-byebug'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-honeycomb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- The Honeycomb.io Team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bump
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rails
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: sinatra
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -161,11 +175,14 @@ files:
|
|
161
175
|
- ".travis.yml"
|
162
176
|
- CONTRIBUTORS
|
163
177
|
- Gemfile
|
178
|
+
- Gemfile.rails3.rb
|
179
|
+
- Gemfile.rails4.rb
|
164
180
|
- LICENSE
|
165
181
|
- README.md
|
166
182
|
- Rakefile
|
167
183
|
- lib/rack-honeycomb.rb
|
168
184
|
- lib/rack-honeycomb/auto_install.rb
|
185
|
+
- lib/rack-honeycomb/railtie.rb
|
169
186
|
- lib/rack/honeycomb.rb
|
170
187
|
- lib/rack/honeycomb/middleware.rb
|
171
188
|
- lib/rack/honeycomb/version.rb
|