honeycomb-beeline 0.2.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8226a2444f449e489670d844e544ec8986ff40b32016ae9199031ae2fef1df8
4
- data.tar.gz: 11e5d5f9dc8dcc000e6a4cdb5dbebd35f0fe332c9ff5ab0a85f4b084f428f7bd
3
+ metadata.gz: 32263488f94bb0aa40611cb4706d001d62885b4de58f86ecd3ce8ccc0416cbc3
4
+ data.tar.gz: 53b773d27af7256c876009a824b8855418d80faa460815a5a3c54febe8ac6514
5
5
  SHA512:
6
- metadata.gz: 5370b82bf792605cf79bcf67a5930a0430f498e84f0472e5046b3a027d52761d0fbc3410b21374a2fc32c61beb20738defa47db30a80a650b9ede888b09bc13a
7
- data.tar.gz: c70d4cd7b0ea59c6642286db68b38bd0c637715e5468bfa096c8684486d93bcbebb0b7b037be01bb440f10c645199465a6500dfd54ab62fb602e467dea017a46
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
- ## Setup
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
- Setup requires minimal changes to your app. First add this line to your Gemfile:
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
- Then in your app's startup script - e.g. for a Rack app "config.ru" is a good
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
- ## Development
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
- ### Releasing a new version
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
- Travis will automatically upload tagged releases to Rubygems. To release a new
59
- version, run
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
- bump patch --tag # Or bump minor --tag, etc.
62
- git push --follow-tags
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).
@@ -1,6 +1,6 @@
1
1
  module Honeycomb
2
2
  module Beeline
3
3
  GEM_NAME = 'honeycomb-beeline'
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
6
6
  end
@@ -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
- client ||= begin
44
- unless options[:writekey] && options[:dataset]
45
- raise ArgumentError, "must specify writekey and dataset"
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 > 1
61
- raise ArgumentError, 'Honeycomb.after_init block should take 1 argument'
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
- @logger.info "Honeycomb inited" if @logger
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
- if auto.available?
19
- hook_label = instrumentation.name.sub(/::Honeycomb$/, '').downcase.to_sym
20
- after_init(hook_label) do |client|
21
- auto.auto_install!(honeycomb_client: client, logger: @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.2.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-05-30 00:00:00.000000000 Z
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.6.0
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.6.0
26
+ version: 1.8.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activerecord-honeycomb
29
29
  requirement: !ruby/object:Gem::Requirement