fluent-plugin-stats-notifier 0.0.3 → 0.0.4
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/.travis.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/README.md +88 -10
- data/fluent-plugin-stats-notifier.gemspec +1 -1
- data/lib/fluent/plugin/out_stats_notifier.rb +121 -73
- data/spec/out_stats_notifier_spec.rb +148 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67d26005468f638f64088219bbd2b412a526025f
|
4
|
+
data.tar.gz: ad90655b0724642ba1aea652fc0ba7d31a7d139e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d4dce4153badaab3416e4d7a096065379aec55397b050bae2a73fb0c96c027411fcf060263fc3914e3ecde2acc05cc9b33bc39c674912ed308f173ba115c959
|
7
|
+
data.tar.gz: 960d59b06a22a0779c755d41e7c8e78e8ccef9641ce4f3de6963c8ec45ee3a541195ad4ee51c14e9007ce4dac21ac962246b593142f75a110db7a56a34fd11cd
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -4,15 +4,47 @@ Fluentd plugin to calculate statistics and then thresholding
|
|
4
4
|
|
5
5
|
## Configuration
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
### Example 1
|
8
|
+
|
9
|
+
Get statistics on messages
|
10
|
+
|
11
|
+
```
|
12
|
+
<match foo.**>
|
13
|
+
type stats_notifier
|
14
|
+
tag notifier
|
15
|
+
interval 5
|
16
|
+
target_key 4xx_count
|
17
|
+
greater_equal 4
|
18
|
+
stats max # default
|
19
|
+
store_file /path/to/store_file.dat
|
20
|
+
</match>
|
21
|
+
```
|
22
|
+
|
23
|
+
Assuming following inputs are coming:
|
24
|
+
|
25
|
+
foo.bar1: {"4xx_count":1,"foobar":2"}
|
26
|
+
foo.bar1: {"4xx_count":6,"foobar":2"}
|
27
|
+
|
28
|
+
then this plugin emits an message because the max of `4xx_count` is greater than or equal to the specified value `4`. Output will be as following:
|
29
|
+
|
30
|
+
notifier: {"4xx_count":6.0}
|
31
|
+
|
32
|
+
### Example 2
|
33
|
+
|
34
|
+
Get statistics among tags
|
35
|
+
|
36
|
+
```
|
37
|
+
<match foo.**>
|
38
|
+
type stats_notifier
|
39
|
+
tag notifier
|
40
|
+
interval 5
|
41
|
+
target_key 4xx_count
|
42
|
+
greater_equal 4
|
43
|
+
aggregate all # default
|
44
|
+
aggregate_stats max # default
|
45
|
+
store_file /path/to/store_file.dat
|
46
|
+
</match>
|
47
|
+
```
|
16
48
|
|
17
49
|
Assuming following inputs are coming:
|
18
50
|
|
@@ -23,6 +55,32 @@ then this plugin emits an message because the max of `4xx_count` is greater than
|
|
23
55
|
|
24
56
|
notifier: {"4xx_count":6.0}
|
25
57
|
|
58
|
+
### Combined Example
|
59
|
+
|
60
|
+
```
|
61
|
+
<match foo.**>
|
62
|
+
type stats_notifier
|
63
|
+
tag notifier
|
64
|
+
interval 5
|
65
|
+
target_key 4xx_count
|
66
|
+
greater_equal 4
|
67
|
+
stats max # default
|
68
|
+
aggregate all # default
|
69
|
+
aggregate_stats max # default
|
70
|
+
store_file /path/to/store_file.dat
|
71
|
+
</match>
|
72
|
+
```
|
73
|
+
|
74
|
+
Assuming following inputs are coming:
|
75
|
+
|
76
|
+
foo.bar1: {"4xx_count":1,"foobar":2"}
|
77
|
+
foo.bar1: {"4xx_count":8,"foobar":2"}
|
78
|
+
foo.bar2: {"4xx_count":6,"foobar":2"}
|
79
|
+
|
80
|
+
Output will be as following:
|
81
|
+
|
82
|
+
notifier: {"4xx_count":8.0}
|
83
|
+
|
26
84
|
## Parameters
|
27
85
|
|
28
86
|
- target\_key (required)
|
@@ -49,10 +107,18 @@ then this plugin emits an message because the max of `4xx_count` is greater than
|
|
49
107
|
|
50
108
|
A `greater than or eqaul` threshold value, that is, emit if `target_key` value >= specified value.
|
51
109
|
|
52
|
-
-
|
110
|
+
- stats
|
53
111
|
|
54
112
|
`max`, `avg`, `min`, `sum` can be specified. Default is `max`.
|
55
113
|
|
114
|
+
- aggregate\_stats
|
115
|
+
|
116
|
+
Work only with `aggregate all`. `max`, `avg`, `min`, `sum` can be specified. Default is `max`.
|
117
|
+
|
118
|
+
- compare\_with
|
119
|
+
|
120
|
+
Obsolete. Use `aggregate_stats`.
|
121
|
+
|
56
122
|
- tag
|
57
123
|
|
58
124
|
The output tag name. Required for `aggregate all`.
|
@@ -61,6 +127,18 @@ then this plugin emits an message because the max of `4xx_count` is greater than
|
|
61
127
|
|
62
128
|
Add tag prefix for output message. Required for `aggregate tag`.
|
63
129
|
|
130
|
+
- remove_tag_prefix
|
131
|
+
|
132
|
+
Remove tag prefix for output message.
|
133
|
+
|
134
|
+
- add_tag_suffix
|
135
|
+
|
136
|
+
Add tag suffix for output message.
|
137
|
+
|
138
|
+
- remove_tag_suffix
|
139
|
+
|
140
|
+
Remove tag suffix for output message.
|
141
|
+
|
64
142
|
- aggragate
|
65
143
|
|
66
144
|
Do calculation for each `tag` or `all`. The defaultis `all`.
|
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "fluent-plugin-stats-notifier"
|
6
|
-
s.version = "0.0.
|
6
|
+
s.version = "0.0.4"
|
7
7
|
s.authors = ["Naotoshi Seo"]
|
8
8
|
s.email = ["sonots@gmail.com"]
|
9
9
|
s.homepage = "https://github.com/sonots/fluent-plugin-stats-notifier"
|
@@ -2,6 +2,11 @@
|
|
2
2
|
class Fluent::StatsNotifierOutput < Fluent::Output
|
3
3
|
Fluent::Plugin.register_output('stats_notifier', self)
|
4
4
|
|
5
|
+
# To support log_level option implemented by Fluentd v0.10.43
|
6
|
+
unless method_defined?(:log)
|
7
|
+
define_method("log") { $log }
|
8
|
+
end
|
9
|
+
|
5
10
|
def initialize
|
6
11
|
super
|
7
12
|
require 'pathname'
|
@@ -13,15 +18,19 @@ class Fluent::StatsNotifierOutput < Fluent::Output
|
|
13
18
|
config_param :less_equal, :float, :default => nil
|
14
19
|
config_param :greater_than, :float, :default => nil
|
15
20
|
config_param :greater_equal, :float, :default => nil
|
16
|
-
config_param :
|
17
|
-
config_param :
|
21
|
+
config_param :stats, :string, :default => "max"
|
22
|
+
config_param :compare_with, :string, :default => nil # Obsolete. Use aggregate_stats
|
23
|
+
config_param :aggregate_stats, :string, :default => "max" # Work only with aggregate :all
|
24
|
+
config_param :tag, :string, :default => nil
|
18
25
|
config_param :add_tag_prefix, :string, :default => nil
|
19
26
|
config_param :remove_tag_prefix, :string, :default => nil
|
27
|
+
config_param :add_tag_suffix, :string, :default => nil
|
28
|
+
config_param :remove_tag_suffix, :string, :default => nil
|
20
29
|
config_param :aggregate, :string, :default => 'all'
|
21
30
|
config_param :store_file, :string, :default => nil
|
22
31
|
|
23
32
|
attr_accessor :counts
|
24
|
-
attr_accessor :
|
33
|
+
attr_accessor :queues
|
25
34
|
attr_accessor :saved_duration
|
26
35
|
attr_accessor :saved_at
|
27
36
|
attr_accessor :last_checked
|
@@ -32,51 +41,57 @@ class Fluent::StatsNotifierOutput < Fluent::Output
|
|
32
41
|
@interval = @interval.to_i
|
33
42
|
|
34
43
|
if @less_than and @less_equal
|
35
|
-
raise Fluent::ConfigError, "
|
44
|
+
raise Fluent::ConfigError, "out_stats_notifier: Only either of `less_than` or `less_equal` can be specified."
|
36
45
|
end
|
37
46
|
if @greater_than and @greater_equal
|
38
|
-
raise Fluent::ConfigError, "
|
47
|
+
raise Fluent::ConfigError, "out_stats_notifier: Only either of `greater_than` or `greater_equal` can be specified."
|
39
48
|
end
|
40
49
|
|
41
|
-
|
50
|
+
@aggregate_stats = @compare_with if @compare_with # Support old version compatibility
|
51
|
+
case @aggregate_stats
|
42
52
|
when "sum"
|
43
|
-
@
|
53
|
+
@aggregate_stats = :sum
|
44
54
|
when "max"
|
45
|
-
@
|
55
|
+
@aggregate_stats = :max
|
46
56
|
when "min"
|
47
|
-
@
|
57
|
+
@aggregate_stats = :min
|
48
58
|
when "avg"
|
49
|
-
@
|
59
|
+
@aggregate_stats = :avg
|
50
60
|
else
|
51
|
-
raise Fluent::ConfigError, "
|
61
|
+
raise Fluent::ConfigError, "out_stats_notifier: `aggregate_stats` must be one of `sum`, `max`, `min`, `avg`"
|
62
|
+
end
|
63
|
+
|
64
|
+
case @stats
|
65
|
+
when "sum"
|
66
|
+
@stats = :sum
|
67
|
+
when "max"
|
68
|
+
@stats = :max
|
69
|
+
when "min"
|
70
|
+
@stats = :min
|
71
|
+
when "avg"
|
72
|
+
@stats = :avg
|
73
|
+
else
|
74
|
+
raise Fluent::ConfigError, "out_stats_notifier: `stats` must be one of `sum`, `max`, `min`, `avg`"
|
75
|
+
end
|
76
|
+
|
77
|
+
if @tag.nil? and @add_tag_prefix.nil? and @remove_tag_prefix.nil? and @add_tag_suffix.nil? and @remove_tag_suffix.nil?
|
78
|
+
raise Fluent::ConfigError, "out_stats_notifier: No tag option is specified"
|
52
79
|
end
|
80
|
+
@tag_proc = tag_proc
|
53
81
|
|
54
82
|
case @aggregate
|
55
83
|
when 'all'
|
56
|
-
raise Fluent::ConfigError, "
|
84
|
+
raise Fluent::ConfigError, "out_stats_notifier: `tag` must be specified with aggregate all" if @tag.nil?
|
85
|
+
@aggregate = :all
|
57
86
|
when 'tag'
|
58
|
-
raise Fluent::ConfigError, "
|
87
|
+
# raise Fluent::ConfigError, "out_stats_notifier: `add_tag_prefix` must be specified with aggregate tag" if @add_tag_prefix.nil?
|
88
|
+
@aggregate = :tag
|
59
89
|
else
|
60
|
-
raise Fluent::ConfigError, "
|
90
|
+
raise Fluent::ConfigError, "out_stats_notifier: aggregate allows tag/all"
|
61
91
|
end
|
62
92
|
|
63
|
-
@tag_prefix = "#{@add_tag_prefix}." if @add_tag_prefix
|
64
|
-
@tag_prefix_match = "#{@remove_tag_prefix}." if @remove_tag_prefix
|
65
|
-
@tag_proc =
|
66
|
-
if @tag_prefix and @tag_prefix_match
|
67
|
-
Proc.new {|tag| "#{@tag_prefix}#{lstrip(tag, @tag_prefix_match)}" }
|
68
|
-
elsif @tag_prefix_match
|
69
|
-
Proc.new {|tag| lstrip(tag, @tag_prefix_match) }
|
70
|
-
elsif @tag_prefix
|
71
|
-
Proc.new {|tag| "#{@tag_prefix}#{tag}" }
|
72
|
-
elsif @tag
|
73
|
-
Proc.new {|tag| @tag }
|
74
|
-
else
|
75
|
-
Proc.new {|tag| tag }
|
76
|
-
end
|
77
|
-
|
78
93
|
@counts = {}
|
79
|
-
@
|
94
|
+
@queues = {}
|
80
95
|
@mutex = Mutex.new
|
81
96
|
end
|
82
97
|
|
@@ -97,30 +112,30 @@ class Fluent::StatsNotifierOutput < Fluent::Output
|
|
97
112
|
def emit(tag, es, chain)
|
98
113
|
key = @target_key
|
99
114
|
|
100
|
-
#
|
101
|
-
count = 0;
|
115
|
+
# enqueus
|
116
|
+
count = 0; queues = {}
|
102
117
|
es.each do |time,record|
|
103
118
|
if record[key]
|
104
|
-
|
105
|
-
|
119
|
+
queues[key] ||= []
|
120
|
+
queues[key] << record[key]
|
106
121
|
end
|
107
122
|
count += 1
|
108
123
|
end
|
109
124
|
|
110
125
|
# thread safe merge
|
111
126
|
@counts[tag] ||= 0
|
112
|
-
@
|
127
|
+
@queues[tag] ||= {}
|
113
128
|
@mutex.synchronize do
|
114
|
-
if
|
115
|
-
|
116
|
-
@
|
129
|
+
if queues[key]
|
130
|
+
@queues[tag][key] ||= []
|
131
|
+
@queues[tag][key].concat(queues[key])
|
117
132
|
end
|
118
133
|
@counts[tag] += count
|
119
134
|
end
|
120
135
|
|
121
136
|
chain.next
|
122
137
|
rescue => e
|
123
|
-
|
138
|
+
log.warn "#{e.class} #{e.message} #{e.backtrace.first}"
|
124
139
|
end
|
125
140
|
|
126
141
|
# thread callback
|
@@ -138,7 +153,7 @@ class Fluent::StatsNotifierOutput < Fluent::Output
|
|
138
153
|
@last_checked = now
|
139
154
|
end
|
140
155
|
rescue => e
|
141
|
-
|
156
|
+
log.warn "#{e.class} #{e.message} #{e.backtrace.first}"
|
142
157
|
end
|
143
158
|
end
|
144
159
|
end
|
@@ -146,46 +161,76 @@ class Fluent::StatsNotifierOutput < Fluent::Output
|
|
146
161
|
# This method is the real one to emit
|
147
162
|
def flush_emit(step)
|
148
163
|
time = Fluent::Engine.now
|
149
|
-
counts,
|
164
|
+
counts, queues, @counts, @queues = @counts, @queues, {}, {}
|
150
165
|
|
151
|
-
|
152
|
-
|
153
|
-
|
166
|
+
# Get statistical value among events
|
167
|
+
evented_queues = {}
|
168
|
+
queues.each do |tag, queue|
|
169
|
+
evented_queues[tag] ||= {}
|
170
|
+
evented_queues[tag][@target_key] = get_stats(queue[@target_key], @stats) if queue[@target_key]
|
171
|
+
end
|
172
|
+
|
173
|
+
if @aggregate == :all
|
174
|
+
values = evented_queues.values.map {|queue| queue[@target_key] }.compact
|
175
|
+
value = get_stats(values, @aggregate_stats)
|
176
|
+
output = generate_output(value) if value
|
154
177
|
Fluent::Engine.emit(@tag, time, output) if output
|
155
178
|
else # aggregate tag
|
156
|
-
|
157
|
-
|
158
|
-
output = generate_output(
|
179
|
+
evented_queues.each do |tag, queue|
|
180
|
+
value = queue[@target_key]
|
181
|
+
output = generate_output(value) if value
|
159
182
|
emit_tag = @tag_proc.call(tag)
|
160
183
|
Fluent::Engine.emit(emit_tag, time, output) if output
|
161
184
|
end
|
162
185
|
end
|
163
186
|
end
|
164
187
|
|
165
|
-
def
|
166
|
-
case
|
188
|
+
def get_stats(values, method = :max)
|
189
|
+
case method
|
167
190
|
when :sum
|
168
|
-
|
191
|
+
stats = values.inject(:+)
|
169
192
|
when :max
|
170
|
-
|
193
|
+
stats = values.max
|
171
194
|
when :min
|
172
|
-
|
195
|
+
stats = values.min
|
173
196
|
when :avg
|
174
|
-
|
197
|
+
stats = values.inject(:+) / values.count unless values.empty?
|
175
198
|
end
|
199
|
+
end
|
176
200
|
|
177
|
-
|
178
|
-
return nil if
|
179
|
-
return nil if @less_than and @less_than <=
|
180
|
-
return nil if @less_equal and @less_equal <
|
181
|
-
return nil if @greater_than and
|
182
|
-
return nil if @greater_equal and
|
201
|
+
def generate_output(value)
|
202
|
+
return nil if value == 0 # ignore 0 because standby nodes receive 0 message usually
|
203
|
+
return nil if @less_than and @less_than <= value
|
204
|
+
return nil if @less_equal and @less_equal < value
|
205
|
+
return nil if @greater_than and value <= @greater_than
|
206
|
+
return nil if @greater_equal and value < @greater_equal
|
183
207
|
|
184
208
|
output = {}
|
185
|
-
output[@target_key] =
|
209
|
+
output[@target_key] = value
|
186
210
|
output
|
187
211
|
end
|
188
212
|
|
213
|
+
def tag_proc
|
214
|
+
rstrip = Proc.new {|str, substr| str.chomp(substr) }
|
215
|
+
lstrip = Proc.new {|str, substr| str.start_with?(substr) ? str[substr.size..-1] : str }
|
216
|
+
tag_prefix = "#{rstrip.call(@add_tag_prefix, '.')}." if @add_tag_prefix
|
217
|
+
tag_suffix = ".#{lstrip.call(@add_tag_suffix, '.')}" if @add_tag_suffix
|
218
|
+
tag_prefix_match = "#{rstrip.call(@remove_tag_prefix, '.')}." if @remove_tag_prefix
|
219
|
+
tag_suffix_match = ".#{lstrip.call(@remove_tag_suffix, '.')}" if @remove_tag_suffix
|
220
|
+
tag_fixed = @tag if @tag
|
221
|
+
if tag_fixed
|
222
|
+
Proc.new {|tag| tag_fixed }
|
223
|
+
elsif tag_prefix_match and tag_suffix_match
|
224
|
+
Proc.new {|tag| "#{tag_prefix}#{rstrip.call(lstrip.call(tag, tag_prefix_match), tag_suffix_match)}#{tag_suffix}" }
|
225
|
+
elsif tag_prefix_match
|
226
|
+
Proc.new {|tag| "#{tag_prefix}#{lstrip.call(tag, tag_prefix_match)}#{tag_suffix}" }
|
227
|
+
elsif tag_suffix_match
|
228
|
+
Proc.new {|tag| "#{tag_prefix}#{rstrip.call(tag, tag_suffix_match)}#{tag_suffix}" }
|
229
|
+
else
|
230
|
+
Proc.new {|tag| "#{tag_prefix}#{tag}#{tag_suffix}" }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
189
234
|
# Store internal status into a file
|
190
235
|
#
|
191
236
|
# @param [String] file_path
|
@@ -198,14 +243,14 @@ class Fluent::StatsNotifierOutput < Fluent::Output
|
|
198
243
|
@saved_duration = @saved_at - @last_checked
|
199
244
|
Marshal.dump({
|
200
245
|
:counts => @counts,
|
201
|
-
:
|
246
|
+
:queues => @queues,
|
202
247
|
:saved_at => @saved_at,
|
203
248
|
:saved_duration => @saved_duration,
|
204
249
|
:target_key => @target_key,
|
205
250
|
}, f)
|
206
251
|
end
|
207
252
|
rescue => e
|
208
|
-
|
253
|
+
log.warn "out_stats_notifier: Can't write store_file #{e.class} #{e.message}"
|
209
254
|
end
|
210
255
|
end
|
211
256
|
|
@@ -220,24 +265,27 @@ class Fluent::StatsNotifierOutput < Fluent::Output
|
|
220
265
|
f.open('rb') do |f|
|
221
266
|
stored = Marshal.load(f)
|
222
267
|
if stored[:target_key] == @target_key
|
268
|
+
if stored[:queues]
|
269
|
+
if Fluent::Engine.now <= stored[:saved_at] + interval
|
270
|
+
@counts = stored[:counts]
|
271
|
+
@queues = stored[:queues]
|
272
|
+
@saved_at = stored[:saved_at]
|
273
|
+
@saved_duration = stored[:saved_duration]
|
223
274
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
# skip the saved duration to continue counting
|
231
|
-
@last_checked = Fluent::Engine.now - @saved_duration
|
275
|
+
# skip the saved duration to continue counting
|
276
|
+
@last_checked = Fluent::Engine.now - @saved_duration
|
277
|
+
else
|
278
|
+
log.warn "out_stats_notifier: stored data is outdated. ignore stored data"
|
279
|
+
end
|
232
280
|
else
|
233
|
-
|
281
|
+
log.warn "out_stats_notifier: stored data is incompatible. ignore stored data"
|
234
282
|
end
|
235
283
|
else
|
236
|
-
|
284
|
+
log.warn "out_stats_notifier: configuration param was changed. ignore stored data"
|
237
285
|
end
|
238
286
|
end
|
239
287
|
rescue => e
|
240
|
-
|
288
|
+
log.warn "out_stats_notifier: Can't load store_file #{e.class} #{e.message}"
|
241
289
|
end
|
242
290
|
end
|
243
291
|
|
@@ -13,6 +13,7 @@ describe Fluent::StatsNotifierOutput do
|
|
13
13
|
CONFIG = %[
|
14
14
|
target_key 5xx_count
|
15
15
|
tag foo
|
16
|
+
# compare_with max
|
16
17
|
]
|
17
18
|
let(:tag) { 'foo.bar' }
|
18
19
|
let(:driver) { Fluent::Test::OutputTestDriver.new(Fluent::StatsNotifierOutput, tag).configure(config) }
|
@@ -33,6 +34,11 @@ describe Fluent::StatsNotifierOutput do
|
|
33
34
|
let(:config) { CONFIG + %[greater_than 2 \n greater_equal 3] }
|
34
35
|
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
35
36
|
end
|
37
|
+
|
38
|
+
context "not tag option is specified" do
|
39
|
+
let(:config) { %[target_key 5xx_count] }
|
40
|
+
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
41
|
+
end
|
36
42
|
end
|
37
43
|
|
38
44
|
describe 'good configuration' do
|
@@ -47,16 +53,16 @@ describe Fluent::StatsNotifierOutput do
|
|
47
53
|
let(:time) { Time.now.to_i }
|
48
54
|
let(:messages) do
|
49
55
|
[
|
50
|
-
{"4xx_count"=>1,"5xx_count"=>
|
51
|
-
{"4xx_count"=>2,"5xx_count"=>
|
52
|
-
{"4xx_count"=>3,"5xx_count"=>
|
56
|
+
{"4xx_count"=>1,"5xx_count"=>6,"reqtime_max"=>6,"reqtime_min"=>1,"reqtime_avg"=>3},
|
57
|
+
{"4xx_count"=>2,"5xx_count"=>6,"reqtime_max"=>5,"reqtime_min"=>2,"reqtime_avg"=>2},
|
58
|
+
{"4xx_count"=>3,"5xx_count"=>6,"reqtime_max"=>1,"reqtime_min"=>3,"reqtime_avg"=>4},
|
53
59
|
]
|
54
60
|
end
|
55
61
|
let(:emit) do
|
56
62
|
driver.run { messages.each {|message| driver.emit(message, time) } }
|
57
63
|
driver.instance.flush_emit(0)
|
58
64
|
end
|
59
|
-
let(:config) { CONFIG } # 5xx_count,
|
65
|
+
let(:config) { CONFIG } # 5xx_count, max
|
60
66
|
let(:expected) do
|
61
67
|
{
|
62
68
|
"5xx_count"=>6,
|
@@ -164,7 +170,7 @@ describe Fluent::StatsNotifierOutput do
|
|
164
170
|
end
|
165
171
|
|
166
172
|
context 'tag' do
|
167
|
-
let(:config) {
|
173
|
+
let(:config) { %[target_key 5xx_count \n aggregate tag \n add_tag_prefix add] }
|
168
174
|
before do
|
169
175
|
Fluent::Engine.stub(:now).and_return(time)
|
170
176
|
Fluent::Engine.should_receive(:emit).with("add.foo.bar1", time, {"5xx_count"=>2.0})
|
@@ -174,7 +180,7 @@ describe Fluent::StatsNotifierOutput do
|
|
174
180
|
end
|
175
181
|
end
|
176
182
|
|
177
|
-
context 'compare_with' do
|
183
|
+
context 'compare_with (obsolete)' do
|
178
184
|
let(:emit) do
|
179
185
|
driver.run do
|
180
186
|
driver.emit_with_tag({"5xx_count"=>2}, time, 'foo.bar1')
|
@@ -284,6 +290,138 @@ describe Fluent::StatsNotifierOutput do
|
|
284
290
|
end
|
285
291
|
end
|
286
292
|
|
293
|
+
context 'aggregate_stats' do
|
294
|
+
let(:emit) do
|
295
|
+
driver.run do
|
296
|
+
driver.emit_with_tag({"5xx_count"=>2}, time, 'foo.bar1')
|
297
|
+
driver.emit_with_tag({"5xx_count"=>6}, time, 'foo.bar2')
|
298
|
+
end
|
299
|
+
driver.instance.flush_emit(0)
|
300
|
+
end
|
301
|
+
|
302
|
+
context 'avg' do
|
303
|
+
let(:config) { CONFIG + %[less_equal 4 \n aggregate_stats avg] }
|
304
|
+
let(:expected) do
|
305
|
+
{
|
306
|
+
"5xx_count" => 4.0
|
307
|
+
}
|
308
|
+
end
|
309
|
+
before do
|
310
|
+
Fluent::Engine.stub(:now).and_return(time)
|
311
|
+
Fluent::Engine.should_receive(:emit).with("foo", time, expected)
|
312
|
+
end
|
313
|
+
it { emit }
|
314
|
+
end
|
315
|
+
|
316
|
+
context 'sum' do
|
317
|
+
let(:config) { CONFIG + %[less_equal 8 \n aggregate_stats sum] }
|
318
|
+
let(:expected) do
|
319
|
+
{
|
320
|
+
"5xx_count" => 8.0
|
321
|
+
}
|
322
|
+
end
|
323
|
+
before do
|
324
|
+
Fluent::Engine.stub(:now).and_return(time)
|
325
|
+
Fluent::Engine.should_receive(:emit).with("foo", time, expected)
|
326
|
+
end
|
327
|
+
it { emit }
|
328
|
+
end
|
329
|
+
|
330
|
+
context 'min' do
|
331
|
+
let(:config) { CONFIG + %[less_equal 2 \n aggregate_stats min] }
|
332
|
+
let(:expected) do
|
333
|
+
{
|
334
|
+
"5xx_count" => 2.0
|
335
|
+
}
|
336
|
+
end
|
337
|
+
before do
|
338
|
+
Fluent::Engine.stub(:now).and_return(time)
|
339
|
+
Fluent::Engine.should_receive(:emit).with("foo", time, expected)
|
340
|
+
end
|
341
|
+
it { emit }
|
342
|
+
end
|
343
|
+
|
344
|
+
context 'max' do
|
345
|
+
let(:config) { CONFIG + %[less_equal 6 \n aggregate_stats max] }
|
346
|
+
let(:expected) do
|
347
|
+
{
|
348
|
+
"5xx_count" => 6.0
|
349
|
+
}
|
350
|
+
end
|
351
|
+
before do
|
352
|
+
Fluent::Engine.stub(:now).and_return(time)
|
353
|
+
Fluent::Engine.should_receive(:emit).with("foo", time, expected)
|
354
|
+
end
|
355
|
+
it { emit }
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
context 'stats' do
|
360
|
+
let(:emit) do
|
361
|
+
driver.run do
|
362
|
+
driver.emit_with_tag({"5xx_count"=>2}, time, 'foo.bar1')
|
363
|
+
driver.emit_with_tag({"5xx_count"=>6}, time, 'foo.bar1')
|
364
|
+
end
|
365
|
+
driver.instance.flush_emit(0)
|
366
|
+
end
|
367
|
+
|
368
|
+
context 'avg' do
|
369
|
+
let(:config) { CONFIG + %[less_equal 4 \n stats avg] }
|
370
|
+
let(:expected) do
|
371
|
+
{
|
372
|
+
"5xx_count" => 4.0
|
373
|
+
}
|
374
|
+
end
|
375
|
+
before do
|
376
|
+
Fluent::Engine.stub(:now).and_return(time)
|
377
|
+
Fluent::Engine.should_receive(:emit).with("foo", time, expected)
|
378
|
+
end
|
379
|
+
it { emit }
|
380
|
+
end
|
381
|
+
|
382
|
+
context 'sum' do
|
383
|
+
let(:config) { CONFIG + %[less_equal 8 \n stats sum] }
|
384
|
+
let(:expected) do
|
385
|
+
{
|
386
|
+
"5xx_count" => 8.0
|
387
|
+
}
|
388
|
+
end
|
389
|
+
before do
|
390
|
+
Fluent::Engine.stub(:now).and_return(time)
|
391
|
+
Fluent::Engine.should_receive(:emit).with("foo", time, expected)
|
392
|
+
end
|
393
|
+
it { emit }
|
394
|
+
end
|
395
|
+
|
396
|
+
context 'min' do
|
397
|
+
let(:config) { CONFIG + %[less_equal 2 \n stats min] }
|
398
|
+
let(:expected) do
|
399
|
+
{
|
400
|
+
"5xx_count" => 2.0
|
401
|
+
}
|
402
|
+
end
|
403
|
+
before do
|
404
|
+
Fluent::Engine.stub(:now).and_return(time)
|
405
|
+
Fluent::Engine.should_receive(:emit).with("foo", time, expected)
|
406
|
+
end
|
407
|
+
it { emit }
|
408
|
+
end
|
409
|
+
|
410
|
+
context 'max' do
|
411
|
+
let(:config) { CONFIG + %[less_equal 6 \n stats max] }
|
412
|
+
let(:expected) do
|
413
|
+
{
|
414
|
+
"5xx_count" => 6.0
|
415
|
+
}
|
416
|
+
end
|
417
|
+
before do
|
418
|
+
Fluent::Engine.stub(:now).and_return(time)
|
419
|
+
Fluent::Engine.should_receive(:emit).with("foo", time, expected)
|
420
|
+
end
|
421
|
+
it { emit }
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
287
425
|
describe "store_file" do
|
288
426
|
let(:store_file) do
|
289
427
|
dirname = "tmp"
|
@@ -298,22 +436,22 @@ describe Fluent::StatsNotifierOutput do
|
|
298
436
|
driver.run { messages.each {|message| driver.emit(message, time) } }
|
299
437
|
driver.instance.shutdown
|
300
438
|
stored_counts = driver.instance.counts
|
301
|
-
|
439
|
+
stored_queues = driver.instance.queues
|
302
440
|
stored_saved_at = driver.instance.saved_at
|
303
441
|
stored_saved_duration = driver.instance.saved_duration
|
304
442
|
driver.instance.counts = {}
|
305
|
-
driver.instance.
|
443
|
+
driver.instance.queues = {}
|
306
444
|
driver.instance.saved_at = nil
|
307
445
|
driver.instance.saved_duration = nil
|
308
446
|
|
309
447
|
driver.instance.start
|
310
448
|
loaded_counts = driver.instance.counts
|
311
|
-
|
449
|
+
loaded_queues = driver.instance.queues
|
312
450
|
loaded_saved_at = driver.instance.saved_at
|
313
451
|
loaded_saved_duration = driver.instance.saved_duration
|
314
452
|
|
315
453
|
loaded_counts.should == stored_counts
|
316
|
-
|
454
|
+
loaded_queues.should == stored_queues
|
317
455
|
loaded_saved_at.should == stored_saved_at
|
318
456
|
loaded_saved_duration.should == stored_saved_duration
|
319
457
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-stats-notifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Naotoshi Seo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|