hallmonitor 1.1.0 → 2.0.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
  SHA1:
3
- metadata.gz: 1079939216599f5d80202ba8bc96224365fbef78
4
- data.tar.gz: 4fea628bc6f7faff08a44e71353ed8a4b6cdef17
3
+ metadata.gz: c7417d6498baf7f73a8d717ed8497503ab3ffc22
4
+ data.tar.gz: 3e5887d9e7bf1220f1fc12e02479cff211c9cbed
5
5
  SHA512:
6
- metadata.gz: 85a0f7f5276194396bc7b6c89d095661f676c4a511b61145b88a9129fa19fbfac3ebcfcfe447691555c43828a0410fc1933968f5110c60bfb6390bfcc786f567
7
- data.tar.gz: dc97db0cf695876cc8aa50bb578bac2f2be58218c5fa7d349dc9eea46fbfed8dad7f3a659f5c2b9a06e50d69939359df9d63d97a83236e1e1e022b94dbcedf49
6
+ metadata.gz: 13952cb19e2809073797e2a2c99b2b540b0d192090442de5b406ca424075b0be32bd4cf4c257897803e636af0cb5ced054f840b64f297d716593010d3a97255c
7
+ data.tar.gz: a23cf1b369e6713251b0f34c2920862b0bf18697f22536a97da80bb73205a48df64da4f7960fa74916caa4a36bcb2af4563c7174e33027f4844ba3e1ec340e0d
data/README.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  Hallmonitor is a simple event monitoring framework for Ruby. It allows programs to define and emit events. These events can then be sent on to various back ends to be counted, monitored, etc.
4
4
 
5
- Hallmonitor includes support for publishing events to a Statsd instance if the `statsd-ruby` gem is installed. See https://github.com/reinh/statsd for details
5
+ Hallmonitor includes support for publishing events to a Statsd instance if the `statsd-ruby` gem is installed. See https://github.com/reinh/statsd for details.
6
+ It also includes support for outputting events to InfluxDB if the 'influxdb' gem is installed.
6
7
 
7
8
  ## Setup
8
9
  Before you can use Hallmonitor you have to do a tiny bit of configuration in the form of adding outputters.
@@ -31,7 +31,7 @@ module Hallmonitor
31
31
  begin
32
32
  o.process(event)
33
33
  rescue
34
- raise unless Hallmonitor.config.trap_outputter_exceptions
34
+ raise unless Hallmonitor.config && Hallmonitor.config.trap_outputter_exceptions
35
35
  end
36
36
  end
37
37
  nil
@@ -9,8 +9,10 @@ module Hallmonitor
9
9
 
10
10
  # Builds a new event
11
11
  # @param name [String] the name of this event
12
- # @param count [Number] the count of this even, defaults to 1
13
- def initialize(name, count=1, tags: {})
12
+ # @param count [Number,Hash] the count of this even, defaults to 1. Can
13
+ # also be a hash of named value pairs
14
+ # @param tags [Hash<Symbol,String>] Hash of tags to values for this event
15
+ def initialize(name, count: 1, tags: {})
14
16
  @name = name
15
17
  @time = Time.now
16
18
  @count = count
@@ -6,8 +6,8 @@ module Hallmonitor
6
6
  class GaugeEvent < Event
7
7
  # @param name [String] Name of this guage
8
8
  # @param value [Number] The current value of this guage
9
- def initialize(name, value)
10
- super(name, value)
9
+ def initialize(name, value: nil, tags: {})
10
+ super(name, count: value, tags: tags)
11
11
  end
12
12
 
13
13
  # The value of this guage
@@ -7,7 +7,7 @@ module Hallmonitor
7
7
  # @param name [Object] Probably a string or symbol, the name of this
8
8
  # outputter
9
9
  def initialize(name)
10
- raise(ArgumentError, "Outputter expects a name") if name.nil?
10
+ fail(ArgumentError, 'Outputter expects a name') if name.nil?
11
11
  @name = name
12
12
  end
13
13
 
@@ -5,50 +5,98 @@ end
5
5
 
6
6
  module Hallmonitor
7
7
  module Outputters
8
- # An outputter for StatsD
9
- class InfluxdbOutputter < Outputter
10
- # Builds a new InfluxdbOutputter
8
+ # An outputter for InfluxDB
9
+ class Influxdb < Outputter
10
+ # Builds a new Influxdb outputter
11
11
  # @param influxdb_client [InfluxDB::Client] client instance to use
12
12
  # @param tags [Hash] Set of default tags applied to all events output to
13
13
  # InfluxDB, will be overridden by tags set by events if they conflict
14
- # @raise if Statsd is undefined (Gem not present)
15
- def initialize(influxdb_client, tags)
16
- raise "In order to use InfluxdbOutputter, influxdb gem must be installed" unless defined?(InfluxDB)
17
- super("influxdb")
18
- @tags = tags
19
- @client = influxdb_client
14
+ # @param transformer [#transform(String)] An object that responds
15
+ # to #transform(String). If supplied it will be passed each event name
16
+ # and should return a hash with keys :name and :tags. This is to allow
17
+ # for transition from a statsd/graphite style event naming convention to
18
+ # an InfluxDb style name+tags convention. Any tags returned by the
19
+ # transformer will defer to tags specified in the event itself, in
20
+ # other words if the event has tags already they will take precedence
21
+ # over tags built by the transformer
22
+ # @raise if influxdb_client does not respond to :write_point
23
+ # (InfluxDB::Client contract)
24
+ def initialize(influxdb_client, tags = {}, transformer = nil)
25
+ unless influxdb_client.respond_to?(:write_point)
26
+ fail 'Supplied InfluxDB Client was not as expected'
27
+ end
28
+
29
+ if transformer && !transformer.respond_to?(:transform)
30
+ fail 'Supplied transformer does not respond to :transform'
31
+ end
32
+
33
+ super('influxdb')
34
+ @tags = {}.merge(tags)
35
+ @client = influxdb_client || fail('Must supply an InfluxDb client')
36
+ @transformer = transformer
20
37
  end
21
38
 
22
- # Sends events to statsd instance
39
+ # Sends events to InfluxDB instance
40
+ # @param evvent []
23
41
  def process(event)
24
- tags = @tags.merge(event.tags)
25
-
26
- data = {}
27
-
28
- if(event.respond_to?(:duration))
29
- tags = {type: 'timer'}.merge(tags)
30
- data = {
31
- values: {value: event.duration},
32
- tags: tags
33
- }
34
- @client.write_point(event.name, data)
35
- elsif(event.respond_to?(:value))
36
- tags = {type: 'guage'}.merge(tags)
37
- data = {
38
- values: {value: event.value},
39
- tags: tags
40
- }
42
+ data =
43
+ if event.is_a?(Hallmonitor::TimedEvent)
44
+ build_timer_data(event)
45
+ elsif event.is_a?(Hallmonitor::GaugeEvent)
46
+ build_gauge_data(event)
47
+ else
48
+ build_counter_data(event)
49
+ end
50
+ transform_and_write(event, data)
51
+ end
52
+
53
+ private
54
+
55
+ def transform_and_write(event, data)
56
+ to_write = transform(event, data)
57
+ @client.write_point(to_write[:name], to_write[:data])
58
+ end
59
+
60
+ # If @transformer exists, use it to transform the event name
61
+ # and possibly build tags from it.
62
+ # @param event [Event] The event we're working with
63
+ # @param data [Hash] Hash of data we're building for InfluxDB,
64
+ # Will be modified directly if the transformer is specified.
65
+ # @see {#build_data} for information on the structure of `data`
66
+ def transform(event, data)
67
+ if @transformer
68
+ t = @transformer.transform(event.name)
69
+ data[:tags] = (t[:tags] || {}).merge(data[:tags])
70
+ { name: t[:name], data: data }
41
71
  else
42
- tags = {type: 'count'}.merge(tags)
43
- data = {
44
- values: {value: event.count},
45
- tags: tags
46
- }
72
+ { name: event.name, data: data }
47
73
  end
74
+ end
75
+
76
+ def build_data(event, type, value)
77
+ data = {
78
+ tags: @tags.merge(event.tags.merge(type: type))
79
+ }
48
80
 
49
- @client.write_point(event.name, data)
81
+ if value.is_a?(Hash)
82
+ data[:values] = value
83
+ else
84
+ data[:values] = { value: value }
85
+ end
86
+ data
50
87
  end
51
88
 
89
+ def build_timer_data(event)
90
+ build_data(event, 'timer', event.duration)
91
+ end
92
+
93
+ def build_gauge_data(event)
94
+ build_data(event, 'gauge', event.value)
95
+ end
96
+
97
+ def build_counter_data(event)
98
+ build_data(event, 'count', event.count)
99
+ end
52
100
  end
53
101
  end
54
102
  end
@@ -4,7 +4,6 @@ module Hallmonitor
4
4
  module Outputters
5
5
  # Simple outputter that just prints to an output stream
6
6
  class IOOutputter < Outputter
7
-
8
7
  # Builds a new IOOutputter
9
8
  # @param name [String] Name for this outputter
10
9
  # @param out [IO] Output to write to
@@ -16,15 +15,14 @@ module Hallmonitor
16
15
  # Sends an event to the configured output
17
16
  # on IOError the output will be closed
18
17
  def process(event)
19
- begin
20
- @out.print "EVENT: #{event.to_json}\n"
21
- @out.flush
22
- rescue IOError => e
23
- close
24
- end
18
+ @out.print "EVENT: #{event.to_json}\n"
19
+ @out.flush
20
+ rescue IOError
21
+ close
25
22
  end
26
23
 
27
24
  private
25
+
28
26
  def close
29
27
  @out.close unless @out.nil?
30
28
  end
@@ -5,25 +5,58 @@ module Hallmonitor
5
5
  # Initializes a new instance
6
6
  # @raise String if {NewRelic::Agent} isn't defined (Library isn't loaded)
7
7
  # @param prefix [String] String to prefix all metrics with
8
- def initialize(prefix='')
9
- raise "In order to use NewRelic, new_relic gem must be installed" unless defined?(::NewRelic::Agent)
8
+ def initialize(prefix = '')
9
+ unless defined?(::NewRelic::Agent)
10
+ fail 'In order to use NewRelic, new_relic gem must be installed'
11
+ end
10
12
  super(prefix)
11
13
  end
12
14
 
13
15
  def process(event)
14
- if(event.respond_to?(:duration))
15
- ::NewRelic::Agent.record_metric(new_relic_name(event), event.duration)
16
- elsif(event.respond_to?(:value))
17
- ::NewRelic::Agent.record_metric(new_relic_name(event), event.value)
16
+ if event.is_a?(Hallmonitor::TimedEvent)
17
+ process_timed_event(event)
18
+ elsif event.is_a?(Hallmonitor::GaugeEvent)
19
+ process_gauge_event(event)
18
20
  else
19
- ::NewRelic::Agent.increment_metric(new_relic_name(event), event.count)
21
+ process_event(event)
20
22
  end
21
23
  end
22
24
 
23
25
  private
26
+
27
+ def process_timed_event(event)
28
+ if event.duration.is_a?(Hash)
29
+ event.duration.each do |name, value|
30
+ ::NewRelic::Agent.record_metric(new_relic_name("#{event.name}.#{name}"), value)
31
+ end
32
+ else
33
+ ::NewRelic::Agent.record_metric(new_relic_name(event.name), event.duration)
34
+ end
35
+ end
36
+
37
+ def process_gauge_event(event)
38
+ if event.value.is_a?(Hash)
39
+ event.value.each do |name, value|
40
+ ::NewRelic::Agent.record_metric(new_relic_name("#{event.name}.#{name}"), value)
41
+ end
42
+ else
43
+ ::NewRelic::Agent.record_metric(new_relic_name(event.name), event.value)
44
+ end
45
+ end
46
+
47
+ def process_event(event)
48
+ if event.count.is_a?(Hash)
49
+ event.count.each do |name, value|
50
+ ::NewRelic::Agent.increment_metric(new_relic_name("#{event.name}.#{name}"), value)
51
+ end
52
+ else
53
+ ::NewRelic::Agent.increment_metric(new_relic_name(event.name), event.count)
54
+ end
55
+ end
56
+
24
57
  # Formats the event name into the naming scheme that NewRelic expects
25
- def new_relic_name(event)
26
- "Custom/#{event.name.gsub('.','/')}"
58
+ def new_relic_name(name)
59
+ "Custom/#{name.tr('.', '/')}"
27
60
  end
28
61
  end
29
62
  end
@@ -12,24 +12,77 @@ module Hallmonitor
12
12
  # the prefix will be applied to all event names before sending to statsd
13
13
  # @param host [String] Statsd Host, defaults to 'localhost'
14
14
  # @param port [Number] Statsd Port, defaults to 8125
15
+ # @param transformer [#transform(event)] An object that responds
16
+ # to #transform(Event). If supplied it will be passed each event
17
+ # and should return an event name. This is to allow for flattening any
18
+ # tags present in the event into a flattened name structure.
15
19
  # @raise if Statsd is undefined (Gem not present)
16
- def initialize(prefix, host="localhost", port=8125)
17
- raise "In order to use StatsdOutputter, statsd gem must be installed" unless defined?(Statsd)
20
+ def initialize(prefix, host = 'localhost', port = 8125, transformer = nil)
21
+ unless defined?(Statsd)
22
+ fail 'In order to use StatsdOutputter, statsd gem must be installed'
23
+ end
24
+
25
+ if transformer && !transformer.respond_to?(:transform)
26
+ fail 'Supplied transformer does not respond to :transform'
27
+ end
28
+
18
29
  super(prefix)
19
- @statsd = Statsd.new(host).tap{|sd| sd.namespace = name}
30
+ @statsd = Statsd.new(host).tap { |sd| sd.namespace = name }
31
+ @transformer = transformer
20
32
  end
21
33
 
22
34
  # Sends events to statsd instance
35
+ # If the event's value field is a hash, this will send multiple events
36
+ # to statsd with the original name suffixed by the name of the events
37
+ # in the hash
23
38
  def process(event)
24
- if(event.respond_to?(:duration))
25
- @statsd.timing(event.name, event.duration)
26
- elsif(event.respond_to?(:value))
27
- @statsd.gauge(event.name, event.value)
39
+ if event.is_a?(Hallmonitor::TimedEvent)
40
+ process_timed_event(event)
41
+ elsif event.is_a?(Hallmonitor::GaugeEvent)
42
+ process_gauge_event(event)
43
+ else
44
+ process_event(event)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def process_timed_event(event)
51
+ event_name = name_for(event)
52
+ if event.duration.is_a?(Hash)
53
+ event.duration.each do |name, value|
54
+ @statsd.timing("#{event_name}.#{name}", value)
55
+ end
28
56
  else
29
- @statsd.count(event.name, event.count)
57
+ @statsd.timing(event_name, event.duration)
30
58
  end
31
59
  end
32
60
 
61
+ def process_gauge_event(event)
62
+ event_name = name_for(event)
63
+ if event.value.is_a?(Hash)
64
+ event.value.each do |name, value|
65
+ @statsd.gauge("#{event_name}.#{name}", value)
66
+ end
67
+ else
68
+ @statsd.gauge(event_name, event.value)
69
+ end
70
+ end
71
+
72
+ def process_event(event)
73
+ event_name = name_for(event)
74
+ if event.count.is_a?(Hash)
75
+ event.count.each do |name, value|
76
+ @statsd.count("#{event_name}.#{name}", value)
77
+ end
78
+ else
79
+ @statsd.count(event_name, event.count)
80
+ end
81
+ end
82
+
83
+ def name_for(event)
84
+ @transformer ? @transformer.transform(event) : event.name
85
+ end
33
86
  end
34
87
  end
35
88
  end
@@ -10,8 +10,9 @@ module Hallmonitor
10
10
 
11
11
  # Builds a new {TimedEvent}
12
12
  # @param name [String] name of this event
13
- # @param duration [Number] the timespan of this event
14
- def initialize(name, duration=nil, tags: {})
13
+ # @param duration [Number, Hash] the timespan of this event, or multiple named
14
+ # timestamps
15
+ def initialize(name, duration: nil, tags: {})
15
16
  super(name, tags: tags)
16
17
  @duration = duration
17
18
  end
@@ -39,7 +40,7 @@ module Hallmonitor
39
40
  time: @time,
40
41
  start: @start,
41
42
  stop: @stop,
42
- duration: self.duration
43
+ duration: duration
43
44
  }.to_json(*a)
44
45
  end
45
46
  end
@@ -1,10 +1,10 @@
1
1
  module Hallmonitor
2
2
  module Version
3
- MAJOR = 1
4
- MINOR = 1
3
+ MAJOR = 2
4
+ MINOR = 0
5
5
  PATCH = 0
6
6
  BUILD = nil
7
7
 
8
- STRING = [MAJOR,MINOR,PATCH,BUILD].compact.join(".")
8
+ STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
9
9
  end
10
10
  end
@@ -24,14 +24,15 @@ module Hallmonitor
24
24
  end
25
25
 
26
26
  describe 'with exception trapping turned off' do
27
+ let(:error) { "FOOO" }
27
28
  before do
28
- allow(outputter).to receive(:process).and_raise("FOOOOO")
29
+ allow(outputter).to receive(:process).and_raise(error)
29
30
  Hallmonitor.configure do |c|
30
31
  c.trap_outputter_exceptions = false
31
32
  end
32
33
  end
33
34
  it 'raises outputter exceptions' do
34
- expect{Dispatcher.output("thing")}.to raise_error
35
+ expect { Dispatcher.output("thing") }.to raise_error(error)
35
36
  end
36
37
  end
37
38
 
@@ -86,11 +86,11 @@ RSpec.describe Hallmonitor::Monitored do
86
86
  it 'emits a timer for the block' do
87
87
  expect(Hallmonitor::Dispatcher).to(
88
88
  receive(:output).with(a_timed_event_with_name(name)))
89
- expect {
89
+ expect do
90
90
  subject.watch(name) do
91
- raise 'OOPS!'
91
+ fail 'OOPS!'
92
92
  end
93
- }.to raise_error
93
+ end.to raise_error('OOPS!')
94
94
  end
95
95
  end
96
96
  end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+ require 'hallmonitor/outputters/influxdb'
3
+
4
+ module Hallmonitor
5
+ module Outputters
6
+ RSpec.describe Influxdb do
7
+ let(:influxdb_client) { nil }
8
+ let(:default_tags) { {} }
9
+ let(:outputter) { described_class.new(influxdb_client, default_tags) }
10
+
11
+ context '#initialize' do
12
+ context 'with a bad influxdb client' do
13
+ it 'raises an error' do
14
+ expect { outputter }.to raise_error(String)
15
+ end
16
+ end
17
+
18
+ context 'with a good client' do
19
+ let(:influxdb_client) { double('influxdb_client') }
20
+ before do
21
+ allow(influxdb_client).to receive(:write_point)
22
+ end
23
+
24
+ it 'does not raise an error' do
25
+ expect { outputter }.to_not raise_error
26
+ end
27
+ end
28
+ end
29
+
30
+ context '#process' do
31
+ let(:default_tags) { { foo: 'bar' } }
32
+ let(:influxdb_client) { double('influxdb_client') }
33
+ let(:event_name) { 'event_name' }
34
+ let(:event) { Hallmonitor::Event.new(event_name, tags: tags) }
35
+ let(:tags) { { tag_one: 'one', tag_two: 'two' } }
36
+ let(:expected_value) { event.count }
37
+ let(:expected_type) { 'count' }
38
+ let(:expected_data) do
39
+ {
40
+ values: { value: expected_value },
41
+ tags: default_tags.merge(tags).merge(type: expected_type)
42
+ }
43
+ end
44
+
45
+ it 'sends the correct information to influxdb' do
46
+ expect(influxdb_client).to(
47
+ receive(:write_point).with(event_name, expected_data))
48
+ outputter.process(event)
49
+ end
50
+
51
+ context 'with a timer event' do
52
+ let(:event) { Hallmonitor::TimedEvent.new(event_name, duration: 100, tags: tags) }
53
+ let(:expected_value) { event.duration }
54
+ let(:expected_type) { 'timer' }
55
+ it 'sends the correct information to influxdb' do
56
+ expect(influxdb_client).to(
57
+ receive(:write_point).with(event_name, expected_data))
58
+ outputter.process(event)
59
+ end
60
+ end
61
+
62
+ context 'with a gauge event' do
63
+ let(:event) { Hallmonitor::GaugeEvent.new(event_name, value: 100, tags: tags) }
64
+ let(:expected_value) { event.value }
65
+ let(:expected_type) { 'gauge' }
66
+ it 'sends the correct information to influxdb' do
67
+ expect(influxdb_client).to(
68
+ receive(:write_point).with(event_name, expected_data))
69
+ outputter.process(event)
70
+ end
71
+ end
72
+
73
+ context 'with a name transformer' do
74
+ let(:transformer) { double('name_transformer') }
75
+ let(:outputter) do
76
+ described_class.new(influxdb_client, default_tags, transformer)
77
+ end
78
+
79
+ it 'builds event information using the transformer' do
80
+ expect(transformer).to(
81
+ receive(:transform)
82
+ .with(event.name)
83
+ .and_return(
84
+ name: 'foo',
85
+ tags: { additional: 'foo' }
86
+ )
87
+ )
88
+ expected_data[:tags][:additional] = 'foo'
89
+ expect(influxdb_client).to(
90
+ receive(:write_point).with('foo', expected_data))
91
+ outputter.process(event)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ require 'hallmonitor/outputters/statsd_outputter'
4
+
5
+ module Hallmonitor
6
+ module Outputters
7
+ RSpec.describe StatsdOutputter do
8
+ let(:statsd_client) { instance_double(Statsd) }
9
+ let(:prefix) { 'test' }
10
+ let(:outputter) { described_class.new(prefix) }
11
+
12
+ before do
13
+ allow(statsd_client).to receive(:namespace=)
14
+ allow(Statsd).to receive(:new).and_return(statsd_client)
15
+ end
16
+
17
+ it 'can be instantiated' do
18
+ expect { outputter }.to_not raise_error
19
+ end
20
+
21
+ context '#process' do
22
+ let(:event_name) { 'foo.bar.baz' }
23
+ context 'with an event' do
24
+ let(:event) { Event.new(event_name) }
25
+
26
+ it 'sends the event to statsd' do
27
+ expect(statsd_client).to receive(:count).with(event_name, event.count)
28
+ outputter.process(event)
29
+ end
30
+
31
+ context 'that has multiple values' do
32
+ let(:values) { { foo: 1, bar: 2 } }
33
+ let(:event) { Event.new(event_name, count: values) }
34
+ it 'sends multiple events to statsd' do
35
+ expect(statsd_client).to receive(:count).with("#{event_name}.foo", event.count[:foo])
36
+ expect(statsd_client).to receive(:count).with("#{event_name}.bar", event.count[:bar])
37
+ outputter.process(event)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hallmonitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris TenHarmsel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-24 00:00:00.000000000 Z
11
+ date: 2016-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -167,6 +167,8 @@ files:
167
167
  - lib/hallmonitor/version.rb
168
168
  - spec/hallmonitor/dispatcher_spec.rb
169
169
  - spec/hallmonitor/monitored_spec.rb
170
+ - spec/hallmonitor/outputters/influxdb_spec.rb
171
+ - spec/hallmonitor/outputters/statsd_outputter_spec.rb
170
172
  - spec/spec_helper.rb
171
173
  homepage: http://github.com/epchris/hallmonitor
172
174
  licenses:
@@ -188,12 +190,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
190
  version: '0'
189
191
  requirements: []
190
192
  rubyforge_project:
191
- rubygems_version: 2.4.5
193
+ rubygems_version: 2.4.5.1
192
194
  signing_key:
193
195
  specification_version: 4
194
196
  summary: Simple Ruby Event Monitoring
195
197
  test_files:
196
198
  - spec/hallmonitor/dispatcher_spec.rb
197
199
  - spec/hallmonitor/monitored_spec.rb
200
+ - spec/hallmonitor/outputters/influxdb_spec.rb
201
+ - spec/hallmonitor/outputters/statsd_outputter_spec.rb
198
202
  - spec/spec_helper.rb
199
203
  has_rdoc: