checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
---
2
2
SHA256:
3
- metadata.gz: 5ba2e24bca76b2786c1264b779e72764e123094150855cae241d673505df95ad
4
- data.tar.gz: 3c297b92a53c51b8b881fbbafb15929b9bac36eb53164c3faab37c2caa72db02
3
+ metadata.gz: 518d9350ed026801311bdc695857fdd057856f6b7fe40715bf8072c990e8e5b8
4
+ data.tar.gz: 7d36fbd3e63994789ce8ac04212fb44c30041fd33f7173fbfdf1a6257beea99a
5
5
SHA512:
6
- metadata.gz: 4d1e8118d48cac15dca166c6c4f0d8e38344b28bfcc85343fa87ff4877d34bc7f12b9841241de563723261df5a48210cf1838c09eece3bc15d5f2dde6a58c8c2
7
- data.tar.gz: 8e62b7b53f73a6343c8fd6f11e0e8a9f856314dd262c10611cd9bf061636c8801255de58818a1736069679525bed73c949e6f61778910de8a306da30c352e2a2
6
+ metadata.gz: 42e990916d474ed52f08330bd7210b4c6f464a0199354cfc1fe3710817b9d57790d445d0d1f88c8fccd6daeb627638a80dd8b578c685544f6a4f9c7765522a5f
7
+ data.tar.gz: 5b49eec021acaef39af2c9401681fa85f02d368f36231a60a64faf595e5b0c1432ce07a67fb86ce9c8b3041835fd4480da86ea5d91f7ca0939ef5b40592e6a49
data/README.md CHANGED
@@ -31,22 +31,20 @@ You can change the timeframe according to your needs and save the metrics by cal
31
31
EZmetrics.new.log(duration: 100.5, views: 40.7, db: 59.8, queries: 4, status: 200)
32
32
```
33
33
34
- or
35
-
36
34
```ruby
37
35
# Store the metrics for 10 minutes
38
36
EZmetrics.new(10.minutes).log(duration: 100.5, views: 40.7, db: 59.8, queries: 4, status: 200)
39
37
```
40
38
41
- For displaying metrics you need call `show` method:
39
+ ---
40
+
41
+ For displaying metrics you need to call `show` method:
42
42
43
43
```ruby
44
44
# Aggregate and show metrics for last 60 seconds (default behaviour)
45
45
EZmetrics.new.show
46
46
```
47
47
48
- or
49
-
50
48
```ruby
51
49
# Aggregate and show metrics for last 10 minutes
52
50
EZmetrics.new(10.minutes).show
@@ -121,11 +119,11 @@ This will return a hash with the following structure:
121
119
}
122
120
```
123
121
124
- ### Output configuration
122
+ ### Aggregation options
125
123
126
- The output can be easily configured by specifying aggregation options as in the following examples:
124
+ The aggregation can be easily configured by specifying aggregation options as in the following examples:
127
125
128
- 1. Single
126
+ **1. Single**
129
127
130
128
```ruby
131
129
EZmetrics.new.show(duration: :max)
@@ -139,7 +137,9 @@ EZmetrics.new.show(duration: :max)
139
137
}
140
138
```
141
139
142
- 2. Multiple
140
+ ---
141
+
142
+ **2. Multiple**
143
143
144
144
```ruby
145
145
EZmetrics.new.show(queries: [:max, :avg])
@@ -154,7 +154,9 @@ EZmetrics.new.show(queries: [:max, :avg])
154
154
}
155
155
```
156
156
157
- 3. Requests
157
+ ---
158
+
159
+ **3. Requests**
158
160
159
161
```ruby
160
162
EZmetrics.new.show(requests: true)
@@ -174,7 +176,9 @@ EZmetrics.new.show(requests: true)
174
176
}
175
177
```
176
178
177
- 4. Combined
179
+ ---
180
+
181
+ **4. Combined**
178
182
179
183
```ruby
180
184
EZmetrics.new.show(views: :avg, :db: [:avg, :max], requests: true)
@@ -203,13 +207,7 @@ EZmetrics.new.show(views: :avg, :db: [:avg, :max], requests: true)
203
207
204
208
### Performance
205
209
206
- The implementation is based on **Redis** commands such as:
210
+ The aggregation speed relies on the performance of **Redis** (data storage) and **Oj** (json serialization/parsing).
207
-
208
- - [`get`](https://redis.io/commands/get)
209
- - [`mget`](https://redis.io/commands/mget)
210
- - [`setex`](https://redis.io/commands/setex)
211
-
212
- which are extremely fast.
213
211
214
212
You can check the **aggregation** time by running:
215
213
@@ -222,7 +220,7 @@ The result of running this benchmark on a _2017 Macbook Pro 2.9 GHz Intel Core i
222
220
| Interval | Duration (seconds) |
223
221
| :------: | :----------------: |
224
222
| 1 minute | 0.0 |
225
- | 1 hour | 0.05 |
226
- | 12 hours | 0.66 |
227
- | 24 hours | 1.83 |
228
- | 48 hours | 4.06 |
223
+ | 1 hour | 0.04 |
224
+ | 12 hours | 0.49 |
225
+ | 24 hours | 1.51 |
226
+ | 48 hours | 3.48 |
data/lib/ezmetrics.rb CHANGED
@@ -9,7 +9,6 @@ class EZmetrics
9
9
def initialize(interval_seconds=60)
10
10
@interval_seconds = interval_seconds.to_i
11
11
@redis = Redis.new
12
- @storage_key = "ez-metrics"
13
12
end
14
13
15
14
def log(payload={duration: 0.0, views: 0.0, db: 0.0, queries: 0, status: 200})
@@ -23,7 +22,7 @@ class EZmetrics
23
22
24
23
this_second = Time.now.to_i
25
24
status_group = "#{payload[:status].to_s[0]}xx"
26
- @this_second_metrics = redis.get("#{storage_key}:#{this_second}")
25
+ @this_second_metrics = redis.get(this_second)
27
26
28
27
if this_second_metrics
29
28
@this_second_metrics = Oj.load(this_second_metrics)
@@ -51,7 +50,7 @@ class EZmetrics
51
50
this_second_metrics["statuses"][status_group] = 1
52
51
end
53
52
54
- redis.setex("#{storage_key}:#{this_second}", interval_seconds, Oj.dump(this_second_metrics))
53
+ redis.setex(this_second, interval_seconds, Oj.dump(this_second_metrics))
55
54
true
56
55
rescue => error
57
56
formatted_error(error)
@@ -60,12 +59,12 @@ class EZmetrics
60
59
def show(options=nil)
61
60
@options = options || default_options
62
61
interval_start = Time.now.to_i - interval_seconds
63
- interval_keys = (interval_start..Time.now.to_i).to_a.map { |second| "#{storage_key}:#{second}" }
62
+ interval_keys = (interval_start..Time.now.to_i).to_a
64
63
@interval_metrics = redis.mget(interval_keys).compact.map { |hash| Oj.load(hash) }
65
64
66
65
return {} unless interval_metrics.any?
67
66
68
- @requests = interval_metrics.map { |hash| hash["statuses"]["all"] }.compact.sum
67
+ @requests = interval_metrics.sum { |hash| hash["statuses"]["all"] }
69
68
build_result
70
69
rescue
71
70
{}
@@ -79,17 +78,7 @@ class EZmetrics
79
78
def build_result
80
79
result = {}
81
80
82
- if options[:requests]
81
+ result[:requests] = { all: requests, grouped: count_all_status_groups } if options[:requests]
83
- result[:requests] = {
84
- all: requests,
85
- grouped: {
86
- "2xx" => count("2xx"),
87
- "3xx" => count("3xx"),
88
- "4xx" => count("4xx"),
89
- "5xx" => count("5xx")
90
- }
91
- }
92
- end
93
82
94
83
options.each do |metrics, aggregation_functions|
95
84
next unless METRICS.include?(metrics)
@@ -108,29 +97,35 @@ class EZmetrics
108
97
109
98
def aggregate(metrics, aggregation_function)
110
99
return unless AGGREGATION_FUNCTIONS.include?(aggregation_function)
111
- return avg("#{metrics}_sum".to_sym) if aggregation_function == :avg
112
- return max("#{metrics}_max".to_sym) if aggregation_function == :max
100
+ return avg("#{metrics}_sum") if aggregation_function == :avg
101
+ return max("#{metrics}_max") if aggregation_function == :max
113
102
end
114
103
115
104
def update_sum(metrics)
116
- this_second_metrics["#{metrics}_sum"] += safe_payload[metrics.to_sym]
105
+ this_second_metrics["#{metrics}_sum"] += safe_payload[metrics]
117
106
end
118
107
119
108
def update_max(metrics)
120
- max_value = [safe_payload[metrics.to_sym], this_second_metrics["#{metrics}_max"]].max
109
+ max_value = [safe_payload[metrics], this_second_metrics["#{metrics}_max"]].max
121
110
this_second_metrics["#{metrics}_max"] = max_value
122
111
end
123
112
124
113
def avg(metrics)
125
- (interval_metrics.map { |h| h[metrics.to_s] }.sum.to_f / requests).round
114
+ (interval_metrics.sum { |h| h[metrics] }.to_f / requests).round
126
115
end
127
116
128
117
def max(metrics)
129
- interval_metrics.map { |h| h[metrics.to_s] }.max.round
118
+ interval_metrics.max { |h| h[metrics] }[metrics].round
130
119
end
131
120
132
- def count(group)
133
- interval_metrics.map { |h| h["statuses"][group.to_s] }.sum
121
+ def count_all_status_groups
122
+ interval_metrics.inject({ "2xx" => 0, "3xx" => 0, "4xx" => 0, "5xx" => 0 }) do |result, h|
123
+ result["2xx"] += h["statuses"]["2xx"]
124
+ result["3xx"] += h["statuses"]["3xx"]
125
+ result["4xx"] += h["statuses"]["4xx"]
126
+ result["5xx"] += h["statuses"]["5xx"]
127
+ result
128
+ end
134
129
end
135
130
136
131
def default_options
data/lib/ezmetrics/benchmark.rb CHANGED
@@ -52,14 +52,14 @@ class EZmetrics::Benchmark
52
52
"all" => rand(40)
53
53
}
54
54
}
55
- redis.setex("ez-metrics:#{second}", seconds, Oj.dump(payload))
55
+ redis.setex(second, seconds, Oj.dump(payload))
56
56
end
57
57
nil
58
58
end
59
59
60
60
def cleanup_metrics
61
61
interval_start = Time.now.to_i - intervals.values.max - 100
62
- interval_keys = (interval_start..Time.now.to_i).to_a.map { |second| "ez-metrics:#{second}" }
62
+ interval_keys = (interval_start..Time.now.to_i).to_a
63
63
redis.del(interval_keys)
64
64
end
65
65
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
--- !ruby/object:Gem::Specification
2
2
name: ezmetrics
3
3
version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
platform: ruby
6
6
authors:
7
7
- Nicolae Rotaru