libhoney 1.10.1 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 701a19cd4bde8de2dfa4a6f3ab46e9a2b6aa08df13e1cecb7b7b0fccb0fe7d4a
4
- data.tar.gz: 8179e03fb6b2711abda9dfb26ffffe6d3e8c5fae600fe917301a02cc5fe6fb39
3
+ metadata.gz: dd29a10e412de6aef7a21988cdf51e253dbfdfa4e3c53a7161f617b27dbcc81a
4
+ data.tar.gz: 25c577fcda6470dd420a292a08cec6632e18889ac1a0ac3bc82c166258860216
5
5
  SHA512:
6
- metadata.gz: 0175476abe1c2bfc530964fd3f5750fadbfc97df3661214975dc5ac2cfe033eace5c575a81c59cb5b977f3ed51cd4f802bba43e468c2fa297700904f5f0226ef
7
- data.tar.gz: eea06aab450dc777b1598c23ecda377fbd888423419406568fb66a7b005609028b3f58582d887eb23f1e871b659e1eb8afd6d6355b1c1d82fcf85ef5a2f3d135
6
+ metadata.gz: 85133ade7a0a6cb208ed0912a6a001fe79d0f8e6c35b7d084512e7e57ac47df94f9181e8428df535f620f9bc4ad9333582c945a5aa72f8e9a0de35a976ce7460
7
+ data.tar.gz: bf7c51ec4d23ae23aaed304c670aed2b08c0f7d51f6c8c7a6c139161f20d70e5c5691b143f00dbc8af5c3b6b075e894a9836e9316e4fce0e7f592527a74b11e7
data/.rubocop.yml ADDED
@@ -0,0 +1,26 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.2
5
+
6
+ Style/Documentation:
7
+ Enabled: false
8
+
9
+ Lint/RescueException:
10
+ Exclude:
11
+ - 'lib/libhoney/transmission.rb'
12
+
13
+ Metrics/ClassLength:
14
+ Exclude:
15
+ - test/*
16
+
17
+ Metrics/MethodLength:
18
+ Max: 25
19
+ Exclude:
20
+ - lib/libhoney/transmission.rb
21
+
22
+ Metrics/LineLength:
23
+ Max: 115
24
+ Exclude:
25
+ - lib/libhoney/client.rb
26
+ - lib/libhoney/builder.rb
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,36 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2018-09-24 20:37:04 -0700 using RuboCop version 0.59.2.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 3
10
+ Lint/HandleExceptions:
11
+ Exclude:
12
+ - 'lib/libhoney/client.rb'
13
+ - 'lib/libhoney/transmission.rb'
14
+
15
+ # Offense count: 7
16
+ Metrics/AbcSize:
17
+ Max: 35
18
+
19
+ # Offense count: 1
20
+ # Configuration parameters: CountComments, ExcludedMethods.
21
+ # ExcludedMethods: refine
22
+ Metrics/BlockLength:
23
+ Max: 27
24
+
25
+ # Offense count: 2
26
+ Metrics/CyclomaticComplexity:
27
+ Max: 8
28
+
29
+ # Offense count: 2
30
+ # Configuration parameters: CountKeywordArgs.
31
+ Metrics/ParameterLists:
32
+ Max: 12
33
+
34
+ # Offense count: 1
35
+ Metrics/PerceivedComplexity:
36
+ Max: 8
data/.travis.yml CHANGED
@@ -4,6 +4,9 @@ rvm:
4
4
  - 2.3
5
5
  - 2.4
6
6
  - 2.5
7
+ script:
8
+ - bundle exec rake rubocop
9
+ - bundle exec rake test
7
10
  deploy:
8
11
  provider: rubygems
9
12
  api_key:
data/CONTRIBUTORS CHANGED
@@ -9,3 +9,4 @@ Ben Hartshorne <ben@honeycomb.io>
9
9
  Eben Freeman <eben@honeycomb.io>
10
10
  Ryan King <ryan@theryanking.com>
11
11
  Paul Sadauskas <psadauskas@gmail.com>
12
+ Shane Becker <veganstraightedge@gmail.com>
data/README.md CHANGED
@@ -1,116 +1,15 @@
1
1
  # libhoney [![Build Status](https://travis-ci.org/honeycombio/libhoney-rb.svg?branch=master)](https://travis-ci.org/honeycombio/libhoney-rb) [![Gem Version](https://badge.fury.io/rb/libhoney.svg)](https://badge.fury.io/rb/libhoney)
2
2
 
3
- Ruby gem for sending events to [Honeycomb](https://honeycomb.io). (For more information, see the [documentation](https://honeycomb.io/docs/) and [Ruby SDK guide](https://honeycomb.io/docs/connect/ruby).)
3
+ Ruby gem for sending events to [Honeycomb](https://www.honeycomb.io), a service for debugging your software in production.
4
4
 
5
- ## Installation
5
+ Requires Ruby 2.2 or greater.
6
6
 
7
- To install the stable release:
7
+ - [Usage and Examples](https://docs.honeycomb.io/sdk/ruby/)
8
+ - [API Reference](https://www.rubydoc.info/gems/libhoney)
8
9
 
9
- ```
10
- gem install libhoney
11
- ```
12
-
13
- or add `libhoney` to your `Gemfile`:
14
-
15
- ```ruby
16
- gem 'libhoney'
17
-
18
- # or, to follow the bleeding edge:
19
- # gem 'libhoney', git: 'https://github.com/honeycombio/libhoney-rb.git'
20
- ```
21
-
22
- This gem has some native dependencies, so if you see an error along the lines of "Failed to build gem native extension", you may need to install the Ruby development headers and a C++ compiler. e.g. on Ubuntu:
23
-
24
- ```
25
- sudo apt-get install build-essential ruby-dev
26
- ```
27
-
28
- Note that `libhoney` requires Ruby 2.2 or greater.
29
-
30
-
31
- ## Documentation
32
-
33
- An API reference is available at [rubydoc.info/gems/libhoney](http://www.rubydoc.info/gems/libhoney).
34
-
35
- ## Example Usage
36
-
37
- Honeycomb can calculate all sorts of statistics, so send the values you care about and let us crunch the averages, percentiles, lower/upper bounds, cardinality -- whatever you want -- for you.
38
-
39
- ```ruby
40
- require 'libhoney'
41
-
42
- # Create a client instance
43
- honeycomb = Libhoney::Client.new(
44
- # Use an environment variable to set your write key with something like
45
- # `writekey: ENV['HONEYCOMB_WRITEKEY']`,
46
- writekey: 'YOUR_WRITE_KEY',
47
- dataset: 'honeycomb-ruby-example'
48
- )
49
-
50
- honeycomb.send_now({
51
- duration_ms: 153.12,
52
- method: 'get',
53
- hostname: 'appserver15',
54
- payload_length: 27
55
- })
56
-
57
- # Call close to flush any pending calls to Honeycomb
58
- honeycomb.close
59
- ```
60
-
61
- Check out the documentation for [`Libhoney::Client`](http://www.rubydoc.info/gems/libhoney/Libhoney/Client) for more detailed API documentation.
62
-
63
- You can find a more complete example demonstrating usage in [`example/fact.rb`](example/fact.rb)
64
-
65
- ## Debugging instrumentation
66
-
67
- If you've instrumented your code to send events to Honeycomb, you may want to
68
- verify that you're sending the events you expected at the right time with the
69
- desired fields. To support this use case, `libhoney` provides a
70
- [`LogClient`](http://www.rubydoc.info/gems/libhoney/Libhoney/LogClient) that
71
- outputs events to standard error, which you can swap in for the usual `Client`.
72
- Example usage:
73
-
74
- ```ruby
75
- honeycomb = Libhoney::LogClient.new
76
-
77
- my_app = MyApp.new(..., honeycomb, ...)
78
- my_app.do_stuff
79
-
80
- # should output events to standard error
81
- ```
82
-
83
- Note that this will disable sending events to Honeycomb, so you'll want to
84
- revert this change once you've verified that the events are coming through
85
- appropriately.
86
-
87
- ## Testing instrumented code
88
-
89
- Once you've instrumented your code to send events to Honeycomb, you may want to
90
- consider writing tests that verify your code is producing the events you expect,
91
- annotating them with the right information, etc. That way, if your code changes
92
- and breaks the instrumentation, you'll find out straight away, instead of at 3am
93
- when you need that data available for debugging!
94
-
95
- To support this use case, `libhoney` provides a
96
- [`TestClient`](http://www.rubydoc.info/gems/libhoney/Libhoney/TestClient) which
97
- you can swap in for the usual `Client`. Example usage:
98
-
99
- ```ruby
100
- fakehoney = Libhoney::TestClient.new
101
-
102
- my_app = MyApp.new(..., fakehoney, ...)
103
- my_app.do_stuff
104
-
105
- expect(fakehoney.events.size).to eq 3
106
-
107
- first_event = fakehoney.events[0]
108
- expect(first_event.data['hovercraft_contents']).to eq 'Eels'
109
- ```
10
+ For tracing support and automatic instrumentation of Sinatra, Rack, ActiveRecord, and other frameworks, check out our [Beeline for Ruby](https://github.com/honeycombio/beeline-ruby).
110
11
 
111
- For more detail see the docs for
112
- [`TestClient`](http://www.rubydoc.info/gems/libhoney/Libhoney/TestClient) and
113
- [`Event`](http://www.rubydoc.info/gems/libhoney/Libhoney/Event).
12
+ For automatic instrumentation of Ruby on Rails, check out our [Rails integration](https://github.com/honeycombio/honeycomb-rails).
114
13
 
115
14
  ## Contributions
116
15
 
data/Rakefile CHANGED
@@ -1,24 +1,27 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
  require 'yard'
3
3
 
4
- require "rake/testtask"
4
+ require 'rake/testtask'
5
5
  Rake::TestTask.new(:test) do |t|
6
6
  t.libs << 'test'
7
- t.libs << "lib"
7
+ t.libs << 'lib'
8
8
  t.test_files = FileList['test/**/*_test.rb']
9
9
  end
10
10
 
11
11
  YARD::Rake::YardocTask.new(:doc)
12
12
 
13
- require "yardstick/rake/measurement"
13
+ require 'yardstick/rake/measurement'
14
14
  Yardstick::Rake::Measurement.new do |measurement|
15
- measurement.output = "measurement/report.txt"
15
+ measurement.output = 'measurement/report.txt'
16
16
  end
17
17
 
18
- require "yardstick/rake/verify"
18
+ require 'yardstick/rake/verify'
19
19
  Yardstick::Rake::Verify.new do |verify|
20
20
  verify.require_exact_threshold = false
21
21
  verify.threshold = 55
22
22
  end
23
23
 
24
- task :default => :test
24
+ require 'rubocop/rake_task'
25
+ RuboCop::RakeTask.new
26
+
27
+ task default: %i[rubocop test]
@@ -0,0 +1,78 @@
1
+ lib = File.expand_path('../lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'libhoney'
5
+
6
+ # replace this with yours from https://ui.honeycomb.com/account
7
+ writekey = '7aefa39399a474bd9f414a8e3f8d9691'
8
+ dataset = 'factorial'
9
+
10
+ def factorial(number)
11
+ return -1 * factorial(abs(number)) if number < 0
12
+ return 1 if number.zero?
13
+
14
+ number * factorial(number - 1)
15
+ end
16
+
17
+ # run factorial. libh_builder comes with some fields already populated
18
+ # (namely, "version", "num_threads", and "range")
19
+ def run_factorial(low, high, libh_builder)
20
+ (low..high).each do |i|
21
+ event = libh_builder.event
22
+ event.metadata = { fn: 'run_factorial', i: i }
23
+
24
+ event.with_timer('factorial') do
25
+ result = factorial(10 + i)
26
+ event.add_field('retval', result)
27
+ end
28
+
29
+ event.send
30
+ end
31
+ end
32
+
33
+ def read_responses(response_queue)
34
+ loop do
35
+ response = response_queue.pop
36
+ break if response.nil?
37
+
38
+ puts "Sent: Event with metadata #{response.metadata} in #{response.duration * 1000}ms."
39
+ puts "Got: Response code #{response.status_code}"
40
+ puts
41
+ end
42
+ end
43
+
44
+ libhoney = Libhoney::Client.new(writekey: writekey,
45
+ dataset: dataset,
46
+ max_concurrent_batches: 1)
47
+
48
+ responses = libhoney.responses
49
+
50
+ Thread.new do
51
+ begin
52
+ # attach fields to top-level instance
53
+ libhoney.add_field('version', '3.4.5')
54
+
55
+ a_proc = proc { Thread.list.select { |thread| thread.status == 'run' }.count }
56
+ libhoney.add_dynamic_field('num_threads', a_proc)
57
+
58
+ event = libhoney.event
59
+ event.metadata = { fn: 'work_thread' }
60
+ event.add_field('start_time', Time.now.iso8601(3))
61
+ event.with_timer 'run_fact_low_dur_ms' do
62
+ run_factorial(1, 20, libhoney.builder(range: 'low'))
63
+ end
64
+ event.with_timer 'run_fact_high_dur_ms' do
65
+ run_factorial(31, 40, libhoney.builder(range: 'high'))
66
+ end
67
+ event.add_field('end_time', Time.now.iso8601(3))
68
+ # sends an event with "version", "num_threads", "start_time", "end_time",
69
+ # "run_fact_low_dur_ms", "run_fact_high_dur_ms"
70
+ event.send
71
+
72
+ libhoney.close
73
+ rescue StandardError => e
74
+ puts e
75
+ end
76
+ end
77
+
78
+ read_responses(responses)
@@ -11,21 +11,21 @@ module Libhoney
11
11
  def initialize(libhoney, parent_builder, fields = {}, dyn_fields = {})
12
12
  @libhoney = libhoney
13
13
 
14
- @fields = {}
14
+ @fields = {}
15
15
  @dyn_fields = {}
16
16
 
17
- if parent_builder != nil
18
- @writekey = parent_builder.writekey
19
- @dataset = parent_builder.dataset
17
+ unless parent_builder.nil?
18
+ @writekey = parent_builder.writekey
19
+ @dataset = parent_builder.dataset
20
20
  @sample_rate = parent_builder.sample_rate
21
- @api_host = parent_builder.api_host
21
+ @api_host = parent_builder.api_host
22
+
22
23
  @fields.merge!(parent_builder.fields)
23
24
  @dyn_fields.merge!(parent_builder.dyn_fields)
24
25
  end
25
26
 
26
27
  @fields.merge!(fields)
27
28
  @dyn_fields.merge!(dyn_fields)
28
- self
29
29
  end
30
30
 
31
31
  # adds a group of field->values to the events created from this builder.
@@ -59,15 +59,23 @@ module Libhoney
59
59
  # adds a single field->dynamic value function, which is invoked to supply values when events are created from this builder.
60
60
  #
61
61
  # @param name [string] the name of the field to add to events.
62
- # @param fn [#call] the function called to generate the value for this field.
62
+ # @param proc [#call] the function called to generate the value for this field.
63
63
  # @return [self] this Builder instance.
64
64
  # @example
65
65
  # builder.add_dynamic_field("process_heapUsed", Proc.new { Thread.list.select {|thread| thread.status == "run"}.count })
66
- def add_dynamic_field(name, fn)
67
- @dyn_fields[name] = fn
66
+ def add_dynamic_field(name, proc)
67
+ @dyn_fields[name] = proc
68
68
  end
69
69
 
70
- # creates and sends an event, including all builder fields/dyn_fields, as well as anything in the optional data parameter.
70
+ # @deprecated
71
+ # Creates and sends an event, including all global builder fields/dyn_fields, as well as anything in the optional data parameter.
72
+ #
73
+ # Equivalent to:
74
+ # ev = builder.event
75
+ # ev.add(data)
76
+ # ev.send
77
+ #
78
+ # May be removed in a future major release
71
79
  #
72
80
  # @param data [Hash<String=>any>] optional field->value mapping to add to the event sent.
73
81
  # @return [self] this Builder instance
@@ -78,9 +86,9 @@ module Libhoney
78
86
  # :additionalField => value
79
87
  # }
80
88
  def send_now(data = {})
81
- ev = self.event
89
+ ev = event
82
90
  ev.add(data)
83
- ev.send()
91
+ ev.send
84
92
  self
85
93
  end
86
94
 
@@ -1,26 +1,27 @@
1
- require 'thread'
2
1
  require 'time'
3
2
  require 'json'
4
3
  require 'http'
5
4
 
6
5
  require 'libhoney/null_transmission'
7
6
 
8
- # define a few additions that proxy access through Client's builder. makes Client much tighter.
7
+ # Define a few additions that proxy access through Client's builder. Makes Client much tighter.
9
8
  class Class
10
9
  def builder_attr_accessor(*args)
11
10
  args.each do |arg|
12
- self.class_eval("def #{arg};@builder.#{arg};end")
13
- self.class_eval("def #{arg}=(val);@builder.#{arg}=val;end")
11
+ class_eval("def #{arg};@builder.#{arg};end", __FILE__, __LINE__)
12
+ class_eval("def #{arg}=(val);@builder.#{arg}=val;end", __FILE__, __LINE__)
14
13
  end
15
14
  end
15
+
16
16
  def builder_attr_reader(*args)
17
17
  args.each do |arg|
18
- self.class_eval("def #{arg};@builder.#{arg};end")
18
+ class_eval("def #{arg};@builder.#{arg};end", __FILE__, __LINE__)
19
19
  end
20
20
  end
21
+
21
22
  def builder_attr_writer(*args)
22
23
  args.each do |arg|
23
- self.class_eval("def #{arg}=(val);@builder.#{arg}=val;end")
24
+ class_eval("def #{arg}=(val);@builder.#{arg}=val;end", __FILE__, __LINE__)
24
25
  end
25
26
  end
26
27
  end
@@ -49,6 +50,8 @@ module Libhoney
49
50
  # Note that by default, the max queue size is 1000. If the queue gets bigger than that, we start dropping events.
50
51
  #
51
52
  class Client
53
+ API_HOST = 'https://api.honeycomb.io/'.freeze
54
+
52
55
  # Instantiates libhoney and prepares it to send events to Honeycomb.
53
56
  #
54
57
  # @param writekey [String] the write key from your honeycomb team (required)
@@ -61,7 +64,7 @@ module Libhoney
61
64
  def initialize(writekey: nil,
62
65
  dataset: nil,
63
66
  sample_rate: 1,
64
- api_host: 'https://api.honeycomb.io/',
67
+ api_host: API_HOST,
65
68
  user_agent_addition: nil,
66
69
  transmission: nil,
67
70
  block_on_send: false,
@@ -71,40 +74,41 @@ module Libhoney
71
74
  max_concurrent_batches: 10,
72
75
  pending_work_capacity: 1000)
73
76
  # check for insanity
74
- raise Exception.new('libhoney: max_concurrent_batches must be greater than 0') if max_concurrent_batches < 1
75
- raise Exception.new('libhoney: sample rate must be greater than 0') if sample_rate < 1
77
+ raise Exception, 'libhoney: max_concurrent_batches must be greater than 0' if max_concurrent_batches < 1
78
+ raise Exception, 'libhoney: sample rate must be greater than 0' if sample_rate < 1
79
+
80
+ unless Gem::Dependency.new('ruby', '~> 2.2').match?('ruby', RUBY_VERSION)
81
+ raise Exception, 'libhoney: Ruby versions < 2.2 are not supported'
82
+ end
76
83
 
77
- raise Exception.new("libhoney: Ruby versions < 2.2 are not supported") if !Gem::Dependency.new("ruby", "~> 2.2").match?("ruby", RUBY_VERSION)
78
84
  @builder = Builder.new(self, nil)
79
- @builder.writekey = writekey
80
- @builder.dataset = dataset
85
+
86
+ @builder.writekey = writekey
87
+ @builder.dataset = dataset
81
88
  @builder.sample_rate = sample_rate
82
- @builder.api_host = api_host
89
+ @builder.api_host = api_host
83
90
 
84
- @tx = transmission
85
- if !@tx && !(writekey && dataset)
91
+ @transmission = transmission
92
+ if !@transmission && !(writekey && dataset)
86
93
  # if no writekey or dataset are configured, and we didn't override the
87
94
  # transmission (e.g. to a MockTransmissionClient), that's almost
88
95
  # certainly a misconfiguration, even though it's possible to override
89
96
  # them on a per-event basis. So let's handle the misconfiguration
90
- # early rather than potentially throwing thousands of exceptions at
91
- # runtime.
97
+ # early rather than potentially throwing thousands of exceptions at runtime.
92
98
  warn "#{self.class.name}: no #{writekey ? 'dataset' : 'writekey'} configured, disabling sending events"
93
- @tx = NullTransmissionClient.new
99
+ @transmission = NullTransmissionClient.new
94
100
  end
95
101
 
96
102
  @user_agent_addition = user_agent_addition
97
103
 
98
- @block_on_send = block_on_send
99
- @block_on_responses = block_on_responses
100
- @max_batch_size = max_batch_size
101
- @send_frequency = send_frequency
104
+ @block_on_send = block_on_send
105
+ @block_on_responses = block_on_responses
106
+ @max_batch_size = max_batch_size
107
+ @send_frequency = send_frequency
102
108
  @max_concurrent_batches = max_concurrent_batches
103
- @pending_work_capacity = pending_work_capacity
104
- @responses = SizedQueue.new(2 * @pending_work_capacity)
105
- @lock = Mutex.new
106
-
107
- self
109
+ @pending_work_capacity = pending_work_capacity
110
+ @responses = SizedQueue.new(2 * @pending_work_capacity)
111
+ @lock = Mutex.new
108
112
  end
109
113
 
110
114
  builder_attr_accessor :writekey, :dataset, :sample_rate, :api_host
@@ -121,11 +125,11 @@ module Libhoney
121
125
  @builder.builder(fields, dyn_fields)
122
126
  end
123
127
 
124
- ##
125
128
  # Nuke the queue and wait for inflight requests to complete before returning.
126
129
  # If you set drain=false, all queued requests will be dropped on the floor.
127
- def close(drain=true)
128
- return @tx.close(drain) if @tx
130
+ def close(drain = true)
131
+ return @transmission.close(drain) if @transmission
132
+
129
133
  0
130
134
  end
131
135
 
@@ -158,26 +162,34 @@ module Libhoney
158
162
  # adds a single field->dynamic value function to the global Builder.
159
163
  #
160
164
  # @param name [String] name of field to add.
161
- # @param fn [#call] function that will be called to generate the value whenever an event is created.
165
+ # @param proc [#call] function that will be called to generate the value whenever an event is created.
162
166
  # @return [self] this libhoney instance.
163
167
  # @example
164
168
  # honey.add_dynamic_field("active_threads", Proc.new { Thread.list.select {|thread| thread.status == "run"}.count })
165
- def add_dynamic_field(name, fn)
166
- @builder.add_dynamic_field(name, fn)
169
+ def add_dynamic_field(name, proc)
170
+ @builder.add_dynamic_field(name, proc)
167
171
  self
168
172
  end
169
173
 
170
- # creates and sends an event, including all global builder fields/dyn_fields, as well as anything in the optional data parameter.
174
+ # @deprecated
175
+ # Creates and sends an event, including all global builder fields/dyn_fields, as well as anything in the optional data parameter.
176
+ #
177
+ # Equivalent to:
178
+ # ev = builder.event
179
+ # ev.add(data)
180
+ # ev.send
181
+ #
182
+ # May be removed in a future major release
171
183
  #
172
184
  # @param data [Hash<String=>any>] optional field->value mapping to add to the event sent.
173
185
  # @return [self] this libhoney instance.
174
186
  # @example empty send_now
175
- # honey.send_now() # sends just the data that has been added via add/add_field/add_dynamic_field.
187
+ # honey.send_now # sends just the data that has been added via add/add_field/add_dynamic_field.
176
188
  # @example adding data at send-time
177
189
  # honey.send_now {
178
190
  # additionalField: value
179
191
  # }
180
- #/
192
+ # /
181
193
  def send_now(data = {})
182
194
  @builder.send_now(data)
183
195
  self
@@ -191,26 +203,28 @@ module Libhoney
191
203
  # @param event [Event] the event to send to honeycomb
192
204
  # @api private
193
205
  def send_event(event)
194
- @lock.synchronize {
195
- if !@tx
196
- @tx = TransmissionClient.new(:max_batch_size => @max_batch_size,
197
- :send_frequency => @send_frequency,
198
- :max_concurrent_batches => @max_concurrent_batches,
199
- :pending_work_capacity => @pending_work_capacity,
200
- :responses => @responses,
201
- :block_on_send => @block_on_send,
202
- :block_on_responses => @block_on_responses,
203
- :user_agent_addition => @user_agent_addition)
204
- end
205
- }
206
-
207
- @tx.add(event)
206
+ @lock.synchronize do
207
+ transmission_client_params = {
208
+ max_batch_size: @max_batch_size,
209
+ send_frequency: @send_frequency,
210
+ max_concurrent_batches: @max_concurrent_batches,
211
+ pending_work_capacity: @pending_work_capacity,
212
+ responses: @responses,
213
+ block_on_send: @block_on_send,
214
+ block_on_responses: @block_on_responses,
215
+ user_agent_addition: @user_agent_addition
216
+ }
217
+
218
+ @transmission ||= TransmissionClient.new(transmission_client_params)
219
+ end
220
+
221
+ @transmission.add(event)
208
222
  end
209
223
 
210
224
  # @api private
211
225
  def send_dropped_response(event, msg)
212
- response = Response.new(:error => msg,
213
- :metadata => event.metadata)
226
+ response = Response.new(error: msg,
227
+ metadata: event.metadata)
214
228
  begin
215
229
  @responses.enq(response, !@block_on_responses)
216
230
  rescue ThreadError
@@ -7,25 +7,22 @@ module Libhoney
7
7
 
8
8
  # @return [Hash<String=>any>] the fields in this event
9
9
  attr_reader :data
10
-
10
+
11
11
  # @api private
12
12
  # @see Client#event
13
13
  # @see Builder#event
14
14
  def initialize(libhoney, builder, fields = {}, dyn_fields = {})
15
- @libhoney = libhoney
16
-
17
- @writekey = builder.writekey
18
- @dataset = builder.dataset
15
+ @libhoney = libhoney
16
+ @writekey = builder.writekey
17
+ @dataset = builder.dataset
19
18
  @sample_rate = builder.sample_rate
20
- @api_host = builder.api_host
21
- @timestamp = Time.now
22
- @metadata = nil
19
+ @api_host = builder.api_host
20
+ @timestamp = Time.now
21
+ @metadata = nil
23
22
 
24
- @data = { }
25
- fields.each { |k, v| self.add_field(k, v) }
26
- dyn_fields.each { |k, v| self.add_field(k, v.call) }
27
-
28
- self
23
+ @data = {}
24
+ fields.each { |k, v| add_field(k, v) }
25
+ dyn_fields.each { |k, v| add_field(k, v.call) }
29
26
  end
30
27
 
31
28
  # adds a group of field->values to this event.
@@ -65,33 +62,34 @@ module Libhoney
65
62
  # event.with_timer "task_ms" do
66
63
  # # something time consuming
67
64
  # end
68
- def with_timer(name, &block)
69
- start = Time.now
70
- block.call
71
- duration = Time.now - start
72
- # report in ms
73
- self.add_field(name, duration * 1000)
74
- self
65
+ def with_timer(name)
66
+ start = Time.now
67
+ yield
68
+ duration = Time.now - start
69
+ # report in ms
70
+ add_field(name, duration * 1000)
71
+ self
75
72
  end
76
-
73
+
77
74
  # sends this event to honeycomb
78
75
  #
79
76
  # @return [self] this event.
80
77
  def send
81
78
  # discard if sampling rate says so
82
- if @libhoney.should_drop(self.sample_rate)
83
- @libhoney.send_dropped_response(self, "event dropped due to sampling")
79
+ if @libhoney.should_drop(sample_rate)
80
+ @libhoney.send_dropped_response(self, 'event dropped due to sampling')
84
81
  return
85
82
  end
86
83
 
87
- self.send_presampled()
84
+ send_presampled
88
85
  end
89
86
 
90
87
  # sends a presampled event to honeycomb
91
88
  #
92
89
  # @return [self] this event.
93
90
  def send_presampled
94
- raise ArgumentError.new("No metrics added to event. Won't send empty event.") if self.data.length == 0
91
+ raise ArgumentError, "No metrics added to event. Won't send empty event." if data.empty?
92
+
95
93
  @libhoney.send_event(self)
96
94
  self
97
95
  end
@@ -2,7 +2,6 @@ require 'libhoney/client'
2
2
  require 'libhoney/log_transmission'
3
3
 
4
4
  module Libhoney
5
-
6
5
  # A client that prints events to stderr or a file for inspection. Does not
7
6
  # actually send any events to Honeycomb; instead, records events for later
8
7
  # inspection.
@@ -17,5 +16,4 @@ module Libhoney
17
16
  **kwargs)
18
17
  end
19
18
  end
20
-
21
19
  end
@@ -10,7 +10,7 @@ module Libhoney
10
10
  # production is not recommended.
11
11
  class LogTransmissionClient
12
12
  def initialize(output:, verbose: false)
13
- @output = output
13
+ @output = output
14
14
  @verbose = verbose
15
15
  end
16
16
 
@@ -18,16 +18,14 @@ module Libhoney
18
18
  def add(event)
19
19
  if @verbose
20
20
  metadata = "Honeycomb dataset '#{event.dataset}' | #{event.timestamp.iso8601}"
21
- if event.sample_rate != 1
22
- metadata << " (sample rate: #{event.sample_rate})"
23
- end
21
+ metadata << " (sample rate: #{event.sample_rate})" if event.sample_rate != 1
24
22
  @output.print("#{metadata} | ")
25
23
  end
26
24
  @output.puts(event.data.to_json)
27
25
  end
28
26
 
29
27
  # Flushes the output (but does not close it)
30
- def close(drain)
28
+ def close(_drain)
31
29
  @output.flush
32
30
  end
33
31
  end
@@ -20,8 +20,7 @@ module Libhoney
20
20
  end
21
21
 
22
22
  # Does nothing.
23
- def close(drain)
24
- end
23
+ def close(drain); end
25
24
 
26
25
  # Discards the recorded events
27
26
  def reset
@@ -2,7 +2,6 @@ require 'libhoney/client'
2
2
  require 'libhoney/null_transmission'
3
3
 
4
4
  module Libhoney
5
-
6
5
  # A no-op client that silently drops events. Does not send events to
7
6
  # Honeycomb, or to anywhere else for that matter.
8
7
  #
@@ -18,5 +17,4 @@ module Libhoney
18
17
  **kwargs)
19
18
  end
20
19
  end
21
-
22
20
  end
@@ -4,10 +4,8 @@ module Libhoney
4
4
  #
5
5
  # @api private
6
6
  class NullTransmissionClient
7
- def add(event)
8
- end
7
+ def add(event); end
9
8
 
10
- def close(drain)
11
- end
9
+ def close(drain); end
12
10
  end
13
11
  end
@@ -1,4 +1,3 @@
1
-
2
1
  module Libhoney
3
2
  class Response
4
3
  attr_accessor :duration, :status_code, :metadata, :error
@@ -7,10 +6,10 @@ module Libhoney
7
6
  status_code: 0,
8
7
  metadata: nil,
9
8
  error: nil)
10
- @duration = duration
9
+ @duration = duration
11
10
  @status_code = status_code
12
- @metadata = metadata
13
- @error = error
11
+ @metadata = metadata
12
+ @error = error
14
13
  end
15
14
  end
16
15
  end
@@ -2,7 +2,6 @@ require 'libhoney/client'
2
2
  require 'libhoney/mock_transmission'
3
3
 
4
4
  module Libhoney
5
-
6
5
  # A client with the network stubbed out for testing purposes. Does not
7
6
  # actually send any events to Honeycomb; instead, records events for later
8
7
  # inspection.
@@ -17,13 +16,12 @@ module Libhoney
17
16
 
18
17
  # @return [Array<Event>] the recorded events
19
18
  def events
20
- @tx.events
19
+ @transmission.events
21
20
  end
22
21
 
23
22
  # Discards the recorded events
24
23
  def reset
25
- @tx.reset
24
+ @transmission.reset
26
25
  end
27
26
  end
28
-
29
27
  end
@@ -7,31 +7,32 @@ module Libhoney
7
7
  send_frequency: 100,
8
8
  max_concurrent_batches: 10,
9
9
  pending_work_capacity: 1000,
10
+ send_timeout: 10,
10
11
  responses: nil,
11
12
  block_on_send: false,
12
13
  block_on_responses: false,
13
14
  user_agent_addition: nil)
14
15
 
15
- @responses = responses || SizedQueue.new(pending_work_capacity * 2)
16
- @block_on_send = block_on_send
17
- @block_on_responses = block_on_responses
18
- @max_batch_size = max_batch_size
19
- @send_frequency = send_frequency
16
+ @responses = responses || SizedQueue.new(pending_work_capacity * 2)
17
+ @block_on_send = block_on_send
18
+ @block_on_responses = block_on_responses
19
+ @max_batch_size = max_batch_size
20
+ @send_frequency = send_frequency
20
21
  @max_concurrent_batches = max_concurrent_batches
21
- @pending_work_capacity = pending_work_capacity
22
-
23
- @user_agent = build_user_agent(user_agent_addition).freeze
22
+ @pending_work_capacity = pending_work_capacity
23
+ @send_timeout = send_timeout
24
+ @user_agent = build_user_agent(user_agent_addition).freeze
24
25
 
25
26
  # use a SizedQueue so the producer will block on adding to the send_queue when @block_on_send is true
26
27
  @send_queue = SizedQueue.new(@pending_work_capacity)
27
- @threads = []
28
- @lock = Mutex.new
28
+ @threads = []
29
+ @lock = Mutex.new
29
30
  end
30
31
 
31
32
  def add(event)
32
- raise ArgumentError, "No APIHost for Honeycomb. Can't send to the Great Unknown." if event.api_host == ""
33
- raise ArgumentError, "No WriteKey specified. Can't send event." if event.writekey == ""
34
- raise ArgumentError, "No Dataset for Honeycomb. Can't send datasetless." if event.dataset == ""
33
+ raise ArgumentError, "No APIHost for Honeycomb. Can't send to the Great Unknown." if event.api_host == ''
34
+ raise ArgumentError, "No WriteKey specified. Can't send event." if event.writekey == ''
35
+ raise ArgumentError, "No Dataset for Honeycomb. Can't send datasetless." if event.dataset == ''
35
36
 
36
37
  begin
37
38
  @send_queue.enq(event, !@block_on_send)
@@ -44,43 +45,48 @@ module Libhoney
44
45
 
45
46
  def send_loop
46
47
  http_clients = Hash.new do |h, api_host|
47
- h[api_host] = HTTP.persistent(api_host).headers(
48
- 'User-Agent' => @user_agent,
49
- 'Content-Type' => 'application/json',
50
- )
48
+ h[api_host] = HTTP.timeout(connect: @send_timeout, write: @send_timeout, read: @send_timeout)
49
+ .persistent(api_host)
50
+ .headers(
51
+ 'User-Agent' => @user_agent,
52
+ 'Content-Type' => 'application/json'
53
+ )
51
54
  end
52
55
 
53
56
  # eat events until we run out
54
- loop {
55
- e = @send_queue.pop
56
- break if e == nil
57
+ loop do
58
+ event = @send_queue.pop
59
+ break if event.nil?
57
60
 
58
61
  before = Time.now
59
62
 
60
63
  begin
61
- http = http_clients[e.api_host]
64
+ http = http_clients[event.api_host]
65
+ url = '/1/events/' + Addressable::URI.escape(event.dataset.dup)
62
66
 
63
- resp = http.post('/1/events/'+URI.escape(e.dataset), json: e.data, headers: {
64
- 'X-Honeycomb-Team' => e.writekey,
65
- 'X-Honeycomb-SampleRate' => e.sample_rate,
66
- 'X-Event-Time' => e.timestamp.iso8601(3)
67
- })
67
+ resp = http.post(url,
68
+ json: event.data,
69
+ headers: {
70
+ 'X-Honeycomb-Team' => event.writekey,
71
+ 'X-Honeycomb-SampleRate' => event.sample_rate,
72
+ 'X-Event-Time' => event.timestamp.iso8601(3)
73
+ })
68
74
 
69
75
  # "You must consume response before sending next request via persistent connection"
70
76
  # https://github.com/httprb/http/wiki/Persistent-Connections-%28keep-alive%29#note-using-persistent-requests-correctly
71
77
  resp.flush
72
78
 
73
- response = Response.new(:status_code => resp.status)
79
+ response = Response.new(status_code: resp.status)
74
80
  rescue Exception => error
75
81
  # catch a broader swath of exceptions than is usually good practice,
76
82
  # because this is effectively the top-level exception handler for the
77
83
  # sender threads, and we don't want those threads to die (leaving
78
84
  # nothing consuming the queue).
79
- response = Response.new(:error => error)
85
+ response = Response.new(error: error)
80
86
  ensure
81
87
  if response
82
88
  response.duration = Time.now - before
83
- response.metadata = e.metadata
89
+ response.metadata = event.metadata
84
90
  end
85
91
  end
86
92
 
@@ -89,10 +95,14 @@ module Libhoney
89
95
  rescue ThreadError
90
96
  # happens if the queue was full and block_on_send = false.
91
97
  end
92
- }
98
+ end
93
99
  ensure
94
100
  http_clients.each do |_, http|
95
- http.close rescue nil
101
+ begin
102
+ http.close
103
+ rescue StandardError
104
+ nil
105
+ end
96
106
  end
97
107
  end
98
108
 
@@ -103,9 +113,7 @@ module Libhoney
103
113
  # send @threads.length number of nils so each thread will fall out of send_loop
104
114
  @threads.length.times { @send_queue << nil }
105
115
 
106
- @threads.each do |t|
107
- t.join
108
- end
116
+ @threads.each(&:join)
109
117
  @threads = []
110
118
 
111
119
  @responses.enq(nil)
@@ -114,6 +122,7 @@ module Libhoney
114
122
  end
115
123
 
116
124
  private
125
+
117
126
  def build_user_agent(user_agent_addition)
118
127
  ua = "libhoney-rb/#{VERSION}"
119
128
  ua << " #{user_agent_addition}" if user_agent_addition
@@ -121,12 +130,10 @@ module Libhoney
121
130
  end
122
131
 
123
132
  def ensure_threads_running
124
- @lock.synchronize {
133
+ @lock.synchronize do
125
134
  @threads.select!(&:alive?)
126
- while @threads.length < @max_concurrent_batches
127
- @threads << Thread.new { self.send_loop }
128
- end
129
- }
135
+ @threads << Thread.new { send_loop } while @threads.length < @max_concurrent_batches
136
+ end
130
137
  end
131
138
  end
132
139
  end
@@ -1,3 +1,3 @@
1
1
  module Libhoney
2
- VERSION = "1.10.1"
2
+ VERSION = '1.11.0'.freeze
3
3
  end
data/libhoney.gemspec CHANGED
@@ -1,34 +1,35 @@
1
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "libhoney/version"
3
+ require 'libhoney/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'libhoney'
7
7
  spec.version = Libhoney::VERSION
8
8
 
9
- spec.summary = "send data to Honeycomb"
10
- spec.description = "Ruby gem for sending data to Honeycomb"
9
+ spec.summary = 'send data to Honeycomb'
10
+ spec.description = 'Ruby gem for sending data to Honeycomb'
11
11
  spec.authors = ['The Honeycomb.io Team']
12
12
  spec.email = 'support@honeycomb.io'
13
- spec.files = ['lib/libhoney.rb', 'lib/libhoney/version.rb']
14
13
  spec.homepage = 'https://github.com/honeycombio/libhoney-rb'
15
14
  spec.license = 'Apache-2.0'
16
15
 
17
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
17
  f.match(%r{^(test|spec|features)/})
19
18
  end
20
- spec.bindir = "exe"
19
+ spec.bindir = 'exe'
21
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
21
+ spec.require_paths = ['lib']
23
22
 
24
23
  spec.required_ruby_version = '>= 2.2.0'
25
24
 
26
- spec.add_development_dependency "bundler", "~> 1.7"
27
- spec.add_development_dependency "rake", "~> 12.3"
28
- spec.add_development_dependency "webmock", "~> 3.4"
29
- spec.add_development_dependency "minitest", "~> 5.0"
30
- spec.add_development_dependency "yard"
31
- spec.add_development_dependency "yardstick", "~> 0.9"
32
- spec.add_development_dependency "bump", "~> 0.5"
33
- spec.add_dependency "http", ">= 2.0", '< 4.0'
25
+ spec.add_development_dependency 'bump', '~> 0.5'
26
+ spec.add_development_dependency 'bundler', '~> 1.7'
27
+ spec.add_development_dependency 'minitest', '~> 5.0'
28
+ spec.add_development_dependency 'rake', '~> 12.3'
29
+ spec.add_development_dependency 'rubocop'
30
+ spec.add_development_dependency 'webmock', '~> 3.4'
31
+ spec.add_development_dependency 'yard'
32
+ spec.add_development_dependency 'yardstick', '~> 0.9'
33
+ spec.add_dependency 'addressable', '~> 2.0'
34
+ spec.add_dependency 'http', '>= 2.0', '< 4.0'
34
35
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libhoney
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.1
4
+ version: 1.11.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-08-31 00:00:00.000000000 Z
11
+ date: 2018-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bump
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.5'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +38,20 @@ dependencies:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
40
  version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: rake
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -39,33 +67,33 @@ dependencies:
39
67
  - !ruby/object:Gem::Version
40
68
  version: '12.3'
41
69
  - !ruby/object:Gem::Dependency
42
- name: webmock
70
+ name: rubocop
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
- - - "~>"
73
+ - - ">="
46
74
  - !ruby/object:Gem::Version
47
- version: '3.4'
75
+ version: '0'
48
76
  type: :development
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
- - - "~>"
80
+ - - ">="
53
81
  - !ruby/object:Gem::Version
54
- version: '3.4'
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
- name: minitest
84
+ name: webmock
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
87
  - - "~>"
60
88
  - !ruby/object:Gem::Version
61
- version: '5.0'
89
+ version: '3.4'
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
- version: '5.0'
96
+ version: '3.4'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: yard
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -95,19 +123,19 @@ dependencies:
95
123
  - !ruby/object:Gem::Version
96
124
  version: '0.9'
97
125
  - !ruby/object:Gem::Dependency
98
- name: bump
126
+ name: addressable
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
129
  - - "~>"
102
130
  - !ruby/object:Gem::Version
103
- version: '0.5'
104
- type: :development
131
+ version: '2.0'
132
+ type: :runtime
105
133
  prerelease: false
106
134
  version_requirements: !ruby/object:Gem::Requirement
107
135
  requirements:
108
136
  - - "~>"
109
137
  - !ruby/object:Gem::Version
110
- version: '0.5'
138
+ version: '2.0'
111
139
  - !ruby/object:Gem::Dependency
112
140
  name: http
113
141
  requirement: !ruby/object:Gem::Requirement
@@ -135,6 +163,8 @@ extensions: []
135
163
  extra_rdoc_files: []
136
164
  files:
137
165
  - ".gitignore"
166
+ - ".rubocop.yml"
167
+ - ".rubocop_todo.yml"
138
168
  - ".travis.yml"
139
169
  - CONTRIBUTORS
140
170
  - Gemfile
@@ -142,7 +172,7 @@ files:
142
172
  - NOTICE
143
173
  - README.md
144
174
  - Rakefile
145
- - example/fact.rb
175
+ - example/factorial.rb
146
176
  - lib/libhoney.rb
147
177
  - lib/libhoney/builder.rb
148
178
  - lib/libhoney/client.rb
data/example/fact.rb DELETED
@@ -1,62 +0,0 @@
1
- lib = File.expand_path("../../lib", __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
-
4
- require 'libhoney'
5
-
6
- writekey = "7aefa39399a474bd9f414a8e3f8d9691" # replace this with yours from https://ui.honeycomb.com/account
7
- dataset = "factorial"
8
-
9
-
10
- def factorial(n)
11
- return -1 * factorial(abs(n)) if n < 0
12
- return 1 if n == 0
13
- return n * factorial(n - 1)
14
- end
15
-
16
- # run factorial. libh_builder comes with some fields already populated
17
- # (namely, "version", "num_threads", and "range")
18
- def run_fact(low, high, libh_builder)
19
- for i in low..high do
20
- ev = libh_builder.event
21
- ev.metadata = { :fn => "run_fact",
22
- :i => i }
23
- ev.with_timer("fact") do
24
- res = factorial(10 + i)
25
- ev.add_field("retval", res)
26
- end
27
- ev.send
28
- end
29
- end
30
-
31
- def read_responses(resp_queue)
32
- while resp = resp_queue.pop()
33
- puts "sending event with metadata #{resp.metadata} took #{resp.duration*1000}ms and got response code #{resp.status_code}"
34
- end
35
- end
36
-
37
-
38
- libhoney = Libhoney::Client.new(:writekey => writekey,
39
- :dataset => dataset,
40
- :max_concurrent_batches => 1)
41
-
42
- resps = libhoney.responses()
43
- Thread.new do
44
- begin
45
- # attach fields to top-level instance
46
- libhoney.add_field("version", "3.4.5")
47
- libhoney.add_dynamic_field("num_threads", Proc.new { Thread.list.select {|thread| thread.status == "run"}.count })
48
-
49
- # sends an event with "version", "num_threads", and "status" fields
50
- libhoney.send_now({:status => "starting run"})
51
- run_fact(1, 20, libhoney.builder({:range => "low"}))
52
- run_fact(31, 40, libhoney.builder({:range => "high"}))
53
-
54
- # sends an event with "version", "num_threads", and "status" fields
55
- libhoney.send_now({:status => "ending run"})
56
- libhoney.close
57
- rescue Exception => e
58
- puts e
59
- end
60
- end
61
-
62
- read_responses(resps)