ezmetrics 1.2.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.gitignore +3 -0
  4. data/.rspec +2 -0
  5. data/CHANGELOG.md +13 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +41 -0
  8. data/LICENSE +21 -674
  9. data/README.md +120 -84
  10. data/_config.yml +1 -0
  11. data/ezmetrics.gemspec +21 -0
  12. data/lib/ezmetrics.rb +7 -200
  13. data/lib/ezmetrics/benchmark.rb +37 -28
  14. data/lib/ezmetrics/dashboard/app/assets/config/dashboard_manifest.js +2 -0
  15. data/lib/ezmetrics/dashboard/app/assets/images/dashboard/.keep +0 -0
  16. data/lib/ezmetrics/dashboard/app/assets/javascripts/dashboard/application.js +15 -0
  17. data/lib/ezmetrics/dashboard/app/assets/javascripts/dashboard/main.js +1 -0
  18. data/lib/ezmetrics/dashboard/app/assets/stylesheets/dashboard/application.css +16 -0
  19. data/lib/ezmetrics/dashboard/app/assets/stylesheets/dashboard/main.css +6 -0
  20. data/lib/ezmetrics/dashboard/app/controllers/dashboard/application_controller.rb +5 -0
  21. data/lib/ezmetrics/dashboard/app/controllers/dashboard/metrics_controller.rb +39 -0
  22. data/lib/ezmetrics/dashboard/app/views/dashboard/metrics/index.html.erb +3 -0
  23. data/lib/ezmetrics/dashboard/app/views/layouts/dashboard/application.html.erb +12 -0
  24. data/lib/ezmetrics/dashboard/bin/rails +14 -0
  25. data/lib/ezmetrics/dashboard/config/routes.rb +5 -0
  26. data/lib/ezmetrics/dashboard/lib/dashboard.rb +4 -0
  27. data/lib/ezmetrics/dashboard/lib/dashboard/ezmetrics.rb +6 -0
  28. data/lib/ezmetrics/dashboard/lib/dashboard/version.rb +3 -0
  29. data/lib/ezmetrics/dashboard/react-dashboard/.gitignore +23 -0
  30. data/lib/ezmetrics/dashboard/react-dashboard/.rescriptsrc.js +9 -0
  31. data/lib/ezmetrics/dashboard/react-dashboard/README.md +0 -0
  32. data/lib/ezmetrics/dashboard/react-dashboard/package-lock.json +15472 -0
  33. data/lib/ezmetrics/dashboard/react-dashboard/package.json +49 -0
  34. data/lib/ezmetrics/dashboard/react-dashboard/public/index.html +18 -0
  35. data/lib/ezmetrics/dashboard/react-dashboard/public/manifest.json +10 -0
  36. data/lib/ezmetrics/dashboard/react-dashboard/public/robots.txt +2 -0
  37. data/lib/ezmetrics/dashboard/react-dashboard/src/App.tsx +216 -0
  38. data/lib/ezmetrics/dashboard/react-dashboard/src/Constants.tsx +74 -0
  39. data/lib/ezmetrics/dashboard/react-dashboard/src/Graph.tsx +71 -0
  40. data/lib/ezmetrics/dashboard/react-dashboard/src/Metric.tsx +21 -0
  41. data/lib/ezmetrics/dashboard/react-dashboard/src/MetricsBlock.tsx +22 -0
  42. data/lib/ezmetrics/dashboard/react-dashboard/src/Nav.tsx +105 -0
  43. data/lib/ezmetrics/dashboard/react-dashboard/src/RequestsBlock.tsx +78 -0
  44. data/lib/ezmetrics/dashboard/react-dashboard/src/index.css +79 -0
  45. data/lib/ezmetrics/dashboard/react-dashboard/src/index.tsx +9 -0
  46. data/lib/ezmetrics/dashboard/react-dashboard/src/react-app-env.d.ts +1 -0
  47. data/lib/ezmetrics/dashboard/react-dashboard/src/setupTests.ts +5 -0
  48. data/lib/ezmetrics/dashboard/react-dashboard/tsconfig.json +25 -0
  49. data/lib/ezmetrics/dashboard/react-dashboard/yarn.lock +11651 -0
  50. data/lib/ezmetrics/storage.rb +289 -0
  51. data/lib/ezmetrics/version.rb +3 -0
  52. data/scripts/compile_assets +20 -0
  53. metadata +50 -3
data/README.md CHANGED
@@ -10,70 +10,29 @@ Simple, lightweight and fast metrics aggregation for Rails.
10
10
  gem 'ezmetrics'
11
11
  ```
12
12
 
13
- ## Usage
14
-
15
- ### Getting started
16
-
17
- This tool captures and aggregates Rails application metrics such as
18
-
19
- - `duration`
20
- - `views`
21
- - `db`
22
- - `queries`
23
- - `status`
24
-
25
- and stores them for the timeframe you specified, 60 seconds by default.
26
-
27
- You can change the timeframe according to your needs and save the metrics by calling `log` method:
28
-
29
- ```ruby
30
- # Store the metrics for 60 seconds (default behaviour)
31
- EZmetrics.new.log(
32
- duration: 100.5,
33
- views: 40.7,
34
- db: 59.8,
35
- queries: 4,
36
- status: 200
37
- )
38
- ```
13
+ ## Available metrics
39
14
 
40
- ```ruby
41
- # Store the metrics for 10 minutes
42
- EZmetrics.new(10.minutes).log(
43
- duration: 100.5,
44
- views: 40.7,
45
- db: 59.8,
46
- queries: 4,
47
- status: 200
48
- )
49
- ```
50
-
51
- ---
52
-
53
- For displaying metrics you need to call `show` method:
54
-
55
- ```ruby
56
- # Aggregate and show metrics for last 60 seconds (default behaviour)
57
- EZmetrics.new.show
58
- ```
15
+ | Type | Aggregate functions |
16
+ | :--------: | :-------------------------------: |
17
+ | `duration` | `avg`, `max`, `percentile` |
18
+ | `views` | `avg`, `max`, `percentile` |
19
+ | `db` | `avg`, `max`, `percentile` |
20
+ | `queries` | `avg`, `max`, `percentile` |
21
+ | `requests` | `all`, `2xx`, `3xx`, `4xx`, `5xx` |
59
22
 
60
- ```ruby
61
- # Aggregate and show metrics for last 10 minutes
62
- EZmetrics.new(10.minutes).show
63
- ```
23
+ ## Usage
64
24
 
65
- You can combine these timeframes, for example - store for 10 minutes, display for 5 minutes.
66
25
 
67
26
  ### Capture metrics
68
27
 
69
- Just add an initializer to your application:
28
+ Add an initializer to your application:
70
29
 
71
30
  ```ruby
72
31
  # config/initializers/ezmetrics.rb
73
32
 
74
33
  ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
75
34
  event = ActiveSupport::Notifications::Event.new(*args)
76
- unless event.payload[:name] == "SCHEMA"
35
+ unless event.payload[:name] == "SCHEMA" || event.payload[:sql] =~ /\ABEGIN|COMMIT|ROLLBACK\z/
77
36
  Thread.current[:queries] ||= 0
78
37
  Thread.current[:queries] += 1
79
38
  end
@@ -81,22 +40,35 @@ end
81
40
 
82
41
  ActiveSupport::Notifications.subscribe("process_action.action_controller") do |*args|
83
42
  event = ActiveSupport::Notifications::Event.new(*args)
84
- EZmetrics.new.log(
43
+ Ezmetrics::Storage.new(24.hours).log(
85
44
  duration: event.duration.to_f,
86
45
  views: event.payload[:view_runtime].to_f,
87
46
  db: event.payload[:db_runtime].to_f,
88
47
  status: event.payload[:status].to_i || 500,
89
48
  queries: Thread.current[:queries].to_i,
90
49
  )
50
+ Thread.current[:queries] = 0
91
51
  end
92
52
  ```
93
53
 
94
54
  ### Display metrics
95
55
 
56
+ #### 1. Dashboard
57
+
58
+ ```ruby
59
+ # add the following line to 'config/routes.rb'
60
+
61
+ mount Dashboard::Ezmetrics, at: "/dashboard", as: "dashboard"
62
+ ```
63
+
64
+ ![Dashboard](https://user-images.githubusercontent.com/1847948/73551868-e26b2800-444f-11ea-83b9-fc81c8d05c07.png)
65
+
66
+ #### 2. Directly
67
+
96
68
  As simple as:
97
69
 
98
70
  ```ruby
99
- EZmetrics.new.show
71
+ Ezmetrics::Storage.new.show
100
72
  ```
101
73
 
102
74
  This will return a hash with the following structure:
@@ -136,7 +108,7 @@ This will return a hash with the following structure:
136
108
  If you prefer a single level object - you can change the default output structure by calling `.flatten` before `.show`
137
109
 
138
110
  ```ruby
139
- EZmetrics.new(1.hour).flatten.show(db: :avg, duration: [:avg, :max])
111
+ Ezmetrics::Storage.new(1.hour).flatten.show(db: :avg, duration: [:avg, :max])
140
112
  ```
141
113
 
142
114
  ```ruby
@@ -152,7 +124,7 @@ EZmetrics.new(1.hour).flatten.show(db: :avg, duration: [:avg, :max])
152
124
  Same for [partitioned aggregation](#partitioning)
153
125
 
154
126
  ```ruby
155
- EZmetrics.new(1.hour).partition_by(:minute).flatten.show(db: :avg, duration: [:avg, :max])
127
+ Ezmetrics::Storage.new(1.hour).partition_by(:minute).flatten.show(db: :avg, duration: [:avg, :max])
156
128
  ```
157
129
 
158
130
  ```ruby
@@ -179,7 +151,7 @@ The aggregation can be easily configured by specifying aggregation options as in
179
151
  **1. Single**
180
152
 
181
153
  ```ruby
182
- EZmetrics.new.show(duration: :max)
154
+ Ezmetrics::Storage.new.show(duration: :max)
183
155
  ```
184
156
 
185
157
  ```ruby
@@ -195,7 +167,7 @@ EZmetrics.new.show(duration: :max)
195
167
  **2. Multiple**
196
168
 
197
169
  ```ruby
198
- EZmetrics.new.show(queries: [:max, :avg])
170
+ Ezmetrics::Storage.new.show(queries: [:max, :avg])
199
171
  ```
200
172
 
201
173
  ```ruby
@@ -212,7 +184,7 @@ EZmetrics.new.show(queries: [:max, :avg])
212
184
  **3. Requests**
213
185
 
214
186
  ```ruby
215
- EZmetrics.new.show(requests: true)
187
+ Ezmetrics::Storage.new.show(requests: true)
216
188
  ```
217
189
 
218
190
  ```ruby
@@ -234,7 +206,7 @@ EZmetrics.new.show(requests: true)
234
206
  **4. Combined**
235
207
 
236
208
  ```ruby
237
- EZmetrics.new.show(views: :avg, :db: [:avg, :max], requests: true)
209
+ Ezmetrics::Storage.new.show(views: :avg, :db: [:avg, :max], requests: true)
238
210
  ```
239
211
 
240
212
  ```ruby
@@ -258,6 +230,70 @@ EZmetrics.new.show(views: :avg, :db: [:avg, :max], requests: true)
258
230
  }
259
231
  ```
260
232
 
233
+ ---
234
+
235
+ **5. Percentile**
236
+
237
+ This feature is available since version `2.0.0`.
238
+
239
+ By default percentile aggregation is turned off because it requires to store each value of all metrics.
240
+
241
+ To enable this feature - you need to set `store_each_value: true` when saving the metrics:
242
+
243
+ ```ruby
244
+ Ezmetrics::Storage.new.log(
245
+ duration: 100.5,
246
+ views: 40.7,
247
+ db: 59.8,
248
+ queries: 4,
249
+ status: 200,
250
+ store_each_value: true
251
+ )
252
+ ```
253
+
254
+ The aggregation syntax has the following format `metrics_type: :percentile_{number}` where `number` is any integer in the 1..99 range.
255
+
256
+ ```ruby
257
+ Ezmetrics::Storage.new.show(db: [:avg, :percentile_90, :percentile_95], duration: :percentile_99)
258
+ ```
259
+
260
+ ```ruby
261
+ {
262
+ db: {
263
+ avg: 155,
264
+ percentile_90: 205,
265
+ percentile_95: 215
266
+ },
267
+ duration: {
268
+ percentile_99: 236
269
+ }
270
+ }
271
+ ```
272
+
273
+ **6. Percentile distribution**
274
+
275
+ If you want to visualize percentile distribution (from 1% to 99%):
276
+
277
+ ```ruby
278
+ Ezmetrics::Storage.new.show(duration: :percentile_distribution)
279
+ ```
280
+
281
+ ```ruby
282
+ {
283
+ duration: {
284
+ percentile_distribution: {
285
+ 1: 12,
286
+ 2: 15,
287
+ 3: 19,
288
+ #...
289
+ 97: 6540,
290
+ 98: 6682,
291
+ 99: 6730
292
+ }
293
+ }
294
+ }
295
+ ```
296
+
261
297
  ### Partitioning
262
298
 
263
299
  If you want to visualize your metrics by using a **line chart**, you will need to use partitioning.
@@ -266,7 +302,7 @@ To aggregate metrics, partitioned by a unit of time you need to call `.partition
266
302
 
267
303
  ```ruby
268
304
  # Aggregate metrics for last hour, partition by minute
269
- EZmetrics.new(1.hour).partition_by(:minute).show(duration: [:avg, :max], db: :avg)
305
+ Ezmetrics::Storage.new(1.hour).partition_by(:minute).show(duration: [:avg, :max], db: :avg)
270
306
  ```
271
307
 
272
308
  This will return an array of objects with the following structure:
@@ -313,38 +349,38 @@ like in the example below:
313
349
 
314
350
  Available time units for partitioning: `second`, `minute`, `hour`, `day`. Default: `minute`.
315
351
 
316
- ### Performance
352
+ ## Performance
317
353
 
318
354
  The aggregation speed relies on the performance of **Redis** (data storage) and **Oj** (json serialization/parsing).
319
355
 
320
- You can check the **aggregation** time by running:
356
+ You can check the **aggregation** time (in seconds) by running:
321
357
 
322
358
  ```ruby
323
- EZmetrics::Benchmark.new.measure_aggregation
324
- ```
359
+ # 1. Simple
360
+ Ezmetrics::Benchmark.new.measure_aggregation
325
361
 
326
- | Interval | Duration (seconds) |
327
- | :------: | :----------------: |
328
- | 1 minute | 0.0 |
329
- | 1 hour | 0.04 |
330
- | 12 hours | 0.49 |
331
- | 24 hours | 1.51 |
332
- | 48 hours | 3.48 |
333
-
334
- ---
362
+ # 2. Partitioned
363
+ Ezmetrics::Benchmark.new.measure_aggregation(:minute)
335
364
 
336
- To check the **partitioned aggregation** time you need to run:
365
+ # 3. Percentile
366
+ Ezmetrics::Benchmark.new(true).measure_aggregation
337
367
 
338
- ```ruby
339
- EZmetrics::Benchmark.new.measure_aggregation(:minute)
368
+ # 4. Percentile (partitioned)
369
+ Ezmetrics::Benchmark.new(true).measure_aggregation(:minute)
340
370
  ```
341
371
 
342
- | Interval | Duration (seconds) |
343
- | :------: | :----------------: |
344
- | 1 minute | 0.0 |
345
- | 1 hour | 0.04 |
346
- | 12 hours | 0.53 |
347
- | 24 hours | 1.59 |
348
- | 48 hours | 3.51 |
372
+ | Interval | Simple aggregation | Partitioned | Percentile | Percentile (partitioned) |
373
+ | :------: | :----------------: | :---------: | :--------: | :----------------------: |
374
+ | 1 minute | 0.0 | 0.0 | 0.0 | 0.0 |
375
+ | 1 hour | 0.02 | 0.02 | 0.14 | 0.16 |
376
+ | 12 hours | 0.22 | 0.25 | 2.11 | 1.97 |
377
+ | 24 hours | 0.61 | 0.78 | 5.85 | 5.85 |
378
+ | 48 hours | 1.42 | 1.75 | 14.1 | 13.9 |
349
379
 
350
380
  The benchmarks above were run on a _2017 Macbook Pro 2.9 GHz Intel Core i7 with 16 GB of RAM_
381
+
382
+ ## [Changelog](CHANGELOG.md)
383
+
384
+ ## License
385
+
386
+ ezmetrics is released under the [MIT License](https://opensource.org/licenses/MIT).
data/_config.yml ADDED
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-tactile
data/ezmetrics.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ require_relative "lib/ezmetrics/version"
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "ezmetrics"
5
+ gem.version = Ezmetrics::VERSION
6
+ gem.date = "2020-02-01"
7
+ gem.summary = "Rails metrics aggregation tool."
8
+ gem.description = "Simple, lightweight and fast metrics aggregation for Rails."
9
+ gem.authors = ["Nicolae Rotaru"]
10
+ gem.email = "nyku.rn@gmail.com"
11
+ gem.homepage = "https://github.com/nyku/ezmetrics"
12
+ gem.license = "MIT"
13
+ gem.files = `git ls-files | grep -Ev '^(spec)'`.split("\n")
14
+ gem.require_paths = ["lib"]
15
+ gem.required_ruby_version = ">= 2.4.0"
16
+ gem.add_dependency "redis", ["~> 4.0"]
17
+ gem.add_dependency "hiredis", ["~> 0.6.3"]
18
+ gem.add_dependency "oj", ["~> 3.10"]
19
+
20
+ gem.add_development_dependency "rspec", "~> 3.5"
21
+ end
data/lib/ezmetrics.rb CHANGED
@@ -2,205 +2,12 @@ require "redis"
2
2
  require "redis/connection/hiredis"
3
3
  require "oj"
4
4
 
5
- class EZmetrics
6
- METRICS = [:duration, :views, :db, :queries].freeze
7
- AGGREGATION_FUNCTIONS = [:max, :avg].freeze
8
- PARTITION_UNITS = [:second, :minute, :hour, :day].freeze
5
+ module Ezmetrics
6
+ require_relative "ezmetrics/version"
7
+ require_relative "ezmetrics/storage"
8
+ require_relative "ezmetrics/benchmark"
9
9
 
10
- def initialize(interval_seconds=60)
11
- @interval_seconds = interval_seconds.to_i
12
- @redis = Redis.new
10
+ if defined?(Rails)
11
+ require_relative "ezmetrics/dashboard/lib/dashboard"
13
12
  end
14
-
15
- def log(payload={duration: 0.0, views: 0.0, db: 0.0, queries: 0, status: 200})
16
- @safe_payload = {
17
- duration: payload[:duration].to_f,
18
- views: payload[:views].to_f,
19
- db: payload[:db].to_f,
20
- queries: payload[:queries].to_i,
21
- status: payload[:status].to_i
22
- }
23
-
24
- this_second = Time.now.to_i
25
- status_group = "#{payload[:status].to_s[0]}xx"
26
- @this_second_metrics = redis.get(this_second)
27
-
28
- if this_second_metrics
29
- @this_second_metrics = Oj.load(this_second_metrics)
30
-
31
- METRICS.each do |metrics_type|
32
- update_sum(metrics_type)
33
- update_max(metrics_type)
34
- end
35
-
36
- this_second_metrics["statuses"]["all"] += 1
37
- this_second_metrics["statuses"][status_group] += 1
38
- else
39
- @this_second_metrics = {
40
- "second" => this_second,
41
- "duration_sum" => safe_payload[:duration],
42
- "duration_max" => safe_payload[:duration],
43
- "views_sum" => safe_payload[:views],
44
- "views_max" => safe_payload[:views],
45
- "db_sum" => safe_payload[:db],
46
- "db_max" => safe_payload[:db],
47
- "queries_sum" => safe_payload[:queries],
48
- "queries_max" => safe_payload[:queries],
49
- "statuses" => { "2xx" => 0, "3xx" => 0, "4xx" => 0, "5xx" => 0, "all" => 1 }
50
- }
51
-
52
- this_second_metrics["statuses"][status_group] = 1
53
- end
54
-
55
- redis.setex(this_second, interval_seconds, Oj.dump(this_second_metrics))
56
- true
57
- rescue => error
58
- formatted_error(error)
59
- end
60
-
61
- def show(options=nil)
62
- @options = options || default_options
63
- partitioned_metrics ? aggregate_partitioned_data : aggregate_data
64
- end
65
-
66
- def flatten
67
- @flat = true
68
- self
69
- end
70
-
71
- def partition_by(time_unit=:minute)
72
- time_unit = PARTITION_UNITS.include?(time_unit) ? time_unit : :minute
73
- @partitioned_metrics = interval_metrics.group_by { |h| second_to_partition_unit(time_unit, h["second"]) }
74
- self
75
- end
76
-
77
- private
78
-
79
- attr_reader :redis, :interval_seconds, :interval_metrics, :requests, :flat,
80
- :storage_key, :safe_payload, :this_second_metrics, :partitioned_metrics, :options
81
-
82
- def aggregate_data
83
- return {} unless interval_metrics.any?
84
- @requests = interval_metrics.sum { |hash| hash["statuses"]["all"] }
85
- build_result
86
- rescue
87
- {}
88
- end
89
-
90
- def aggregate_partitioned_data
91
- partitioned_metrics.map do |partition, metrics|
92
- @interval_metrics = metrics
93
- @requests = interval_metrics.sum { |hash| hash["statuses"]["all"] }
94
- flat ? { timestamp: partition, **build_result } : { timestamp: partition, data: build_result }
95
- end
96
- rescue
97
- new(options)
98
- end
99
-
100
- def build_result
101
- result = {}
102
-
103
- if options[:requests]
104
- append_requests_to_result(result, { all: requests, grouped: count_all_status_groups })
105
- end
106
-
107
- options.each do |metrics, aggregation_functions|
108
- next unless METRICS.include?(metrics)
109
- aggregation_functions = [aggregation_functions] unless aggregation_functions.is_a?(Array)
110
- next unless aggregation_functions.any?
111
-
112
- aggregation_functions.each do |aggregation_function|
113
- aggregated_metrics = aggregate(metrics, aggregation_function)
114
- append_metrics_to_result(result, metrics, aggregation_function, aggregated_metrics)
115
- end
116
- end
117
- result
118
- ensure
119
- result
120
- end
121
-
122
- def append_requests_to_result(result, aggregated_requests)
123
- return result[:requests] = aggregated_requests unless flat
124
-
125
- result[:requests_all] = aggregated_requests[:all]
126
- aggregated_requests[:grouped].each do |group, counter|
127
- result[:"requests_#{group}"] = counter
128
- end
129
- end
130
-
131
- def append_metrics_to_result(result, metrics, aggregation_function, aggregated_metrics)
132
- return result[:"#{metrics}_#{aggregation_function}"] = aggregated_metrics if flat
133
-
134
- result[metrics] ||= {}
135
- result[metrics][aggregation_function] = aggregated_metrics
136
- end
137
-
138
- def second_to_partition_unit(time_unit, second)
139
- return second if time_unit == :second
140
- time = Time.at(second)
141
- return (time - time.sec - time.min * 60 - time.hour * 3600).to_i if time_unit == :day
142
- return (time - time.sec - time.min * 60).to_i if time_unit == :hour
143
- (time - time.sec).to_i
144
- end
145
-
146
- def interval_metrics
147
- @interval_metrics ||= begin
148
- interval_start = Time.now.to_i - interval_seconds
149
- interval_keys = (interval_start..Time.now.to_i).to_a
150
- redis.mget(interval_keys).compact.map { |hash| Oj.load(hash) }
151
- end
152
- end
153
-
154
- def aggregate(metrics, aggregation_function)
155
- return unless AGGREGATION_FUNCTIONS.include?(aggregation_function)
156
- return avg("#{metrics}_sum") if aggregation_function == :avg
157
- return max("#{metrics}_max") if aggregation_function == :max
158
- end
159
-
160
- def update_sum(metrics)
161
- this_second_metrics["#{metrics}_sum"] += safe_payload[metrics]
162
- end
163
-
164
- def update_max(metrics)
165
- max_value = [safe_payload[metrics], this_second_metrics["#{metrics}_max"]].max
166
- this_second_metrics["#{metrics}_max"] = max_value
167
- end
168
-
169
- def avg(metrics)
170
- (interval_metrics.sum { |h| h[metrics] }.to_f / requests).round
171
- end
172
-
173
- def max(metrics)
174
- interval_metrics.max { |h| h[metrics] }[metrics].round
175
- end
176
-
177
- def count_all_status_groups
178
- interval_metrics.inject({ "2xx" => 0, "3xx" => 0, "4xx" => 0, "5xx" => 0 }) do |result, h|
179
- result["2xx"] += h["statuses"]["2xx"]
180
- result["3xx"] += h["statuses"]["3xx"]
181
- result["4xx"] += h["statuses"]["4xx"]
182
- result["5xx"] += h["statuses"]["5xx"]
183
- result
184
- end
185
- end
186
-
187
- def default_options
188
- {
189
- duration: AGGREGATION_FUNCTIONS,
190
- views: AGGREGATION_FUNCTIONS,
191
- db: AGGREGATION_FUNCTIONS,
192
- queries: AGGREGATION_FUNCTIONS,
193
- requests: true
194
- }
195
- end
196
-
197
- def formatted_error(error)
198
- {
199
- error: error.class.name,
200
- message: error.message,
201
- backtrace: error.backtrace.reject { |line| line.match(/ruby|gems/) }
202
- }
203
- end
204
- end
205
-
206
- require "ezmetrics/benchmark"
13
+ end