fozzie 1.0.3 → 1.1.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/lib/fozzie/adapter.rb +1 -1
- data/lib/fozzie/adapter/datadog.rb +26 -0
- data/lib/fozzie/adapter/statsd.rb +94 -95
- data/lib/fozzie/bulk_dsl.rb +27 -28
- data/lib/fozzie/configuration.rb +0 -2
- data/lib/fozzie/dsl.rb +17 -19
- data/lib/fozzie/interface.rb +140 -140
- data/lib/fozzie/version.rb +3 -3
- data/spec/lib/fozzie/adapter/datadog_spec.rb +31 -0
- data/spec/lib/fozzie/adapter/statsd_spec.rb +82 -82
- data/spec/lib/fozzie/configuration_spec.rb +125 -125
- data/spec/lib/fozzie/rack/sinatra_spec.rb +31 -31
- data/spec/shared_examples/interface.rb +154 -160
- data/spec/spec_helper.rb +32 -29
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62870b7d38427ff5336337c4653e1d9a4baafd42
|
4
|
+
data.tar.gz: a89f19a1490f4b08b9eebe444c01f62b369c6594
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd6195e443aae3ce9a8069cf81522b0a924438cd25fa9ac1b04baf012df7d368cd0140798e08580150ffb63070e9d1af9d3461de8fd3b2f102cbf954b5a24613
|
7
|
+
data.tar.gz: a5037ff3afd5f73f1eb532049f643062849e4f6725297cf9521299cdd704d5b75407500d1938ef7b54120033b76869a9fe40b20fd1977f5e329144d61b039a92
|
data/lib/fozzie/adapter.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
%w{statsd}.each {|r| require "fozzie/adapter/#{r}" }
|
1
|
+
%w{statsd datadog}.each {|r| require "fozzie/adapter/#{r}" }
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'fozzie/adapter/statsd'
|
2
|
+
|
3
|
+
module Fozzie
|
4
|
+
module Adapter
|
5
|
+
class Datadog < Statsd
|
6
|
+
|
7
|
+
# stats is a collection of hashes in the following format:
|
8
|
+
# { :bucket => stat, :value => value, :type => type, :sample_rate => sample_rate, tags => ["serviceid:fozzie","country:au"] }
|
9
|
+
def register(*stats)
|
10
|
+
metrics = stats.flatten.map do |stat|
|
11
|
+
next if sampled?(stat[:sample_rate])
|
12
|
+
|
13
|
+
bucket = format_bucket(stat[:bucket])
|
14
|
+
value = format_value(stat[:value], stat[:type], stat[:sample_rate])
|
15
|
+
tags = (stat[:tags] || []).map {|tag| tag.gsub(/[,\|]/, RESERVED_CHARS_REPLACEMENT)}
|
16
|
+
|
17
|
+
result = "#{bucket}:#{value}"
|
18
|
+
result << "|##{tags.join(',')}" if tags.any?
|
19
|
+
result
|
20
|
+
end.compact.join(BULK_DELIMETER)
|
21
|
+
|
22
|
+
send_to_socket(metrics)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,95 +1,94 @@
|
|
1
|
-
require 'socket'
|
2
|
-
require 'resolv'
|
3
|
-
|
4
|
-
module Fozzie
|
5
|
-
module Adapter
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
bucket =
|
34
|
-
bucket =
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
converted_type
|
42
|
-
|
43
|
-
|
44
|
-
value
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
Fozzie.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
1
|
+
require 'socket'
|
2
|
+
require 'resolv'
|
3
|
+
|
4
|
+
module Fozzie
|
5
|
+
module Adapter
|
6
|
+
class Statsd
|
7
|
+
|
8
|
+
RESERVED_CHARS_REGEX = /[\:\|\@\s]/
|
9
|
+
RESERVED_CHARS_REPLACEMENT = '_'
|
10
|
+
DELIMETER = '.'
|
11
|
+
SAFE_SEPARATOR = '-'
|
12
|
+
TYPES = { :gauge => 'g', :count => 'c', :timing => 'ms' }
|
13
|
+
BULK_DELIMETER = "\n"
|
14
|
+
|
15
|
+
# Send the statistic to the server
|
16
|
+
#
|
17
|
+
# Creates the Statsd key from the given values, and sends to socket (depending on sample rate)
|
18
|
+
def register(*stats)
|
19
|
+
metrics = stats.flatten.map do |stat|
|
20
|
+
next if sampled?(stat[:sample_rate])
|
21
|
+
|
22
|
+
bucket = format_bucket(stat[:bucket])
|
23
|
+
value = format_value(stat[:value], stat[:type], stat[:sample_rate])
|
24
|
+
|
25
|
+
[bucket, value].join(':')
|
26
|
+
end.compact.join(BULK_DELIMETER)
|
27
|
+
|
28
|
+
send_to_socket(metrics)
|
29
|
+
end
|
30
|
+
|
31
|
+
def format_bucket(stat)
|
32
|
+
bucket = [stat].flatten.compact.collect(&:to_s).join(DELIMETER).downcase
|
33
|
+
bucket = bucket.gsub('::', DELIMETER).gsub(RESERVED_CHARS_REGEX, RESERVED_CHARS_REPLACEMENT)
|
34
|
+
bucket = [Fozzie.c.data_prefix, bucket].compact.join(DELIMETER)
|
35
|
+
|
36
|
+
bucket
|
37
|
+
end
|
38
|
+
|
39
|
+
def format_value(val, type, sample_rate)
|
40
|
+
converted_type = TYPES[type.to_sym]
|
41
|
+
converted_type ||= TYPES[:gauge]
|
42
|
+
|
43
|
+
value = [val, converted_type].join('|')
|
44
|
+
value << '@%s' % sample_rate.to_s if sample_rate < 1
|
45
|
+
|
46
|
+
value
|
47
|
+
end
|
48
|
+
|
49
|
+
# If the statistic is sampled, generate a condition to check if it's good to send
|
50
|
+
def sampled(sample_rate)
|
51
|
+
yield unless sampled?(sample_rate)
|
52
|
+
end
|
53
|
+
|
54
|
+
def sampled?(sample_rate)
|
55
|
+
sample_rate < 1 and rand > sample_rate
|
56
|
+
end
|
57
|
+
|
58
|
+
# Send data to the server via the socket
|
59
|
+
def send_to_socket(message)
|
60
|
+
Fozzie.logger.debug {"Statsd: #{message}"} if Fozzie.logger
|
61
|
+
Timeout.timeout(Fozzie.c.timeout) {
|
62
|
+
res = socket.send(message, 0, host_ip, host_port)
|
63
|
+
Fozzie.logger.debug {"Statsd sent: #{res}"} if Fozzie.logger
|
64
|
+
(res.to_i == message.length)
|
65
|
+
}
|
66
|
+
rescue => exc
|
67
|
+
Fozzie.logger.debug {"Statsd Failure: #{exc.message}\n#{exc.backtrace}"} if Fozzie.logger
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
# The Socket we want to use to send data
|
72
|
+
def socket
|
73
|
+
@socket ||= ::UDPSocket.new
|
74
|
+
end
|
75
|
+
|
76
|
+
def host_ip
|
77
|
+
@host_ip ||= Resolv.getaddress(Fozzie.c.host)
|
78
|
+
end
|
79
|
+
|
80
|
+
def host_port
|
81
|
+
@host_port ||= Fozzie.c.port
|
82
|
+
end
|
83
|
+
|
84
|
+
def delimeter
|
85
|
+
DELIMETER
|
86
|
+
end
|
87
|
+
|
88
|
+
def safe_separator
|
89
|
+
SAFE_SEPARATOR
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
data/lib/fozzie/bulk_dsl.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
|
-
module Fozzie
|
2
|
-
class BulkDsl
|
3
|
-
include Fozzie::Interface
|
4
|
-
|
5
|
-
def initialize(&block)
|
6
|
-
@metrics = []
|
7
|
-
block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
|
8
|
-
send_bulk
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
# Cache the requested metrics for bulk sending
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
1
|
+
module Fozzie
|
2
|
+
class BulkDsl
|
3
|
+
include Fozzie::Interface
|
4
|
+
|
5
|
+
def initialize(&block)
|
6
|
+
@metrics = []
|
7
|
+
block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
|
8
|
+
send_bulk
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Cache the requested metrics for bulk sending
|
14
|
+
def send(stat, value, type, sample_rate = 1, extra = {})
|
15
|
+
val = extra.merge({ :bucket => stat, :value => value, :type => type, :sample_rate => sample_rate })
|
16
|
+
|
17
|
+
@metrics.push(val)
|
18
|
+
end
|
19
|
+
|
20
|
+
def send_bulk
|
21
|
+
return if @metrics.empty?
|
22
|
+
|
23
|
+
adapter.register(@metrics)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/fozzie/configuration.rb
CHANGED
data/lib/fozzie/dsl.rb
CHANGED
@@ -1,19 +1,17 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
require "fozzie/interface"
|
3
|
-
|
4
|
-
module Fozzie
|
5
|
-
class Dsl
|
6
|
-
include Fozzie::Interface, Singleton
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
# Send the statistic to the chosen provider
|
11
|
-
#
|
12
|
-
def send(stat, value, type, sample_rate = 1)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
1
|
+
require 'singleton'
|
2
|
+
require "fozzie/interface"
|
3
|
+
|
4
|
+
module Fozzie
|
5
|
+
class Dsl
|
6
|
+
include Fozzie::Interface, Singleton
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
# Send the statistic to the chosen provider
|
11
|
+
#
|
12
|
+
def send(stat, value, type, sample_rate = 1, extra = {})
|
13
|
+
val = extra.merge(:bucket => stat, :value => value, :type => type, :sample_rate => sample_rate)
|
14
|
+
adapter.register(val)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/fozzie/interface.rb
CHANGED
@@ -1,140 +1,140 @@
|
|
1
|
-
require 'fozzie/adapter/statsd'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
#
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
#
|
46
|
-
#
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
#
|
60
|
-
#
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
#
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
#
|
74
|
-
#
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
#
|
81
|
-
#
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
#
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
#
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
#
|
102
|
-
#
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
#
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
#
|
118
|
-
#
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
end
|
1
|
+
require 'fozzie/adapter/statsd'
|
2
|
+
require 'fozzie/adapter/datadog'
|
3
|
+
|
4
|
+
module Fozzie
|
5
|
+
module Interface
|
6
|
+
|
7
|
+
# Increments the given stat by one, with an optional sample rate
|
8
|
+
#
|
9
|
+
# `Stats.increment 'wat'`
|
10
|
+
def increment(stat, sample_rate=1, extra = {})
|
11
|
+
count(stat, 1, sample_rate, extra)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Decrements the given stat by one, with an optional sample rate
|
15
|
+
#
|
16
|
+
# `Stats.decrement 'wat'`
|
17
|
+
def decrement(stat, sample_rate=1, extra = {})
|
18
|
+
count(stat, -1, sample_rate, extra)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Registers a count for the given stat, with an optional sample rate
|
22
|
+
#
|
23
|
+
# `Stats.count 'wat', 500`
|
24
|
+
def count(stat, count, sample_rate=1, extra = {})
|
25
|
+
send(stat, count, :count, sample_rate, extra)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Registers a timing (in ms) for the given stat, with an optional sample rate
|
29
|
+
#
|
30
|
+
# `Stats.timing 'wat', 500`
|
31
|
+
def timing(stat, ms, sample_rate=1, extra = {})
|
32
|
+
send(stat, ms, :timing, sample_rate, extra)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Registers the time taken to complete a given block (in ms), with an optional sample rate
|
36
|
+
#
|
37
|
+
# `Stats.time 'wat' { # Do something... }`
|
38
|
+
def time(stat, sample_rate=1, extra = {})
|
39
|
+
start = Time.now
|
40
|
+
result = yield
|
41
|
+
timing(stat, ((Time.now - start) * 1000).round, sample_rate, extra)
|
42
|
+
result
|
43
|
+
end
|
44
|
+
|
45
|
+
# Registers the time taken to complete a given block (in ms), with an optional sample rate
|
46
|
+
#
|
47
|
+
# `Stats.time_to_do 'wat' { # Do something, again... }`
|
48
|
+
def time_to_do(stat, sample_rate=1, extra = {}, &block)
|
49
|
+
time(stat, sample_rate, extra, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Registers the time taken to complete a given block (in ms), with an optional sample rate
|
53
|
+
#
|
54
|
+
# `Stats.time_for 'wat' { # Do something, grrr... }`
|
55
|
+
def time_for(stat, sample_rate=1, extra = {}, &block)
|
56
|
+
time(stat, sample_rate, extra, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Registers a commit
|
60
|
+
#
|
61
|
+
# `Stats.commit`
|
62
|
+
def commit(extra = {})
|
63
|
+
event(:commit, nil, extra)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Registers a commit
|
67
|
+
#
|
68
|
+
# `Stats.commit`
|
69
|
+
def committed(extra = {})
|
70
|
+
commit(extra)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Registers that the app has been built
|
74
|
+
#
|
75
|
+
# `Stats.built`
|
76
|
+
def built(extra = {})
|
77
|
+
event(:build, nil, extra)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Registers a build for the app
|
81
|
+
#
|
82
|
+
# `Stats.build`
|
83
|
+
def build(extra = {})
|
84
|
+
built(extra)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Registers a deployed status for the given app
|
88
|
+
#
|
89
|
+
# `Stats.deployed 'watapp'`
|
90
|
+
def deployed(app = nil, extra = {})
|
91
|
+
event(:deploy, app, extra)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Registers a deployment for the given app
|
95
|
+
#
|
96
|
+
# `Stats.deploy 'watapp'`
|
97
|
+
def deploy(app = nil, extra = {})
|
98
|
+
deployed(app, extra)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Register an event of any type
|
102
|
+
#
|
103
|
+
# `Stats.event 'wat', 'app'`
|
104
|
+
def event(type, app = nil, extra = {})
|
105
|
+
gauge(["event", type.to_s, app], Time.now.usec, 1, extra)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Registers an increment on the result of the given boolean
|
109
|
+
#
|
110
|
+
# `Stats.increment_on 'wat', wat.random?`
|
111
|
+
def increment_on(stat, perf, sample_rate=1, extra = {})
|
112
|
+
key = [stat, (perf ? "success" : "fail")]
|
113
|
+
increment(key, sample_rate, extra)
|
114
|
+
perf
|
115
|
+
end
|
116
|
+
|
117
|
+
# Register an arbitrary value
|
118
|
+
#
|
119
|
+
# `Stats.gauge 'wat', 'app'`
|
120
|
+
def gauge(stat, value, sample_rate = 1, extra = {})
|
121
|
+
send(stat, value, :gauge, sample_rate, extra)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Register multiple statistics in a single call
|
125
|
+
#
|
126
|
+
# `Stats.bulk do
|
127
|
+
# increment 'wat'
|
128
|
+
# decrement 'wot'
|
129
|
+
# end`
|
130
|
+
def bulk(&block)
|
131
|
+
Fozzie::BulkDsl.new(&block)
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def adapter
|
137
|
+
Fozzie.c.adapter
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|