hallmonitor 4.2.0 → 5.0.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 +4 -4
- data/README.md +16 -5
- data/lib/hallmonitor/gauge_event.rb +8 -0
- data/lib/hallmonitor/monitored.rb +27 -20
- data/lib/hallmonitor/outputters/datadog.rb +82 -0
- data/lib/hallmonitor/timed_event.rb +4 -3
- data/lib/hallmonitor/version.rb +2 -2
- data/spec/hallmonitor/monitored_spec.rb +71 -33
- data/spec/hallmonitor/outputters/datadog_spec.rb +72 -0
- metadata +27 -35
- data/.document +0 -5
- data/.gitignore +0 -50
- data/CHANGELOG.md +0 -17
- data/Gemfile +0 -3
- data/Rakefile +0 -16
- data/bin/example.rb +0 -49
- data/hallmonitor.gemspec +0 -31
- data/lib/hallmonitor/outputters/dogstatsd_outputter.rb +0 -85
- data/spec/hallmonitor/outputters/dogstatsd_outputter_spec.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54c0631a67fb95ae8201691fdd5e5e12c09936f1
|
4
|
+
data.tar.gz: d0dddea0967b40bfeea62612157649eeef033711
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e314315927b4dbaa450022ac88e054ff6e1e230a5f81db0930cab21e54c7e28d20d3521d17cce6671897f1837f8ad7a400409038f7e0a2e8e34e4da4e721045
|
7
|
+
data.tar.gz: 193b9d428e2cca3a95618f5a8b77853fefd8194673f2bf83ef8937326c05c0c47ad667c5328372a99845c4ae862b4f6acf948a77ec1e64b8de9e3721ceff5349
|
data/README.md
CHANGED
@@ -2,21 +2,32 @@
|
|
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
|
6
|
-
|
5
|
+
Hallmonitor includes support for the following outputters:
|
6
|
+
|
7
|
+
- [Statsd](https://github.com/reinh/statsd) - Requires the `statsd` gem to be installed
|
8
|
+
- [InfluxDB](https://github.com/influxdata/influxdb-ruby) - Requires the `influxdb` gem to be installed
|
9
|
+
- [Datadog](https://github.com/DataDog/dogstatsd-ruby) - Requires the `dogstatsd-ruby` gem to be installed
|
10
|
+
- IOOutputter - Simple outputter that outputs to an IO object
|
11
|
+
- [NewRelic](https://github.com/newrelic/rpm) - Requires the `newrelic_rpm` gem to be installed
|
12
|
+
|
7
13
|
|
8
14
|
## Setup
|
9
15
|
Before you can use Hallmonitor you have to do a tiny bit of configuration in the form of adding outputters.
|
10
16
|
|
11
17
|
```ruby
|
12
18
|
# Add an outputter to STDOUT
|
19
|
+
require 'hallmonitor/outputters/iooutputter.rb'
|
13
20
|
Hallmonitor.add_outputter Hallmonitor::Outputters::IOOutputter.new("STDOUT", STDOUT)
|
14
21
|
|
15
22
|
# Add an outputter to StatsD
|
23
|
+
require 'hallmonitor/outputters/statsd_outputter'
|
16
24
|
Hallmonitor.add_outputter Hallmonitor::Outputters::StatsdOutputter.new("example", "localhost")
|
17
|
-
```
|
18
25
|
|
19
|
-
|
26
|
+
# Add an outputter to Datadog
|
27
|
+
require 'hallmonitor/outputters/datadog
|
28
|
+
datadog = Datadog::Statsd.new
|
29
|
+
Hallmonitor.add_outputter Hallmonitor::Outputters::Datadog.new(datadog)
|
30
|
+
```
|
20
31
|
|
21
32
|
## Configuration
|
22
33
|
Right now there's only one configuration option and here's how you can set it:
|
@@ -90,5 +101,5 @@ event.emit
|
|
90
101
|
|
91
102
|
## Copyright
|
92
103
|
|
93
|
-
Copyright (c) 2012-
|
104
|
+
Copyright (c) 2012-2018 Chris TenHarmsel. See LICENSE.txt for
|
94
105
|
further details.
|
@@ -9,16 +9,18 @@ module Hallmonitor
|
|
9
9
|
# @options [Hash] Optional settings:
|
10
10
|
# metric_name: [String] Metric name to emit, defaults to
|
11
11
|
# "#{underscore(name)}.#{method_sym}"
|
12
|
-
def timer_for(method_sym,
|
13
|
-
metric_name
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def timer_for(method_sym, metric_name: nil, tags: {})
|
13
|
+
metric_name ||= "#{underscore(name)}.#{method_sym}"
|
14
|
+
undecorated_method_sym = "#{method_sym}_without_hallmonitor_timer".to_sym
|
15
|
+
decorated_method_sym = "#{method_sym}_with_hallmonitor_timer".to_sym
|
16
|
+
send(:define_method, decorated_method_sym) do |*args|
|
17
|
+
watch(metric_name, tags: tags) do
|
18
|
+
send(undecorated_method_sym, *args)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
alias_method
|
21
|
-
alias_method method_sym,
|
22
|
+
alias_method undecorated_method_sym, method_sym
|
23
|
+
alias_method method_sym, decorated_method_sym
|
22
24
|
end
|
23
25
|
|
24
26
|
# Sets up a counter for a method by symbol. Method must have already been
|
@@ -27,17 +29,20 @@ module Hallmonitor
|
|
27
29
|
# @options [Hash] Optional settings:
|
28
30
|
# metric_name: [String] Metric name to emit, defaults to
|
29
31
|
# "#{underscore(name)}.#{method_sym}"
|
30
|
-
def count_for(method_sym,
|
31
|
-
metric_name
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
def count_for(method_sym, metric_name: nil, tags: {})
|
33
|
+
metric_name ||= "#{underscore(name)}.#{method_sym}"
|
34
|
+
undecorated_method_sym = "#{method_sym}_without_hallmonitor_counter".to_sym
|
35
|
+
decorated_method_sym = "#{method_sym}_with_hallmonitor_counter".to_sym
|
36
|
+
send(:define_method, decorated_method_sym) do |*args|
|
37
|
+
emit(metric_name, tags: tags)
|
38
|
+
send(undecorated_method_sym, *args)
|
35
39
|
end
|
36
40
|
|
37
|
-
alias_method
|
38
|
-
alias_method method_sym,
|
41
|
+
alias_method undecorated_method_sym, method_sym
|
42
|
+
alias_method method_sym, decorated_method_sym
|
39
43
|
end
|
40
44
|
|
45
|
+
# :reek:UtilityFunction
|
41
46
|
def underscore(value)
|
42
47
|
word = value.dup
|
43
48
|
word.gsub!(/::/, '.')
|
@@ -51,17 +56,19 @@ module Hallmonitor
|
|
51
56
|
|
52
57
|
def self.included(base)
|
53
58
|
base.extend(ClassMethods)
|
59
|
+
base.extend(self)
|
54
60
|
end
|
55
61
|
|
56
|
-
# Emits an event: self if the event param is nil, the passed in
|
57
|
-
# it's an {Event}, or constructs a {Event} from the
|
62
|
+
# Emits an event: self if the event param is nil, the passed in
|
63
|
+
# event if it's an {Event}, or constructs a {Event} from the
|
64
|
+
# passed in param.
|
65
|
+
#
|
66
|
+
# If the parameter is a {Hallmonitor::Event}, it will be emitted
|
67
|
+
# as is. Otherwise, a new {Hallmonitor::Event} will be created
|
68
|
+
# with the parameter and emitted.
|
58
69
|
#
|
59
|
-
# If the parameter is a {Hallmonitor::Event}, it will be emitted as is.
|
60
|
-
# Otherwise, a new {Hallmonitor::Event} will be created with the parameter
|
61
|
-
# and emitted.
|
62
70
|
# @param event [Mixed] The thing to emit, see method description
|
63
71
|
# @yield [to_emit] The thing that's going to be emitted
|
64
|
-
# @return nil
|
65
72
|
def emit(event = nil, tags: {})
|
66
73
|
to_emit = self
|
67
74
|
unless event.nil?
|
@@ -0,0 +1,82 @@
|
|
1
|
+
begin
|
2
|
+
require 'datadog/statsd'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
module Hallmonitor
|
7
|
+
module Outputters
|
8
|
+
# An outputter for Dogstatsd
|
9
|
+
class Datadog < Outputter
|
10
|
+
# Simple EventData struct
|
11
|
+
EventData = Struct.new(:name, :value, :tags, :type)
|
12
|
+
|
13
|
+
# Builds a new DogstatsdOutputter.
|
14
|
+
# @param dogstatsd [Datadog::Statsd] Dogstatd client instance to use
|
15
|
+
# @param tags [Hash] Default tags to apply to all metrics sent to this outputter
|
16
|
+
def initialize(dogstatsd, tags: {})
|
17
|
+
super('dogstatsd')
|
18
|
+
@tags = {}.merge(tags)
|
19
|
+
@statsd = dogstatsd
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sends events to datadog statsd instance
|
23
|
+
#
|
24
|
+
# If the event's value field is a hash, this will send multiple
|
25
|
+
# events to statsd with the original name suffixed by the name
|
26
|
+
# of the events in the hash
|
27
|
+
def process(event)
|
28
|
+
event_data = build_event_data(event)
|
29
|
+
write(event_data)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# :reek:FeatureEnvy
|
35
|
+
def write(event_data)
|
36
|
+
event_data.each do |data|
|
37
|
+
@statsd.send(data.type, data.name, data.value, tags: data.tags)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_event_data(event)
|
42
|
+
case event
|
43
|
+
when Hallmonitor::TimedEvent
|
44
|
+
build_timed_data(event)
|
45
|
+
when Hallmonitor::GaugeEvent
|
46
|
+
build_gauge_data(event)
|
47
|
+
else
|
48
|
+
build_count_data(event)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def build_timed_data(event)
|
53
|
+
build_data(event, event.duration, :timing)
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_gauge_data(event)
|
57
|
+
build_data(event, event.value, :gauge)
|
58
|
+
end
|
59
|
+
|
60
|
+
def build_count_data(event)
|
61
|
+
build_data(event, event.count, :count)
|
62
|
+
end
|
63
|
+
|
64
|
+
# :reek:FeatureEnvy
|
65
|
+
def build_data(event, value, type)
|
66
|
+
event_name = event.name
|
67
|
+
tags = process_tags(event.tags)
|
68
|
+
if value.is_a?(Hash)
|
69
|
+
value.map do |name, value|
|
70
|
+
EventData.new("#{event_name}.#{name}", value, tags, type)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
[EventData.new(event_name, value, tags, type)]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def process_tags(tags)
|
78
|
+
@tags.merge(tags).map { |key, value| "#{key}:#{value}" }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/hallmonitor/version.rb
CHANGED
@@ -6,24 +6,28 @@ class Thing
|
|
6
6
|
def timer_for_test
|
7
7
|
# Nothing
|
8
8
|
end
|
9
|
-
timer_for :timer_for_test
|
9
|
+
timer_for :timer_for_test, metric_name: 'thing.measure', tags: {foo: 'bar'}
|
10
10
|
|
11
11
|
def count_for_test
|
12
12
|
# Nothing
|
13
13
|
end
|
14
|
-
count_for :count_for_test
|
14
|
+
count_for :count_for_test, metric_name: 'thing.execute', tags: {foo: 'bar'}
|
15
15
|
end
|
16
16
|
|
17
|
-
RSpec::Matchers.define :
|
18
|
-
match { |actual| actual.is_a?(Hallmonitor::Event)
|
17
|
+
RSpec::Matchers.define :an_event do
|
18
|
+
match { |actual| actual.is_a?(Hallmonitor::Event)}
|
19
19
|
end
|
20
20
|
|
21
|
-
RSpec::Matchers.define :
|
22
|
-
match { |actual| actual.is_a?(Hallmonitor::Event)
|
21
|
+
RSpec::Matchers.define :a_timed_event do
|
22
|
+
match { |actual| actual.is_a?(Hallmonitor::Event)}
|
23
23
|
end
|
24
24
|
|
25
|
-
RSpec::Matchers.define :
|
26
|
-
match { |actual| actual.
|
25
|
+
RSpec::Matchers.define :has_name do |expected_name|
|
26
|
+
match { |actual| actual.name == expected_name }
|
27
|
+
end
|
28
|
+
|
29
|
+
RSpec::Matchers.define :has_tags do |expected_tags|
|
30
|
+
match { |actual| actual.tags == expected_tags}
|
27
31
|
end
|
28
32
|
|
29
33
|
RSpec.describe Hallmonitor::Monitored do
|
@@ -32,7 +36,11 @@ RSpec.describe Hallmonitor::Monitored do
|
|
32
36
|
describe '#timer_for' do
|
33
37
|
it 'emits a timer with an appropriate name' do
|
34
38
|
expect(Hallmonitor::Dispatcher).to(
|
35
|
-
receive(:output)
|
39
|
+
receive(:output)
|
40
|
+
.with(
|
41
|
+
a_timed_event.and(has_name('thing.measure')).and(has_tags({foo: 'bar'}))
|
42
|
+
)
|
43
|
+
)
|
36
44
|
Thing.new.timer_for_test
|
37
45
|
end
|
38
46
|
end
|
@@ -40,33 +48,33 @@ RSpec.describe Hallmonitor::Monitored do
|
|
40
48
|
describe '#count_for' do
|
41
49
|
it 'emits an event with an appropriate name' do
|
42
50
|
expect(Hallmonitor::Dispatcher).to(
|
43
|
-
receive(:output).with(
|
51
|
+
receive(:output).with(
|
52
|
+
an_event.and(has_name('thing.execute')).and(has_tags({foo: 'bar'}))
|
53
|
+
)
|
54
|
+
)
|
44
55
|
Thing.new.count_for_test
|
45
56
|
end
|
46
57
|
end
|
47
58
|
|
48
|
-
|
59
|
+
shared_examples 'for watch' do
|
49
60
|
let(:retval) { 'Hello World' }
|
50
61
|
let(:name) { 'foo' }
|
51
62
|
|
52
63
|
it 'returns the value the block returns' do
|
53
|
-
value = subject.watch(name)
|
54
|
-
retval
|
55
|
-
end
|
64
|
+
value = subject.watch(name) { retval }
|
56
65
|
expect(value).to eq(retval)
|
57
66
|
|
58
|
-
value = subject.watch(name)
|
59
|
-
nil
|
60
|
-
end
|
67
|
+
value = subject.watch(name) { nil }
|
61
68
|
expect(value).to_not be
|
62
69
|
end
|
63
70
|
|
64
71
|
it 'emits a timer event for the block' do
|
65
72
|
expect(Hallmonitor::Dispatcher).to(
|
66
|
-
receive(:output).with(
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
receive(:output).with(
|
74
|
+
an_event.and(has_name(name))
|
75
|
+
)
|
76
|
+
)
|
77
|
+
subject.watch(name) { 'foo' }
|
70
78
|
end
|
71
79
|
|
72
80
|
describe 'with tags' do
|
@@ -75,44 +83,53 @@ RSpec.describe Hallmonitor::Monitored do
|
|
75
83
|
|
76
84
|
it 'emits an event with tags' do
|
77
85
|
expect(Hallmonitor::Dispatcher).to(
|
78
|
-
receive(:output).with(
|
79
|
-
|
80
|
-
|
81
|
-
|
86
|
+
receive(:output).with(
|
87
|
+
an_event.and(has_tags(tags))
|
88
|
+
)
|
89
|
+
)
|
90
|
+
subject.watch(name, tags: tags) { 'foo' }
|
82
91
|
end
|
83
92
|
end
|
84
93
|
|
85
94
|
describe 'when the block raises an error' do
|
86
95
|
it 'emits a timer for the block' do
|
87
96
|
expect(Hallmonitor::Dispatcher).to(
|
88
|
-
receive(:output).with(
|
97
|
+
receive(:output).with(
|
98
|
+
a_timed_event.and(has_name(name))
|
99
|
+
)
|
100
|
+
)
|
89
101
|
expect do
|
90
|
-
subject.watch(name)
|
91
|
-
fail 'OOPS!'
|
92
|
-
end
|
102
|
+
subject.watch(name) { fail 'OOPS!' }
|
93
103
|
end.to raise_error('OOPS!')
|
94
104
|
end
|
95
105
|
end
|
96
106
|
end
|
97
107
|
|
98
|
-
|
108
|
+
shared_examples 'for emit' do
|
99
109
|
describe 'with a string parameter' do
|
100
110
|
let(:name) { 'foo' }
|
101
111
|
|
102
112
|
it 'emits an event with the passed in name' do
|
103
113
|
expect(Hallmonitor::Dispatcher).to(
|
104
|
-
receive(:output).with(
|
114
|
+
receive(:output).with(
|
115
|
+
an_event.and(has_name(name))
|
116
|
+
)
|
117
|
+
)
|
118
|
+
|
105
119
|
subject.emit(name)
|
106
120
|
end
|
107
121
|
end
|
108
122
|
|
109
123
|
describe 'with tags' do
|
110
124
|
let(:name) { 'foo'}
|
111
|
-
let(:tags) { {'foo'
|
125
|
+
let(:tags) { {'foo' => 'bar', 'baz' => 6}}
|
112
126
|
|
113
127
|
it 'emits an event with tags' do
|
114
128
|
expect(Hallmonitor::Dispatcher).to(
|
115
|
-
receive(:output).with(
|
129
|
+
receive(:output).with(
|
130
|
+
an_event.and(has_tags(tags)).and(has_name(name))
|
131
|
+
)
|
132
|
+
)
|
116
133
|
subject.emit(name, tags: tags)
|
117
134
|
end
|
118
135
|
end
|
@@ -139,6 +156,27 @@ RSpec.describe Hallmonitor::Monitored do
|
|
139
156
|
subject.emit(event)
|
140
157
|
end
|
141
158
|
end
|
159
|
+
end
|
142
160
|
|
161
|
+
context 'Instance' do
|
162
|
+
subject { Thing.new }
|
163
|
+
context '#watch' do
|
164
|
+
include_examples 'for watch'
|
165
|
+
end
|
166
|
+
|
167
|
+
context '#emit' do
|
168
|
+
include_examples 'for emit'
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'Class' do
|
173
|
+
subject { Thing }
|
174
|
+
context '.watch' do
|
175
|
+
include_examples 'for watch'
|
176
|
+
end
|
177
|
+
|
178
|
+
context '.emit' do
|
179
|
+
include_examples 'for emit'
|
180
|
+
end
|
143
181
|
end
|
144
182
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hallmonitor/outputters/datadog'
|
3
|
+
|
4
|
+
module Hallmonitor
|
5
|
+
module Outputters
|
6
|
+
RSpec.describe Datadog do
|
7
|
+
let(:dogstatsd_client) { instance_double(::Datadog::Statsd) }
|
8
|
+
let(:outputter) { described_class.new(dogstatsd_client) }
|
9
|
+
|
10
|
+
it 'can be instantiated' do
|
11
|
+
expect { outputter }.to_not raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
context '#process' do
|
15
|
+
let(:event_name) { 'foo.bar.baz' }
|
16
|
+
let(:event_tags) { { foo: 'bar' } }
|
17
|
+
let(:event_tags_expected) { { tags: ['foo:bar'] } }
|
18
|
+
|
19
|
+
context 'with a timed event' do
|
20
|
+
let(:event) { TimedEvent.new(event_name, duration: 100, tags: event_tags) }
|
21
|
+
|
22
|
+
it 'sends the event to statsd' do
|
23
|
+
expect(dogstatsd_client).to(
|
24
|
+
receive(:timing)
|
25
|
+
.with(event_name, event.duration, event_tags_expected)
|
26
|
+
)
|
27
|
+
outputter.process(event)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with an event' do
|
32
|
+
let(:event) { Event.new(event_name, tags: event_tags) }
|
33
|
+
|
34
|
+
it 'sends the event to statsd' do
|
35
|
+
expect(dogstatsd_client).to(
|
36
|
+
receive(:count)
|
37
|
+
.with(event_name, event.count, event_tags_expected)
|
38
|
+
)
|
39
|
+
outputter.process(event)
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'that has multiple values' do
|
43
|
+
let(:values) { { foo: 1, bar: 2 } }
|
44
|
+
let(:event) do
|
45
|
+
Event.new(event_name, count: values, tags: event_tags)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'sends multiple events to statsd' do
|
49
|
+
expect(dogstatsd_client).to(
|
50
|
+
receive(:count)
|
51
|
+
.with(
|
52
|
+
"#{event_name}.foo",
|
53
|
+
event.count[:foo],
|
54
|
+
event_tags_expected
|
55
|
+
)
|
56
|
+
)
|
57
|
+
expect(dogstatsd_client).to(
|
58
|
+
receive(:count)
|
59
|
+
.with(
|
60
|
+
"#{event_name}.bar",
|
61
|
+
event.count[:bar],
|
62
|
+
event_tags_expected
|
63
|
+
)
|
64
|
+
)
|
65
|
+
outputter.process(event)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
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:
|
4
|
+
version: 5.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:
|
11
|
+
date: 2018-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -25,19 +25,19 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: dogstatsd-ruby
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,21 +67,21 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.2.2
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: pry-byebug
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,35 +95,35 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rdoc
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: rspec
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
117
|
+
version: '3.0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
124
|
+
version: '3.0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: yard
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
@@ -137,7 +137,7 @@ dependencies:
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: statsd-ruby
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - ">="
|
@@ -157,15 +157,8 @@ executables: []
|
|
157
157
|
extensions: []
|
158
158
|
extra_rdoc_files: []
|
159
159
|
files:
|
160
|
-
- ".document"
|
161
|
-
- ".gitignore"
|
162
|
-
- CHANGELOG.md
|
163
|
-
- Gemfile
|
164
160
|
- LICENSE.txt
|
165
161
|
- README.md
|
166
|
-
- Rakefile
|
167
|
-
- bin/example.rb
|
168
|
-
- hallmonitor.gemspec
|
169
162
|
- lib/hallmonitor.rb
|
170
163
|
- lib/hallmonitor/configuration.rb
|
171
164
|
- lib/hallmonitor/dispatcher.rb
|
@@ -174,7 +167,7 @@ files:
|
|
174
167
|
- lib/hallmonitor/middleware.rb
|
175
168
|
- lib/hallmonitor/monitored.rb
|
176
169
|
- lib/hallmonitor/outputter.rb
|
177
|
-
- lib/hallmonitor/outputters/
|
170
|
+
- lib/hallmonitor/outputters/datadog.rb
|
178
171
|
- lib/hallmonitor/outputters/influxdb.rb
|
179
172
|
- lib/hallmonitor/outputters/iooutputter.rb
|
180
173
|
- lib/hallmonitor/outputters/new_relic.rb
|
@@ -183,7 +176,7 @@ files:
|
|
183
176
|
- lib/hallmonitor/version.rb
|
184
177
|
- spec/hallmonitor/dispatcher_spec.rb
|
185
178
|
- spec/hallmonitor/monitored_spec.rb
|
186
|
-
- spec/hallmonitor/outputters/
|
179
|
+
- spec/hallmonitor/outputters/datadog_spec.rb
|
187
180
|
- spec/hallmonitor/outputters/influxdb_spec.rb
|
188
181
|
- spec/hallmonitor/outputters/statsd_outputter_spec.rb
|
189
182
|
- spec/spec_helper.rb
|
@@ -207,15 +200,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
200
|
version: '0'
|
208
201
|
requirements: []
|
209
202
|
rubyforge_project:
|
210
|
-
rubygems_version: 2.
|
203
|
+
rubygems_version: 2.5.2
|
211
204
|
signing_key:
|
212
205
|
specification_version: 4
|
213
206
|
summary: Simple Ruby Event Monitoring
|
214
207
|
test_files:
|
215
|
-
- spec/
|
208
|
+
- spec/spec_helper.rb
|
216
209
|
- spec/hallmonitor/monitored_spec.rb
|
217
|
-
- spec/hallmonitor/outputters/
|
210
|
+
- spec/hallmonitor/outputters/datadog_spec.rb
|
218
211
|
- spec/hallmonitor/outputters/influxdb_spec.rb
|
219
212
|
- spec/hallmonitor/outputters/statsd_outputter_spec.rb
|
220
|
-
- spec/
|
221
|
-
has_rdoc:
|
213
|
+
- spec/hallmonitor/dispatcher_spec.rb
|
data/.document
DELETED
data/.gitignore
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# rcov generated
|
2
|
-
coverage
|
3
|
-
coverage.data
|
4
|
-
|
5
|
-
# rdoc generated
|
6
|
-
rdoc
|
7
|
-
|
8
|
-
# yard generated
|
9
|
-
doc
|
10
|
-
.yardoc
|
11
|
-
|
12
|
-
# bundler
|
13
|
-
.bundle
|
14
|
-
|
15
|
-
# jeweler generated
|
16
|
-
pkg
|
17
|
-
|
18
|
-
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
19
|
-
#
|
20
|
-
# * Create a file at ~/.gitignore
|
21
|
-
# * Include files you want ignored
|
22
|
-
# * Run: git config --global core.excludesfile ~/.gitignore
|
23
|
-
#
|
24
|
-
# After doing this, these files will be ignored in all your git projects,
|
25
|
-
# saving you from having to 'pollute' every project you touch with them
|
26
|
-
#
|
27
|
-
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
28
|
-
#
|
29
|
-
# For MacOS:
|
30
|
-
#
|
31
|
-
#.DS_Store
|
32
|
-
|
33
|
-
# For TextMate
|
34
|
-
#*.tmproj
|
35
|
-
#tmtags
|
36
|
-
|
37
|
-
# For emacs:
|
38
|
-
#*~
|
39
|
-
#\#*
|
40
|
-
#.\#*
|
41
|
-
|
42
|
-
# For vim:
|
43
|
-
#*.swp
|
44
|
-
|
45
|
-
# For redcar:
|
46
|
-
#.redcar
|
47
|
-
|
48
|
-
# For rubinius:
|
49
|
-
#*.rbc
|
50
|
-
Gemfile.lock
|
data/CHANGELOG.md
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# Verison 4.2.0
|
2
|
-
- Added Dogstatsd outputter, thanks to mlahaye
|
3
|
-
|
4
|
-
# Version 4.0.0
|
5
|
-
- Changed initializer signature for InfluxDB outputter to use
|
6
|
-
keyword args.
|
7
|
-
- Added `attr_accessor` for InfluxDB Outputter's transformer
|
8
|
-
|
9
|
-
# Version 3.0.0
|
10
|
-
- Refactored the Transformer concept in the InfluxDB outputter so that
|
11
|
-
it is more flexible. This was in response to the InfluxDB client gem
|
12
|
-
"fixing" a bug where numerical values were previously always sent as
|
13
|
-
floats, now numbers are marked as "integer" type if they are ruby
|
14
|
-
Integers which can lead to some field-type conflicts if you update
|
15
|
-
your InfluxDB gem version and were previously sending integers at
|
16
|
-
floats. Using the Transformer now allows you to modify the values
|
17
|
-
that will be sent to InfluxDB immediately before they're sent out.x
|
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler/gem_tasks'
|
5
|
-
|
6
|
-
require 'rspec/core/rake_task'
|
7
|
-
RSpec::Core::RakeTask.new(:spec)
|
8
|
-
task :default => :spec
|
9
|
-
|
10
|
-
require 'rdoc/task'
|
11
|
-
Rake::RDocTask.new do |rdoc|
|
12
|
-
rdoc.rdoc_dir = 'rdoc'
|
13
|
-
rdoc.title = "hallmonitor #{Hallmonitor::Version::STRING}"
|
14
|
-
rdoc.rdoc_files.include('README*')
|
15
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
16
|
-
end
|
data/bin/example.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
lib = File.expand_path('../../lib', __FILE__)
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
|
6
|
-
require 'hallmonitor'
|
7
|
-
require 'hallmonitor/outputters/iooutputter'
|
8
|
-
require 'hallmonitor/outputters/statsd_outputter'
|
9
|
-
require 'pry'
|
10
|
-
|
11
|
-
Hallmonitor.add_outputter Hallmonitor::Outputters::IOOutputter.new("STDOUT", STDOUT)
|
12
|
-
Hallmonitor.add_outputter Hallmonitor::Outputters::StatsdOutputter.new("example", "localhost")
|
13
|
-
|
14
|
-
class Foo
|
15
|
-
include Hallmonitor::Monitored
|
16
|
-
|
17
|
-
def do_something
|
18
|
-
sleep_time_ms = ((Random.rand * 100).floor) * 2
|
19
|
-
puts "Sleeping for #{sleep_time_ms} milliseconds"
|
20
|
-
sleep(sleep_time_ms / 1000.0)
|
21
|
-
end
|
22
|
-
timer_for :do_something
|
23
|
-
count_for :do_something
|
24
|
-
|
25
|
-
def emit_events(count=30)
|
26
|
-
# Emit 100 events
|
27
|
-
count.times do
|
28
|
-
emit("event")
|
29
|
-
sleep(1)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def time_me
|
34
|
-
watch("timed") do |x|
|
35
|
-
sleep(5)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
f = Foo.new
|
41
|
-
|
42
|
-
puts 'Calling method with timer_for and count_for...'
|
43
|
-
f.do_something
|
44
|
-
|
45
|
-
puts 'Emitting some events'
|
46
|
-
f.emit_events(5)
|
47
|
-
|
48
|
-
puts 'Timing a 5 second block'
|
49
|
-
f.time_me
|
data/hallmonitor.gemspec
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
lib = File.expand_path('../lib', __FILE__)
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require 'hallmonitor/version'
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "hallmonitor"
|
7
|
-
s.version = Hallmonitor::Version::STRING
|
8
|
-
|
9
|
-
s.authors = ["Chris TenHarmsel"]
|
10
|
-
s.summary = "Simple Ruby Event Monitoring"
|
11
|
-
s.description = "Hallmonitor is a simple event monitoring framework in Ruby"
|
12
|
-
s.email = ["chris@tenharmsel.com"]
|
13
|
-
s.homepage = "http://github.com/epchris/hallmonitor"
|
14
|
-
s.licenses = ["MIT"]
|
15
|
-
|
16
|
-
s.files = `git ls-files`.split($/)
|
17
|
-
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
18
|
-
s.require_paths = ["lib"]
|
19
|
-
|
20
|
-
s.add_runtime_dependency("json", [">= 0"])
|
21
|
-
|
22
|
-
s.add_development_dependency("statsd-ruby", [">= 0"])
|
23
|
-
s.add_development_dependency("dogstatsd-ruby", [">= 0"])
|
24
|
-
s.add_development_dependency("influxdb", ["~> 0.2.2"])
|
25
|
-
s.add_development_dependency("rspec", [">= 3.0"])
|
26
|
-
s.add_development_dependency("rdoc", [">= 0"])
|
27
|
-
s.add_development_dependency("bundler", ["~> 1.3"])
|
28
|
-
s.add_development_dependency("pry-byebug", [">= 0"])
|
29
|
-
s.add_development_dependency("rake", [">= 0"])
|
30
|
-
s.add_development_dependency("yard", [">= 0"])
|
31
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'datadog/statsd'
|
3
|
-
rescue LoadError
|
4
|
-
end
|
5
|
-
|
6
|
-
module Hallmonitor
|
7
|
-
module Outputters
|
8
|
-
# An outputter for Dogstatsd
|
9
|
-
class DogstatsdOutputter < Outputter
|
10
|
-
# Builds a new DogstatsdOutputter.
|
11
|
-
# @param prefix [String] Prefix for all events output by this outputter,
|
12
|
-
# the prefix will be applied to all event names before sending to statsd
|
13
|
-
# @param host [String] Datadog Host, defaults to '127.0.0.1'
|
14
|
-
# @param port [Number] Datadog Port, defaults to 8125
|
15
|
-
# @raise if Datadog::Statsd is undefined (Gem not present)
|
16
|
-
def initialize(prefix, host = '127.0.0.1', port = 8125, tags: {})
|
17
|
-
unless defined?(Datadog::Statsd)
|
18
|
-
fail 'In order to use DogstatsdOutputter, dogstatsd-ruby gem must be installed'
|
19
|
-
end
|
20
|
-
|
21
|
-
super(prefix)
|
22
|
-
@tags = {}.merge(tags)
|
23
|
-
@statsd = Datadog::Statsd.new(host).tap { |sd| sd.namespace = name }
|
24
|
-
end
|
25
|
-
|
26
|
-
# Sends events to statsd instance
|
27
|
-
# If the event's value field is a hash, this will send multiple events
|
28
|
-
# to statsd with the original name suffixed by the name of the events
|
29
|
-
# in the hash
|
30
|
-
|
31
|
-
def process_tags(tags)
|
32
|
-
@tags.merge(tags).map {|key, value| "#{key}:#{value}"}
|
33
|
-
end
|
34
|
-
|
35
|
-
def process(event)
|
36
|
-
if event.is_a?(Hallmonitor::TimedEvent)
|
37
|
-
process_timed_event(event)
|
38
|
-
elsif event.is_a?(Hallmonitor::GaugeEvent)
|
39
|
-
process_gauge_event(event)
|
40
|
-
else
|
41
|
-
process_event(event)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def process_timed_event(event)
|
48
|
-
event_name = name_for(event)
|
49
|
-
if event.duration.is_a?(Hash)
|
50
|
-
event.duration.each do |name, value|
|
51
|
-
@statsd.timing("#{event_name}.#{name}", value, tags: process_tags(event.tags))
|
52
|
-
end
|
53
|
-
else
|
54
|
-
@statsd.timing(event_name, event.duration, tags: process_tags(event.tags))
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def process_gauge_event(event)
|
59
|
-
event_name = name_for(event)
|
60
|
-
if event.value.is_a?(Hash)
|
61
|
-
event.value.each do |name, value|
|
62
|
-
@statsd.gauge("#{event_name}.#{name}", value, tags: process_tags(event.tags))
|
63
|
-
end
|
64
|
-
else
|
65
|
-
@statsd.gauge(event_name, event.value, tags: process_tags(event.tags))
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def process_event(event)
|
70
|
-
event_name = name_for(event)
|
71
|
-
if event.count.is_a?(Hash)
|
72
|
-
event.count.each do |name, value|
|
73
|
-
@statsd.count("#{event_name}.#{name}", value, tags: process_tags(event.tags))
|
74
|
-
end
|
75
|
-
else
|
76
|
-
@statsd.count(event_name, event.count, tags: process_tags(event.tags))
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def name_for(event)
|
81
|
-
event.name
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'hallmonitor/outputters/dogstatsd_outputter'
|
3
|
-
|
4
|
-
module Hallmonitor
|
5
|
-
module Outputters
|
6
|
-
RSpec.describe DogstatsdOutputter do
|
7
|
-
let(:dogstatsd_client) { instance_double(Datadog::Statsd) }
|
8
|
-
let(:prefix) { 'test' }
|
9
|
-
let(:outputter) { described_class.new(prefix) }
|
10
|
-
|
11
|
-
before do
|
12
|
-
allow(dogstatsd_client).to receive(:namespace=)
|
13
|
-
allow(Datadog::Statsd).to receive(:new).and_return(dogstatsd_client)
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'can be instantiated' do
|
17
|
-
expect { outputter }.to_not raise_error
|
18
|
-
end
|
19
|
-
|
20
|
-
context '#process' do
|
21
|
-
let(:event_name) { 'foo.bar.baz' }
|
22
|
-
let(:event_tags) { {foo:"bar"} }
|
23
|
-
let(:event_tags_expected) {{tags:["foo:bar"]}}
|
24
|
-
context 'with an event' do
|
25
|
-
let(:event) { Event.new(name = event_name, tags: event_tags) }
|
26
|
-
|
27
|
-
it 'sends the event to statsd' do
|
28
|
-
expect(dogstatsd_client).to receive(:count).with(event_name, event.count, event_tags_expected)
|
29
|
-
outputter.process(event)
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'that has multiple values' do
|
33
|
-
let(:values) { { foo: 1, bar: 2 } }
|
34
|
-
let(:event) { Event.new(event_name, count: values, tags: event_tags) }
|
35
|
-
it 'sends multiple events to statsd' do
|
36
|
-
expect(dogstatsd_client).to receive(:count).with("#{event_name}.foo", event.count[:foo], event_tags_expected)
|
37
|
-
expect(dogstatsd_client).to receive(:count).with("#{event_name}.bar", event.count[:bar], event_tags_expected)
|
38
|
-
outputter.process(event)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|