rack-honeycomb 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|