librato-rack 1.1.1 → 2.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.
@@ -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'