librato-rack 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,33 +5,40 @@ require 'rack/test'
5
5
  #
6
6
  class CustomTest < Minitest::Test
7
7
  include Rack::Test::Methods
8
+ include EnvironmentHelpers
8
9
 
9
10
  def app
10
11
  Rack::Builder.parse_file('test/apps/custom.ru').first
11
12
  end
12
13
 
14
+ def setup
15
+ ENV["LIBRATO_TAGS"] = "hostname=metrics-web-stg-1"
16
+ @tags = { hostname: "metrics-web-stg-1" }
17
+ end
18
+
13
19
  def teardown
14
20
  # clear metrics before each run
15
21
  aggregate.delete_all
16
22
  counters.delete_all
23
+ clear_config_env_vars
17
24
  end
18
25
 
19
26
  def test_increment
20
27
  get '/increment'
21
- assert_equal 1, counters[:hits]
28
+ assert_equal 1, counters[:hits][:value]
22
29
  2.times { get '/increment' }
23
- assert_equal 3, counters[:hits]
30
+ assert_equal 3, counters[:hits][:value]
24
31
  end
25
32
 
26
33
  def test_measure
27
34
  get '/measure'
28
- assert_equal 3.0, aggregate[:nodes][:sum]
29
- assert_equal 1, aggregate[:nodes][:count]
35
+ assert_equal 3.0, aggregate.fetch(:nodes, @tags)[:sum]
36
+ assert_equal 1, aggregate.fetch(:nodes, @tags)[:count]
30
37
  end
31
38
 
32
39
  def test_timing
33
40
  get '/timing'
34
- assert_equal 1, aggregate['lookup.time'][:count]
41
+ assert_equal 1, aggregate.fetch("lookup.time", @tags)[:count]
35
42
  end
36
43
 
37
44
  def test_timing_block
@@ -42,10 +49,17 @@ class CustomTest < Minitest::Test
42
49
 
43
50
  def test_grouping
44
51
  get '/group'
45
- assert_equal 1, counters['did.a.thing']
52
+ assert_equal 1, counters['did.a.thing'][:value]
46
53
  assert_equal 1, aggregate['did.a.timing'][:count]
47
54
  end
48
55
 
56
+ def test_tags
57
+ tags = { region: "us-east-1" }
58
+ get '/tags'
59
+ assert_equal 1, counters.fetch("requests", tags: tags)[:value]
60
+ assert_equal 1, aggregate.fetch("requests.time", tags: tags)[:count]
61
+ end
62
+
49
63
  private
50
64
 
51
65
  def aggregate
@@ -20,9 +20,8 @@ class NoStatsTest < Minitest::Test
20
20
  get '/'
21
21
  assert last_response.ok?
22
22
 
23
- assert_nil counters["rack.request.total"]
24
- assert_nil counters["rack.request.status.200"]
25
- assert_nil counters["rack.request.status.2xx"]
23
+ assert_nil counters["rack.request"]
24
+ assert_nil counters["rack.request.status"]
26
25
  end
27
26
 
28
27
  def test_no_standard_measures
@@ -24,7 +24,7 @@ class NoSuitesTest < Minitest::Test
24
24
  def test_increment_total
25
25
  get '/'
26
26
  assert last_response.ok?
27
- assert_nil counters["rack.request.total"], 'should not increment'
27
+ assert_nil counters["rack.request"], "should not increment"
28
28
  end
29
29
 
30
30
  def test_track_queue_time
@@ -36,16 +36,15 @@ class NoSuitesTest < Minitest::Test
36
36
  def test_increment_status
37
37
  get '/'
38
38
  assert last_response.ok?
39
- assert_nil counters["rack.request.status.200"], 'should not increment'
40
- assert_nil counters["rack.request.status.2xx"], 'should not increment'
39
+ assert_nil counters["rack.request.status"], "should not increment"
41
40
  end
42
41
 
43
42
  def test_track_http_method_info
44
43
  get '/'
45
- assert_nil counters['rack.request.method.get']
44
+ assert_nil counters["rack.request.method"]
46
45
 
47
46
  post '/'
48
- assert_nil counters['rack.request.method.post']
47
+ assert_nil counters["rack.request.method"]
49
48
  end
50
49
 
51
50
  def test_increment_exception
@@ -19,13 +19,10 @@ class QueueWaitTest < Minitest::Test
19
19
  def test_milliseconds
20
20
  get '/milli'
21
21
 
22
- # give jruby a bit more time since it can be slow
23
- delta = defined?(JRUBY_VERSION) ? 6 : 4
24
-
25
22
  # puts "milli: #{aggregate["rack.request.queue.time"].inspect}"
26
23
  assert_equal 1, aggregate["rack.request.queue.time"][:count],
27
24
  'should track total queue time'
28
- assert_in_delta 5, aggregate["rack.request.queue.time"][:sum], delta
25
+ assert_in_delta 5, aggregate["rack.request.queue.time"][:sum], 4
29
26
  end
30
27
 
31
28
  def test_microseconds
@@ -40,13 +37,10 @@ class QueueWaitTest < Minitest::Test
40
37
  def test_queue_start
41
38
  get '/queue_start'
42
39
 
43
- # give jruby a bit more time since it can be slow
44
- delta = defined?(JRUBY_VERSION) ? 6 : 4
45
-
46
40
  # puts "micro: #{aggregate["rack.request.queue.time"].inspect}"
47
41
  assert_equal 1, aggregate["rack.request.queue.time"][:count],
48
42
  'should track total queue time'
49
- assert_in_delta 15, aggregate["rack.request.queue.time"][:sum], delta
43
+ assert_in_delta 15, aggregate["rack.request.queue.time"][:sum], 6
50
44
  end
51
45
 
52
46
  def test_with_t
@@ -55,14 +49,14 @@ class QueueWaitTest < Minitest::Test
55
49
  # puts "micro: #{aggregate["rack.request.queue.time"].inspect}"
56
50
  assert_equal 1, aggregate["rack.request.queue.time"][:count],
57
51
  'should track total queue time'
58
- assert_in_delta 20, aggregate["rack.request.queue.time"][:sum], 4
52
+ assert_in_delta 20, aggregate["rack.request.queue.time"][:sum], 6
59
53
  end
60
54
 
61
55
  def test_with_period
62
56
  get '/with_period'
63
57
 
64
58
  # give jruby a bit more time since it can be slow
65
- delta = defined?(JRUBY_VERSION) ? 10 : 4
59
+ delta = defined?(JRUBY_VERSION) ? 10 : 6
66
60
  assert_equal 1, aggregate["rack.request.queue.time"][:count],
67
61
  'should track total queue time'
68
62
  assert_in_delta 25, aggregate["rack.request.queue.time"][:sum], delta
@@ -5,29 +5,34 @@ require 'rack/test'
5
5
  #
6
6
  class RequestTest < Minitest::Test
7
7
  include Rack::Test::Methods
8
+ include EnvironmentHelpers
8
9
 
9
10
  def app
10
11
  Rack::Builder.parse_file('test/apps/basic.ru').first
11
12
  end
12
13
 
14
+ def setup
15
+ ENV["LIBRATO_TAGS"] = "hostname=metrics-web-stg-1"
16
+ @tags = { hostname: "metrics-web-stg-1" }
17
+ end
18
+
13
19
  def teardown
14
20
  # clear metrics before each run
15
21
  aggregate.delete_all
16
22
  counters.delete_all
23
+ clear_config_env_vars
17
24
  end
18
25
 
19
26
  def test_increment_total_and_status
20
27
  get '/'
21
28
  assert last_response.ok?
22
- assert_equal 1, counters["rack.request.total"]
23
- assert_equal 1, counters["rack.request.status.200"]
24
- assert_equal 1, counters["rack.request.status.2xx"]
29
+ assert_equal 1, counters["rack.request.total"][:value]
30
+ assert_equal 1, counters.fetch("rack.request.status", tags: @tags.merge({ status: 200 }))[:value]
25
31
 
26
32
  get '/status/204'
27
- assert_equal 2, counters["rack.request.total"]
28
- assert_equal 1, counters["rack.request.status.200"], 'should not increment'
29
- assert_equal 1, counters["rack.request.status.204"], 'should increment'
30
- assert_equal 2, counters["rack.request.status.2xx"]
33
+ assert_equal 2, counters["rack.request.total"][:value]
34
+ assert_equal 1, counters.fetch("rack.request.status", tags: @tags.merge({ status: 200 }))[:value], "should not increment"
35
+ assert_equal 1, counters.fetch("rack.request.status", tags: @tags.merge({ status: 204 }))[:value], "should increment"
31
36
  end
32
37
 
33
38
  def test_request_times
@@ -38,30 +43,22 @@ class RequestTest < Minitest::Test
38
43
  'should track total request time'
39
44
 
40
45
  # should calculate p95 value
41
- assert aggregate.fetch("rack.request.time", percentile: 95) > 0.0
46
+ assert aggregate.fetch("rack.request.time", tags: @tags, percentile: 95) > 0.0
42
47
 
43
48
  # status specific
44
- assert_equal 1, aggregate["rack.request.status.200.time"][:count]
45
- assert_equal 1, aggregate["rack.request.status.2xx.time"][:count]
49
+ assert_equal 1, aggregate.fetch("rack.request.status.time", tags: @tags.merge({ status: 200 }))[:count]
46
50
  end
47
51
 
48
52
  def test_track_http_method_info
49
53
  get '/'
50
54
 
51
- assert_equal 1, counters['rack.request.method.get']
52
- assert_equal 1, aggregate['rack.request.method.get.time'][:count]
55
+ assert_equal 1, counters.fetch("rack.request.method", tags: @tags.merge({ method: "GET" }))[:value]
56
+ assert_equal 1, aggregate.fetch("rack.request.method.time", tags: @tags.merge({ method: "get" }))[:count]
53
57
 
54
58
  post '/'
55
59
 
56
- assert_equal 1, counters['rack.request.method.post']
57
- assert_equal 1, aggregate['rack.request.method.post.time'][:count]
58
- end
59
-
60
- def test_request_method_not_mutated
61
- get '/', {}, {'REQUEST_METHOD' => "GET".freeze}
62
-
63
- assert_equal 1, counters['rack.request.method.get']
64
- assert_equal 1, aggregate['rack.request.method.get.time'][:count]
60
+ assert_equal 1, counters.fetch("rack.request.method", tags: @tags.merge({ method: "POST" }))[:value]
61
+ assert_equal 1, aggregate.fetch("rack.request.method.time", tags: @tags.merge({ method: "post" }))[:count]
65
62
  end
66
63
 
67
64
  def test_track_exceptions
@@ -70,12 +67,12 @@ class RequestTest < Minitest::Test
70
67
  rescue RuntimeError => e
71
68
  raise unless e.message == 'exception raised!'
72
69
  end
73
- assert_equal 1, counters["rack.request.exceptions"]
70
+ assert_equal 1, counters["rack.request.exceptions"][:value]
74
71
  end
75
72
 
76
73
  def test_track_slow_requests
77
74
  get '/slow'
78
- assert_equal 1, counters["rack.request.slow"]
75
+ assert_equal 1, counters["rack.request.slow"][:value]
79
76
  end
80
77
 
81
78
  private
@@ -21,18 +21,16 @@ class SuitesTest < Minitest::Test
21
21
  assert last_response.ok?
22
22
 
23
23
  # rack.request metrics (rack suite) should get logged
24
- assert_equal 1, counters["rack.request.total"]
24
+ assert_equal 1, counters["rack.request.total"][:value]
25
25
  assert_equal 1, aggregate["rack.request.time"][:count]
26
26
 
27
27
  # rack.request.method metrics (rack_method suite) should not get logged
28
- assert_nil counters['rack.request.method.get']
29
- assert_nil aggregate['rack.request.method.get.time']
28
+ assert_nil counters.fetch("rack.request.method", tags: { method: "GET" })
29
+ assert_nil aggregate.fetch("rack.request.method.time", tags: { method: "get" })
30
30
 
31
31
  # rack.request.status metrics (rack_status suite) should not get logged
32
- assert_nil counters["rack.request.status.200"]
33
- assert_nil counters["rack.request.status.2xx"]
34
- assert_nil counters["rack.request.status.200.time"]
35
- assert_nil counters["rack.request.status.2xx.time"]
32
+ assert_nil counters.fetch("rack.request.status", tags: { status: 200, status_message: "OK" })
33
+ assert_nil counters.fetch("rack.request.status.time", tags: { status: 200, status_message: "OK" })
36
34
  end
37
35
 
38
36
  private
@@ -27,24 +27,26 @@ class TrackerRemoteTest < Minitest::Test
27
27
  end
28
28
 
29
29
  def test_flush_counters
30
- tracker.increment :foo # simple
31
- tracker.increment :bar, 2 # specified
32
- tracker.increment :foo # multincrement
33
- tracker.increment :foo, source: 'baz', by: 3 # custom source
30
+ tracker.increment :foo # simple
31
+ tracker.increment :bar, 2 # specified
32
+ tracker.increment :foo # multincrement
33
+ tracker.increment :foo, tags: { hostname: "baz" }, by: 3 # custom source
34
34
  @queued = tracker.queued
35
35
  tracker.flush
36
36
 
37
+ sleep 15 # TODO: retry logic for replica delay
38
+
37
39
  # metrics are SSA, so should exist but won't have measurements yet
38
- metric_names = client.list.map { |m| m['name'] }
40
+ metric_names = client.metrics.map { |m| m['name'] }
39
41
  assert metric_names.include?('foo'), 'foo should be present'
40
42
  assert metric_names.include?('bar'), 'bar should be present'
41
43
 
42
44
  # interogate queued payload for expected values
43
- assert_equal source, @queued[:source]
45
+ assert_equal [:host], @queued[:measurements].first[:tags].keys
44
46
  assert_equal 2, queued('foo')
45
47
 
46
48
  # custom source
47
- assert_equal 3, queued('foo', source: 'baz')
49
+ assert_equal 3, queued("foo", tags: { hostname: "baz" })
48
50
 
49
51
  # different counter
50
52
  assert_equal 2, queued('bar')
@@ -53,39 +55,41 @@ class TrackerRemoteTest < Minitest::Test
53
55
  def test_counter_persistent_through_flush
54
56
  tracker.increment 'knightrider'
55
57
  tracker.increment 'badguys', sporadic: true
56
- assert_equal 1, collector.counters['knightrider']
57
- assert_equal 1, collector.counters['badguys']
58
+ assert_equal 1, collector.counters['knightrider'][:value]
59
+ assert_equal 1, collector.counters['badguys'][:value]
58
60
 
59
61
  tracker.flush
60
- assert_equal 0, collector.counters['knightrider']
62
+ assert_equal 0, collector.counters['knightrider'][:value]
61
63
  assert_nil collector.counters['badguys']
62
64
  end
63
65
 
64
66
  def test_flush_should_send_measures_and_timings
65
- tracker.timing 'request.time.total', 122.1
67
+ tracker.timing "request.time", 122.1
66
68
  tracker.measure 'items_bought', 20
67
- tracker.timing 'request.time.total', 81.3
68
- tracker.timing 'jobs.queued', 5, source: 'worker.3'
69
+ tracker.timing "request.time", 81.3
70
+ tracker.timing "jobs.queued", 5, tags: { hostname: "worker.3" }
69
71
  @queued = tracker.queued
70
72
  tracker.flush
71
73
 
74
+ sleep 15 # TODO: retry logic for replica delay
75
+
72
76
  # metrics are SSA, so should exist but won't have measurements yet
73
- metric_names = client.list.map { |m| m['name'] }
74
- assert metric_names.include?('request.time.total'), 'request.time.total should be present'
77
+ metric_names = client.metrics.map { |m| m['name'] }
78
+ assert metric_names.include?('request.time'), 'request.time should be present'
75
79
  assert metric_names.include?('items_bought'), 'request.time.db should be present'
76
80
 
77
- assert_equal 2, queued('request.time.total')[:count]
78
- assert_in_delta 203.4, queued('request.time.total')[:sum], 0.1
81
+ assert_equal 2, queued("request.time", tags: tags)[:count]
82
+ assert_in_delta 203.4, queued("request.time", tags: tags)[:sum], 0.1
79
83
 
80
- assert_equal 1, queued('items_bought')[:count]
81
- assert_in_delta 20, queued('items_bought')[:sum], 0.1
84
+ assert_equal 1, queued("items_bought", tags: tags)[:count]
85
+ assert_in_delta 20, queued("items_bought", tags: tags)[:sum], 0.1
82
86
 
83
- assert_equal 1, queued('jobs.queued', source: 'worker.3')[:count]
84
- assert_in_delta 5, queued('jobs.queued', source: 'worker.3')[:sum], 0.1
87
+ assert_equal 1, queued("jobs.queued", tags: { hostname: "worker.3" })[:count]
88
+ assert_in_delta 5, queued("jobs.queued", tags: { hostname: "worker.3" })[:sum], 0.1
85
89
  end
86
90
 
87
91
  def test_flush_should_purge_measures_and_timings
88
- tracker.timing 'request.time.total', 122.1
92
+ tracker.timing "request.time", 122.1
89
93
  tracker.measure 'items_bought', 20
90
94
  tracker.flush
91
95
 
@@ -94,29 +98,33 @@ class TrackerRemoteTest < Minitest::Test
94
98
  end
95
99
 
96
100
  def test_flush_respects_prefix
101
+ tags = { hostname: "metrics-web-stg-1" }
97
102
  config.prefix = 'testyprefix'
98
103
 
99
- tracker.timing 'mytime', 221.1
104
+ tracker.timing "mytime", 221.1, tags: tags
100
105
  tracker.increment 'mycount', 4
101
106
  @queued = tracker.queued
102
107
  tracker.flush
103
108
 
104
- metric_names = client.list.map { |m| m['name'] }
109
+ sleep 15 # TODO: retry logic for replica delay
110
+
111
+ metric_names = client.metrics.map { |m| m['name'] }
112
+
105
113
  assert metric_names.include?('testyprefix.mytime'),
106
114
  'testyprefix.mytime should be present'
107
115
  assert metric_names.include?('testyprefix.mycount'), '
108
116
  testyprefix.mycount should be present'
109
117
 
110
- assert_equal 1, queued('testyprefix.mytime')[:count]
118
+ assert_equal 1, queued("testyprefix.mytime", tags: tags)[:count]
111
119
  assert_equal 4, queued('testyprefix.mycount')
112
120
  end
113
121
 
114
122
  def test_flush_recovers_from_failure
115
123
  # create a metric foo of counter type
116
- client.submit foo: {type: :counter, value: 12}
124
+ client.submit test_counter: { type: :counter, value: 12 }
117
125
 
118
126
  # failing flush - submit a foo measurement as a gauge (type mismatch)
119
- tracker.measure :foo, 2.12
127
+ tracker.measure :test_counter, 2.12
120
128
 
121
129
  # won't be accepted
122
130
  tracker.flush
@@ -124,7 +132,7 @@ class TrackerRemoteTest < Minitest::Test
124
132
  tracker.measure :boo, 2.12
125
133
  tracker.flush
126
134
 
127
- metric_names = client.list.map { |m| m['name'] }
135
+ metric_names = client.metrics.map { |m| m['name'] }
128
136
  assert metric_names.include?('boo')
129
137
  end
130
138
 
@@ -135,24 +143,24 @@ class TrackerRemoteTest < Minitest::Test
135
143
  @queued = tracker.queued
136
144
  tracker.flush
137
145
 
138
- metric_names = client.list.map { |m| m['name'] }
146
+ metric_names = client.metrics.map { |m| m['name'] }
139
147
  assert metric_names.include?('foo')
140
148
 
141
149
  # should be sending value for foo
142
150
  assert_equal 1.0, queued('foo')
143
151
  end
144
152
 
145
- def test_flush_handles_invalid_sources_names
146
- tracker.increment :foo, source: 'atreides' # valid
147
- tracker.increment :bar, source: 'glébnöst' # invalid
148
- tracker.measure 'baz', 2.25, source: 'b/l/ak/nok' # invalid
153
+ def test_flush_handles_invalid_tags
154
+ tracker.increment :foo, tags: { hostname: "atreides" } # valid
155
+ tracker.increment :bar, tags: { hostname: "glébnöst" } # invalid
156
+ tracker.measure 'baz', 2.25, tags: { hostname: "b/l/ak/nok" } # invalid
149
157
  @queued = tracker.queued
150
158
  tracker.flush
151
159
 
152
- metric_names = client.list.map { |m| m['name'] }
160
+ metric_names = client.metrics.map { |m| m['name'] }
153
161
  assert metric_names.include?('foo')
154
162
 
155
- assert_equal 1.0, queued('foo', source: 'atreides')
163
+ assert_equal 1.0, queued("foo", tags: { hostname: "atreides" })
156
164
  end
157
165
 
158
166
  private
@@ -176,29 +184,29 @@ class TrackerRemoteTest < Minitest::Test
176
184
  # wrapper to make api format more easy to query
177
185
  def queued(name, opts={})
178
186
  raise "No queued found" unless @queued
179
- source = opts[:source] || nil
187
+ tags_query = opts.fetch(:tags, nil)
180
188
 
181
- @queued[:gauges].each do |g|
182
- if g[:name] == name.to_s && g[:source] == source
183
- if g[:count]
189
+ @queued[:measurements].each do |measurement|
190
+ if measurement[:name] == name.to_s && measurement[:tags] == tags_query || measurement[:name] == name.to_s && @queued[:tags] == tags_query
191
+ if measurement[:count]
184
192
  # complex metric, return the whole hash
185
- return g
193
+ return measurement
186
194
  else
187
195
  # return just the value
188
- return g[:value]
196
+ return measurement[:value]
189
197
  end
190
198
  end
191
199
  end
192
200
  raise "No queued entry with '#{name}' found."
193
201
  end
194
202
 
195
- def source
196
- @tracker.qualified_source
203
+ def tags
204
+ @tracker.send(:tags)
197
205
  end
198
206
 
199
207
  def delete_all_metrics
200
- metric_names = client.list.map { |metric| metric['name'] }
201
- client.delete(*metric_names) if !metric_names.empty?
208
+ metric_names = client.metrics.map { |metric| metric['name'] }
209
+ client.delete_metrics(*metric_names) if !metric_names.empty?
202
210
  end
203
211
 
204
212
  else
@@ -7,7 +7,7 @@ module EnvironmentHelpers
7
7
  ENV.delete('LIBRATO_USER')
8
8
  ENV.delete('LIBRATO_TOKEN')
9
9
  ENV.delete('LIBRATO_PROXY')
10
- ENV.delete('LIBRATO_SOURCE')
10
+ ENV.delete("LIBRATO_TAGS")
11
11
  ENV.delete('LIBRATO_PREFIX')
12
12
  ENV.delete('LIBRATO_SUITES')
13
13
  ENV.delete('LIBRATO_LOG_LEVEL')
data/test/test_helper.rb CHANGED
@@ -6,4 +6,4 @@ require 'minitest/autorun'
6
6
 
7
7
  require 'librato/rack'
8
8
 
9
- require_relative 'support/environment_helpers'
9
+ require_relative 'support/environment_helpers'