honeycomb-beeline 0.2.0 → 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/README.md +162 -11
- data/lib/honeycomb/beeline/version.rb +1 -1
- data/lib/honeycomb/client.rb +27 -12
- data/lib/honeycomb/instrumentations.rb +6 -4
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32263488f94bb0aa40611cb4706d001d62885b4de58f86ecd3ce8ccc0416cbc3
|
4
|
+
data.tar.gz: 53b773d27af7256c876009a824b8855418d80faa460815a5a3c54febe8ac6514
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bbb53742e2b9ccd2392893a260ce17d74e27eb46d9e20a9f56e60a0fca910cd5007734880a36d825f33ad188917a02dbb3d7dbf754e9950abfa04fb6a07b67e
|
7
|
+
data.tar.gz: 635c9e858d1393f4cd61ecbe375faeb60fc5b6bcdf8727fea662b10562371334a607e2ec757bc96cc9ec157c2f73bf828a586547de7091c0f5c47a8f0d685c4d
|
data/README.md
CHANGED
@@ -4,15 +4,21 @@ The Honeycomb Beeline for Ruby is the fastest path to observability for your
|
|
4
4
|
Ruby apps. It understands the common packages you use and automatically
|
5
5
|
instruments them to send useful events to Honeycomb.
|
6
6
|
|
7
|
-
|
7
|
+
Sign up for a [Honeycomb trial](https://ui.honeycomb.io/signup) to obtain a
|
8
|
+
writekey before starting.
|
9
|
+
|
10
|
+
## Installation
|
8
11
|
|
9
|
-
|
12
|
+
Add `honeycomb-beeline` to your Gemfile:
|
10
13
|
|
11
14
|
```ruby
|
12
15
|
gem 'honeycomb-beeline'
|
13
16
|
```
|
17
|
+
Now run `bundle install` to install the gem.
|
14
18
|
|
15
|
-
|
19
|
+
## Setup
|
20
|
+
|
21
|
+
In your app's startup script - e.g. for a Rack app "config.ru" is a good
|
16
22
|
place - add the following code:
|
17
23
|
|
18
24
|
```ruby
|
@@ -21,8 +27,6 @@ require 'honeycomb-beeline'
|
|
21
27
|
Honeycomb.init
|
22
28
|
```
|
23
29
|
|
24
|
-
Now run `bundle install` to install the gem.
|
25
|
-
|
26
30
|
## Configuration
|
27
31
|
|
28
32
|
You'll need to configure your Honeycomb writekey so that your app can
|
@@ -51,13 +55,160 @@ Honeycomb.init(writekey: '<MY HONEYCOMB WRITEKEY>', dataset: 'my-app')
|
|
51
55
|
Note that you should not check your Honeycomb writekey into version control, as
|
52
56
|
it is sensitive and allows sending data to your Honeycomb account.
|
53
57
|
|
54
|
-
##
|
58
|
+
## Example questions
|
59
|
+
|
60
|
+
Now your app is instrumented and sending events, try using Honeycomb to ask
|
61
|
+
these questions:
|
62
|
+
|
63
|
+
* Which of my app's routes are the slowest?
|
64
|
+
```
|
65
|
+
BREAKDOWN: request.path
|
66
|
+
CALCULATE: P99(duration_ms)
|
67
|
+
FILTER: type == http_server
|
68
|
+
ORDER BY: P99(duration_ms) DESC
|
69
|
+
```
|
70
|
+
* Where's my app spending the most time?
|
71
|
+
```
|
72
|
+
BREAKDOWN: type
|
73
|
+
CALCULATE: SUM(duration_ms)
|
74
|
+
ORDER BY: SUM(duration_ms) DESC
|
75
|
+
```
|
76
|
+
* Which users are using the endpoint that I'd like to deprecate? First add a
|
77
|
+
[custom field](#adding-additional-context) `user.email`, then try:
|
78
|
+
```
|
79
|
+
BREAKDOWN: app.user.email
|
80
|
+
CALCULATE: COUNT
|
81
|
+
FILTER: request.path == /my/deprecated/endpoint
|
82
|
+
```
|
83
|
+
|
84
|
+
## Example event
|
85
|
+
|
86
|
+
Here is an example of an `http_server` event (recording that your web app
|
87
|
+
processed an incoming HTTP request) emitted by the Beeline:
|
88
|
+
|
89
|
+
```json
|
90
|
+
{
|
91
|
+
"meta.beeline_version": "0.2.0",
|
92
|
+
"meta.local_hostname": "killerbee",
|
93
|
+
"service_name": "my-test-app",
|
94
|
+
"meta.package": "rack",
|
95
|
+
"meta.package_version": "1.3",
|
96
|
+
"type": "http_server",
|
97
|
+
"name": "GET /dashboard",
|
98
|
+
"request.method": "GET",
|
99
|
+
"request.path": "/dashboard",
|
100
|
+
"request.protocol": "https",
|
101
|
+
"request.http_version": "HTTP/1.1",
|
102
|
+
"request.host": "my-test-app.example.com",
|
103
|
+
"request.remote_addr": "172.217.1.238",
|
104
|
+
"request.header.user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
|
105
|
+
"trace.trace_id": "b694512a-833f-4b35-be5f-6c742ba18e12",
|
106
|
+
"trace.span_id": "c35cc326-ed90-4881-a4a8-68526d252f2e",
|
107
|
+
"response.status_code": 200,
|
108
|
+
"duration_ms": 303.057396
|
109
|
+
}
|
110
|
+
```
|
111
|
+
|
112
|
+
## Adding additional context
|
113
|
+
|
114
|
+
The Beeline will automatically instrument your incoming HTTP requests, database
|
115
|
+
queries and outbound HTTP requests to send events to Honeycomb. However, it can
|
116
|
+
be very helpful to extend these events with additional context specific to your
|
117
|
+
app. You can add your own fields by calling `Rack::Honeycomb.add_field`. For
|
118
|
+
example, this snippet shows how to associate the currently logged-in user with
|
119
|
+
each `http_server` event:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
get '/hello' do
|
123
|
+
user = authenticate_user()
|
124
|
+
|
125
|
+
# this will add a custom field 'app.user.email' to the http_server event
|
126
|
+
Rack::Honeycomb.add_field(env, 'user.email', user.email)
|
127
|
+
|
128
|
+
"Hello, #{user.name}!"
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
## Instrumented packages
|
133
|
+
|
134
|
+
The Beeline will automatically send the following events if you are using one of
|
135
|
+
the listed packages:
|
136
|
+
|
137
|
+
### `http_server` (incoming HTTP requests)
|
138
|
+
|
139
|
+
* [Sinatra](http://sinatrarb.com) - via [rack-honeycomb](https://github.com/honeycombio/rack-honeycomb)
|
140
|
+
* Any other [Rack](https://rack.github.io)-based web app - via [rack-honeycomb](https://github.com/honeycombio/rack-honeycomb) (requires manually adding the middleware)
|
141
|
+
|
142
|
+
### `db` (database queries)
|
143
|
+
|
144
|
+
* [ActiveRecord](https://rubygems.org/gems/activerecord) - via
|
145
|
+
[activerecord-honeycomb](https://github.com/honeycombio/activerecord-honeycomb)
|
146
|
+
* [Sequel](https://sequel.jeremyevans.net/) - via
|
147
|
+
[sequel-honeycomb](https://github.com/honeycombio/sequel-honeycomb)
|
148
|
+
|
149
|
+
### `http_client` (outbound HTTP requests)
|
150
|
+
|
151
|
+
* [Faraday](https://github.com/lostisland/faraday) - via
|
152
|
+
[faraday-honeycomb](https://github.com/honeycombio/faraday-honeycomb)
|
153
|
+
|
154
|
+
## Known limitations
|
155
|
+
|
156
|
+
* The Beeline will try to autodetect your web framework and automatically
|
157
|
+
install its middleware. Currently this only works for Sinatra apps, and
|
158
|
+
also fails in some more exotic configurations of Sinatra. If you find you
|
159
|
+
aren't seeing any events for processing web requests, you can install the
|
160
|
+
[middleware](https://www.rubydoc.info/gems/rack-honeycomb) manually: e.g.
|
161
|
+
`use Rack::Honeycomb::Middleware`.
|
162
|
+
* Rails apps are not supported currently; instead, use our [Rails
|
163
|
+
integration](https://github.com/honeycombio/honeycomb-rails).
|
164
|
+
* Alternative concurrency models such as EventMachine or Celluloid are not
|
165
|
+
currently supported.
|
166
|
+
|
167
|
+
If support for one of these scenarios is important to you, please [let us
|
168
|
+
know](#get-in-touch)!
|
169
|
+
|
170
|
+
## Troubleshooting
|
55
171
|
|
56
|
-
|
172
|
+
If you've setup the Beeline as above but you aren't seeing data for your app in
|
173
|
+
Honeycomb, or you're seeing errors on startup, here are a few things to try:
|
57
174
|
|
58
|
-
|
59
|
-
|
175
|
+
### Debug mode
|
176
|
+
|
177
|
+
To verify the Beeline is working as expected, try running it in debug mode:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
Honeycomb.init(debug: true)
|
60
181
|
```
|
61
|
-
|
62
|
-
|
182
|
+
|
183
|
+
Alternatively, you can also enable debug mode with no code changes by setting
|
184
|
+
`HONEYCOMB_DEBUG=true` in your environment.
|
185
|
+
|
186
|
+
In debug mode, the Beeline will not send any events to Honeycomb, but will
|
187
|
+
instead print them to your app's standard error. It will also log startup
|
188
|
+
messages to standard error.
|
189
|
+
|
190
|
+
### Logging
|
191
|
+
|
192
|
+
By default the Beeline will log errors but otherwise keep quiet. To see more
|
193
|
+
detail about what it's doing, you can pass a logger object (compliant with the
|
194
|
+
[stdlib Logger API](https://ruby-doc.org/stdlib-2.4.1/libdoc/logger/rdoc/)) to
|
195
|
+
`Honeycomb.init`:
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
require 'logger'
|
199
|
+
logger = Logger.new($stderr)
|
200
|
+
logger.level = :info # determine how much detail you want to see
|
201
|
+
Honeycomb.init(logger: logger)
|
63
202
|
```
|
203
|
+
|
204
|
+
A level of `:debug` will show you detail about each library being instrumented,
|
205
|
+
whereas a level of `:info` will just print a few progress messages.
|
206
|
+
|
207
|
+
### Get in touch
|
208
|
+
|
209
|
+
This beeline is still young, so please reach out to
|
210
|
+
[support@honeycomb.io](mailto:support@honeycomb.io) or ping us with the chat
|
211
|
+
bubble on [our website](https://www.honeycomb.io){target=_blank} for assistance.
|
212
|
+
We also welcome [bug
|
213
|
+
reports](https://github.com/honeycombio/beeline-ruby/issues) and
|
214
|
+
[contributions](https://github.com/honeycombio/beeline-ruby/blob/master/CONTRIBUTING.md).
|
data/lib/honeycomb/client.rb
CHANGED
@@ -2,6 +2,7 @@ require 'honeycomb/beeline/version'
|
|
2
2
|
|
3
3
|
require 'libhoney'
|
4
4
|
|
5
|
+
require 'logger'
|
5
6
|
require 'socket'
|
6
7
|
|
7
8
|
module Honeycomb
|
@@ -16,14 +17,19 @@ module Honeycomb
|
|
16
17
|
dataset: ENV['HONEYCOMB_DATASET'],
|
17
18
|
service_name: ENV['HONEYCOMB_SERVICE'] || dataset,
|
18
19
|
without: [],
|
20
|
+
debug: ENV.key?('HONEYCOMB_DEBUG'),
|
19
21
|
logger: nil,
|
20
22
|
**options
|
21
23
|
)
|
22
24
|
reset
|
23
25
|
|
24
|
-
@logger = logger
|
25
26
|
@without = without
|
26
27
|
@service_name = service_name
|
28
|
+
@logger = logger || Logger.new($stderr).tap {|l| l.level = Logger::WARN }
|
29
|
+
@debug = debug
|
30
|
+
if debug
|
31
|
+
@logger ||= Logger.new($stderr)
|
32
|
+
end
|
27
33
|
|
28
34
|
options = options.merge(writekey: writekey, dataset: dataset)
|
29
35
|
@client = new_client(options)
|
@@ -40,11 +46,17 @@ module Honeycomb
|
|
40
46
|
client = options.delete :client
|
41
47
|
|
42
48
|
options = {user_agent_addition: USER_AGENT_SUFFIX}.merge(options)
|
43
|
-
|
44
|
-
|
45
|
-
|
49
|
+
if @debug
|
50
|
+
raise ArgumentError, "can't specify both client and debug options", caller if client
|
51
|
+
@logger.info 'logging events to standard error instead of sending to Honeycomb' if @logger
|
52
|
+
client = Libhoney::LogClient.new(verbose: true, **options)
|
53
|
+
else
|
54
|
+
client ||= if options[:writekey] && options[:dataset]
|
55
|
+
Libhoney::Client.new(options)
|
56
|
+
else
|
57
|
+
@logger.warn "#{self.name}: no #{options[:writekey] ? 'dataset' : 'writekey'} configured, disabling sending events" if @logger
|
58
|
+
Libhoney::NullClient.new(options)
|
46
59
|
end
|
47
|
-
Libhoney::Client.new(options)
|
48
60
|
end
|
49
61
|
client.add_field 'meta.beeline_version', Beeline::VERSION
|
50
62
|
client.add_field 'meta.local_hostname', Socket.gethostname rescue nil
|
@@ -56,9 +68,11 @@ module Honeycomb
|
|
56
68
|
raise ArgumentError unless block_given?
|
57
69
|
|
58
70
|
hook = if block.arity == 0
|
59
|
-
->(_) { block.call }
|
60
|
-
elsif block.arity
|
61
|
-
|
71
|
+
->(_, _) { block.call }
|
72
|
+
elsif block.arity == 1
|
73
|
+
->(client, _) { block.call client }
|
74
|
+
elsif block.arity > 2
|
75
|
+
raise ArgumentError, 'Honeycomb.after_init block should take 2 arguments'
|
62
76
|
else
|
63
77
|
block
|
64
78
|
end
|
@@ -87,6 +101,7 @@ module Honeycomb
|
|
87
101
|
@logger = nil
|
88
102
|
@without = nil
|
89
103
|
@service_name = nil
|
104
|
+
@debug = nil
|
90
105
|
@client = nil
|
91
106
|
@initialized = false
|
92
107
|
end
|
@@ -100,14 +115,14 @@ module Honeycomb
|
|
100
115
|
if @without.include?(label)
|
101
116
|
@logger.debug "Skipping hook '#{label}' due to opt-out" if @logger
|
102
117
|
else
|
103
|
-
block.call @client
|
118
|
+
block.call @client, @logger
|
104
119
|
end
|
105
120
|
rescue => e
|
106
|
-
warn "Honeycomb.init hook '#{label}' raised #{e.class}: #{e}"
|
121
|
+
@logger.warn "Honeycomb.init hook '#{label}' raised #{e.class}: #{e}" if @logger
|
107
122
|
end
|
108
123
|
end
|
109
124
|
|
110
|
-
after_init :log do
|
111
|
-
|
125
|
+
after_init :log do |_, logger|
|
126
|
+
logger.info "Honeycomb inited" if logger
|
112
127
|
end
|
113
128
|
end
|
@@ -15,10 +15,12 @@ module Honeycomb
|
|
15
15
|
|
16
16
|
INSTRUMENTATIONS.each do |instrumentation|
|
17
17
|
auto = instrumentation::AutoInstall
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
auto.auto_install!(honeycomb_client: client, logger:
|
18
|
+
hook_label = instrumentation.name.sub(/::Honeycomb$/, '').downcase.to_sym
|
19
|
+
after_init(hook_label) do |client, logger|
|
20
|
+
if auto.available?(logger: logger)
|
21
|
+
auto.auto_install!(honeycomb_client: client, logger: logger)
|
22
|
+
else
|
23
|
+
logger.debug "Not autoinitialising #{instrumentation.name}" if logger
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: honeycomb-beeline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Stokes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: libhoney
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.8.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.8.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord-honeycomb
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|