fluent-plugin-notifier 0.0.1
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.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +63 -0
- data/Rakefile +2 -0
- data/fluent-plugin-notifier.gemspec +18 -0
- data/lib/fluent/plugin/out_notifier.rb +350 -0
- data/test/helper.rb +28 -0
- data/test/plugin/test_out_notifier.rb +0 -0
- metadata +88 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2012- TAGOMORI Satoshi
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# fluent-plugin-notifier
|
2
|
+
|
3
|
+
## Component
|
4
|
+
|
5
|
+
### NotifierOutput
|
6
|
+
|
7
|
+
Plugin to emit notifications for messages, with numbers over/under threshold, or specified pattern strings.
|
8
|
+
|
9
|
+
## Configuration
|
10
|
+
|
11
|
+
### NotifierOutput
|
12
|
+
|
13
|
+
To notify apache logs with over 1000000 (microseconds) duration for CRITICAL , or status '500' by string pattern match:
|
14
|
+
|
15
|
+
<match apache.log.**>
|
16
|
+
type notifier
|
17
|
+
<def>
|
18
|
+
pattern apache_duration
|
19
|
+
check numeric_upward
|
20
|
+
warn_threshold 800000
|
21
|
+
crit_threshold 1000000
|
22
|
+
target_keys duration
|
23
|
+
</def>
|
24
|
+
<def>
|
25
|
+
pattern status_500
|
26
|
+
check string_find
|
27
|
+
warn_regexp 5\d\d
|
28
|
+
crit_regexp 500
|
29
|
+
target_key_pattern ^status.*$
|
30
|
+
</def>
|
31
|
+
</match>
|
32
|
+
|
33
|
+
With this configuration, you will get notification message like this:
|
34
|
+
|
35
|
+
2012-05-15 19:44:29 +0900 notification: {"pattern":"apache_duration","target_tag":"apache.log.xxx","target_key":"duration","check_type":"numeric_upward","level":"crit","threshold":1000000,"value":"1057231","message_time":"2012-05-15 19:44:27 +0900"}
|
36
|
+
2012-05-15 19:44:29 +0900 notification: {"pattern":"status_500","target_tag":"apache.log.xxx","target_key":"status","check_type":"string_find","level":"crit","regexp":"/500/","value":"500","message_time":"2012-05-15 19:44:27 +0900"}
|
37
|
+
|
38
|
+
Available 'check' types: 'numeric\_upward', 'numeric\_downward' and 'string\_find'
|
39
|
+
|
40
|
+
Default configurations:
|
41
|
+
|
42
|
+
* tag: 'notification'
|
43
|
+
* in <match> top level, 'default\_tag', 'default\_tag\_warn,' and 'default\_tag\_crit' available
|
44
|
+
* in each <def> section, 'tag', 'tag\_warn' and 'tag\_crit' available
|
45
|
+
* notification suppression
|
46
|
+
* at first, notified once in 1 minute, 5 times
|
47
|
+
* next, notified once in 5 minutes, 5 times
|
48
|
+
* last, notified once in 30 minutes
|
49
|
+
* in <match> top level, 'default\_interval\_1st', 'default\_interval\_2nd', 'default\_interval\_3rd', 'default\_repetitions\_1st' and 'default\_repetitions\_2nd' available
|
50
|
+
* in each <def> section, 'interval\_1st', 'interval\_2nd', 'interval\_3rd', 'repetitions\_1st' and 'repetitions\_2nd' available
|
51
|
+
|
52
|
+
If you want to get every 5 minutes notifications (after 1 minutes notifications), specify '0' for 'repetitions\_2nd'.
|
53
|
+
|
54
|
+
## TODO
|
55
|
+
|
56
|
+
* long run
|
57
|
+
|
58
|
+
## Copyright
|
59
|
+
|
60
|
+
* Copyright
|
61
|
+
* Copyright (c) 2012- TAGOMORI Satoshi (tagomoris)
|
62
|
+
* License
|
63
|
+
* Apache License, Version 2.0
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |gem|
|
3
|
+
gem.name = "fluent-plugin-notifier"
|
4
|
+
gem.version = "0.0.1"
|
5
|
+
gem.authors = ["TAGOMORI Satoshi"]
|
6
|
+
gem.email = ["tagomoris@gmail.com"]
|
7
|
+
gem.summary = %q{check matched messages and emit alert message}
|
8
|
+
gem.description = %q{check matched messages and emit alert message with throttling by conditions...}
|
9
|
+
gem.homepage = "https://github.com/tagomoris/fluent-plugin-notifier"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.require_paths = ["lib"]
|
15
|
+
|
16
|
+
gem.add_development_dependency "fluentd"
|
17
|
+
gem.add_runtime_dependency "fluentd"
|
18
|
+
end
|
@@ -0,0 +1,350 @@
|
|
1
|
+
class Fluent::NotifierOutput < Fluent::Output
|
2
|
+
Fluent::Plugin.register_output('notifier', self)
|
3
|
+
|
4
|
+
NOTIFICATION_LEVELS = ['OK', 'WARN', 'CRIT', 'LOST'].freeze
|
5
|
+
|
6
|
+
STATES_CLEAN_INTERVAL = 3600 # 1hours
|
7
|
+
STATES_EXPIRE_SECONDS = 14400 # 4hours
|
8
|
+
|
9
|
+
config_param :default_tag, :string, :default => 'notification'
|
10
|
+
config_param :default_tag_warn, :string, :default => nil
|
11
|
+
config_param :default_tag_crit, :string, :default => nil
|
12
|
+
|
13
|
+
config_param :default_interval_1st, :time, :default => 60
|
14
|
+
config_param :default_repetitions_1st, :integer, :default => 5
|
15
|
+
config_param :default_interval_2nd, :time, :default => 300
|
16
|
+
config_param :default_repetitions_2nd, :integer, :default => 5
|
17
|
+
config_param :default_interval_3rd, :time, :default => 1800
|
18
|
+
|
19
|
+
attr_accessor :defs, :states, :match_cache, :negative_cache
|
20
|
+
|
21
|
+
### output
|
22
|
+
# {
|
23
|
+
# 'pattern' => 'http_status_errors',
|
24
|
+
# 'target_tag' => 'httpstatus.blog',
|
25
|
+
# 'target_key' => 'blog_5xx_percentage',
|
26
|
+
# 'check_type' => 'numeric_upward'
|
27
|
+
# 'level' => 'warn',
|
28
|
+
# 'threshold' => 25, # or 'regexp' => ....,
|
29
|
+
# 'value' => 49, # or 'value' => 'matched some string...',
|
30
|
+
# 'message_time' => Time.instance
|
31
|
+
# }
|
32
|
+
|
33
|
+
# <match httpstatus.blog>
|
34
|
+
# type notifier
|
35
|
+
# default_tag notification
|
36
|
+
# default_interval_1st 1m
|
37
|
+
# default_repetitions_1st 5
|
38
|
+
# default_interval_2nd 5m
|
39
|
+
# default_repetitions_2nd 5
|
40
|
+
# default_interval_3rd 30m
|
41
|
+
# <def>
|
42
|
+
# pattern http_status_errors
|
43
|
+
# check numeric_upward
|
44
|
+
# warn_threshold 25
|
45
|
+
# crit_threshold 50
|
46
|
+
# tag alert
|
47
|
+
# # tag_warn alert.warn
|
48
|
+
# # tag_crit alert.crit
|
49
|
+
# # target_keys blog_5xx_percentage
|
50
|
+
# target_key_pattern ^.*_5xx_percentage$
|
51
|
+
# </def>
|
52
|
+
# <def>
|
53
|
+
# pattern log_checker
|
54
|
+
# check string_find
|
55
|
+
# crit_pattern 'ERROR'
|
56
|
+
# warn_pattern 'WARNING'
|
57
|
+
# tag alert
|
58
|
+
# # target_keys message
|
59
|
+
# target_key_pattern ^.*_message$
|
60
|
+
# </def>
|
61
|
+
# </match>
|
62
|
+
|
63
|
+
def configure(conf)
|
64
|
+
super
|
65
|
+
|
66
|
+
@match_cache = {} # cache which has map (fieldname => definition(s))
|
67
|
+
@negative_cache = {}
|
68
|
+
@defs = []
|
69
|
+
@states = {} # key: tag+field ?
|
70
|
+
|
71
|
+
defaults = {
|
72
|
+
:tag => @default_tag, :tag_warn => @default_tag_warn, :tag_crit => @default_tag_crit,
|
73
|
+
:interval_1st => @default_interval_1st, :repetitions_1st => @default_repetitions_1st,
|
74
|
+
:interval_2nd => @default_interval_2nd, :repetitions_2nd => @default_repetitions_2nd,
|
75
|
+
:interval_3rd => @default_interval_3rd,
|
76
|
+
}
|
77
|
+
|
78
|
+
conf.elements.each do |element|
|
79
|
+
if element.name != 'def'
|
80
|
+
raise Fluent::ConfigError, "invalid section name for out_notifier: #{d.name}"
|
81
|
+
end
|
82
|
+
defs.push(Definition.new(element, defaults))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def start
|
87
|
+
super
|
88
|
+
@mutex = Mutex.new
|
89
|
+
@last_status_cleaned = Fluent::Engine.now
|
90
|
+
end
|
91
|
+
|
92
|
+
# def shutdown
|
93
|
+
# end
|
94
|
+
|
95
|
+
def suppressed_emit(notifications)
|
96
|
+
notifications.each do |n|
|
97
|
+
hashkey = n.delete(:hashkey)
|
98
|
+
definition = n.delete(:match_def)
|
99
|
+
tag = n.delete(:emit_tag)
|
100
|
+
|
101
|
+
state = @states[hashkey]
|
102
|
+
if state
|
103
|
+
unless state.suppress?(definition, n)
|
104
|
+
Fluent::Engine.emit(tag, Fluent::Engine.now, n)
|
105
|
+
state.update_notified(definition, n)
|
106
|
+
end
|
107
|
+
else
|
108
|
+
Fluent::Engine.emit(tag, Fluent::Engine.now, n)
|
109
|
+
@states[hashkey] = State.new(n)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def states_cleanup
|
115
|
+
now = Fluent::Engine.now
|
116
|
+
@states.keys.each do |key|
|
117
|
+
if now - @states[key].last_notified > STATES_EXPIRE_SECONDS
|
118
|
+
@states.delete(key)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def emit(tag, es, chain)
|
124
|
+
notifications = []
|
125
|
+
|
126
|
+
es.each do |time,record|
|
127
|
+
record.keys.each do |key|
|
128
|
+
|
129
|
+
next if @negative_cache[key]
|
130
|
+
|
131
|
+
defs = @match_cache[key]
|
132
|
+
unless defs
|
133
|
+
defs = []
|
134
|
+
@defs.each do |d|
|
135
|
+
defs.push(d) if d.match?(key)
|
136
|
+
end
|
137
|
+
if defs.size < 1
|
138
|
+
@negative_cache[key] = true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
defs.each do |d|
|
143
|
+
alert = d.check(tag, time, record, key)
|
144
|
+
if alert
|
145
|
+
notifications.push(alert)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
if notifications.size > 0
|
152
|
+
@mutex.synchronize do
|
153
|
+
suppressed_emit(notifications)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
if Fluent::Engine.now - @last_status_cleaned > STATES_CLEAN_INTERVAL
|
158
|
+
@mutex.synchronize do
|
159
|
+
states_cleanup
|
160
|
+
@last_status_cleaned = Fluent::Engine.now
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
chain.next
|
165
|
+
end
|
166
|
+
|
167
|
+
class Definition
|
168
|
+
attr_accessor :tag, :tag_warn, :tag_crit
|
169
|
+
attr_accessor :intervals, :repetitions
|
170
|
+
attr_accessor :pattern, :check, :target_keys, :target_key_pattern
|
171
|
+
attr_accessor :crit_threshold, :warn_threshold # for 'numeric_upward', 'numeric_downward'
|
172
|
+
attr_accessor :crit_regexp, :warn_regexp # for 'string_find'
|
173
|
+
|
174
|
+
def initialize(element, defaults)
|
175
|
+
element.keys.each do |k|
|
176
|
+
case k
|
177
|
+
when 'pattern'
|
178
|
+
@pattern = element[k]
|
179
|
+
when 'check'
|
180
|
+
case element[k]
|
181
|
+
when 'numeric_upward'
|
182
|
+
@check = :upward
|
183
|
+
@crit_threshold = element['crit_threshold'].to_f
|
184
|
+
@warn_threshold = element['warn_threshold'].to_f
|
185
|
+
when 'numeric_downward'
|
186
|
+
@check = :downward
|
187
|
+
@crit_threshold = element['crit_threshold'].to_f
|
188
|
+
@warn_threshold = element['warn_threshold'].to_f
|
189
|
+
when 'string_find'
|
190
|
+
@check = :find
|
191
|
+
@crit_regexp = Regexp.compile(element['crit_regexp'].to_s)
|
192
|
+
@warn_regexp = Regexp.compile(element['warn_regexp'].to_s)
|
193
|
+
else
|
194
|
+
raise Fluent::ConfigError, "invalid check type: #{element[k]}"
|
195
|
+
end
|
196
|
+
when 'target_keys'
|
197
|
+
@target_keys = element['target_keys'].split(',')
|
198
|
+
when 'target_key_pattern'
|
199
|
+
@target_key_pattern = Regexp.compile(element['target_key_pattern'])
|
200
|
+
end
|
201
|
+
end
|
202
|
+
if @pattern.nil? or @pattern.length < 1
|
203
|
+
raise Fluent::ConfigError, "pattern must be set"
|
204
|
+
end
|
205
|
+
if @target_keys.nil? and @target_key_pattern.nil?
|
206
|
+
raise Fluent::ConfigError, "out_notifier needs one of target_keys or target_key_pattern"
|
207
|
+
end
|
208
|
+
@tag = element['tag'] || defaults[:tag]
|
209
|
+
@tag_warn = element['tag_warn'] || defaults[:tag_warn]
|
210
|
+
@tag_crit = element['tag_crit'] || defaults[:tag_crit]
|
211
|
+
@intervals = [
|
212
|
+
(element['interval_1st'] || defaults[:interval_1st]),
|
213
|
+
(element['interval_2nd'] || defaults[:interval_2nd]),
|
214
|
+
(element['interval_3rd'] || defaults[:interval_3rd])
|
215
|
+
]
|
216
|
+
@repetitions = [
|
217
|
+
(element['repetitions_1st'] || defaults[:repetitions_1st]),
|
218
|
+
(element['repetitions_2nd'] || defaults[:repetitions_2nd])
|
219
|
+
]
|
220
|
+
end
|
221
|
+
|
222
|
+
def match?(key)
|
223
|
+
(@target_keys and @target_keys.include?(key)) or (@target_key_pattern and @target_key_pattern.match(key))
|
224
|
+
end
|
225
|
+
|
226
|
+
# {
|
227
|
+
# 'pattern' => 'http_status_errors',
|
228
|
+
# 'target_tag' => 'httpstatus.blog',
|
229
|
+
# 'target_key' => 'blog_5xx_percentage',
|
230
|
+
# 'check_type' => 'numeric_upward'
|
231
|
+
# 'level' => 'warn', # 'regexp' => '[WARN] .* MUST BE CHECKED!$'
|
232
|
+
# 'threshold' => 25,
|
233
|
+
# 'value' => 49, # 'value' => '2012/05/15 18:01:59 [WARN] wooooops, MUST BE CHECKED!'
|
234
|
+
# 'message_time' => Time.instance
|
235
|
+
# }
|
236
|
+
def check(tag, time, record, key)
|
237
|
+
case @check
|
238
|
+
when :upward
|
239
|
+
if @crit_threshold and record[key].to_f >= @crit_threshold
|
240
|
+
{
|
241
|
+
:hashkey => @pattern + "\t" + tag + "\t" + key,
|
242
|
+
:match_def => self,
|
243
|
+
:emit_tag => (@tag_crit || @tag),
|
244
|
+
'pattern' => @pattern, 'target_tag' => tag, 'target_key' => key, 'check_type' => 'numeric_upward', 'level' => 'crit',
|
245
|
+
'threshold' => @crit_threshold, 'value' => record[key], 'message_time' => Time.at(time).to_s
|
246
|
+
}
|
247
|
+
elsif @warn_threshold and record[key].to_f >= @warn_threshold
|
248
|
+
{
|
249
|
+
:hashkey => @pattern + "\t" + tag + "\t" + key,
|
250
|
+
:match_def => self,
|
251
|
+
:emit_tag => (@tag_warn || @tag),
|
252
|
+
'pattern' => @pattern, 'target_tag' => tag, 'target_key' => key, 'check_type' => 'numeric_upward', 'level' => 'warn',
|
253
|
+
'threshold' => @warn_threshold, 'value' => record[key], 'message_time' => Time.at(time).to_s
|
254
|
+
}
|
255
|
+
else
|
256
|
+
nil
|
257
|
+
end
|
258
|
+
when :downward
|
259
|
+
if @crit_threshold and record[key].to_f <= @crit_threshold
|
260
|
+
{
|
261
|
+
:hashkey => @pattern + "\t" + tag + "\t" + key,
|
262
|
+
:match_def => self,
|
263
|
+
:emit_tag => (@tag_crit || @tag),
|
264
|
+
'pattern' => @pattern, 'target_tag' => tag, 'target_key' => key, 'check_type' => 'numeric_downward', 'level' => 'crit',
|
265
|
+
'threshold' => @crit_threshold, 'value' => record[key], 'message_time' => Time.at(time).to_s
|
266
|
+
}
|
267
|
+
elsif @warn_threshold and record[key].to_f <= @warn_threshold
|
268
|
+
{
|
269
|
+
:hashkey => @pattern + "\t" + tag + "\t" + key,
|
270
|
+
:match_def => self,
|
271
|
+
:emit_tag => (@tag_warn || @tag),
|
272
|
+
'pattern' => @pattern, 'target_tag' => tag, 'target_key' => key, 'check_type' => 'numeric_downward', 'level' => 'warn',
|
273
|
+
'threshold' => @warn_threshold, 'value' => record[key], 'message_time' => Time.at(time).to_s
|
274
|
+
}
|
275
|
+
else
|
276
|
+
nil
|
277
|
+
end
|
278
|
+
when :find
|
279
|
+
if @crit_regexp and @crit_regexp.match(record[key].to_s)
|
280
|
+
{
|
281
|
+
:hashkey => @pattern + "\t" + tag + "\t" + key,
|
282
|
+
:match_def => self,
|
283
|
+
:emit_tag => (@tag_crit || @tag),
|
284
|
+
'pattern' => @pattern, 'target_tag' => tag, 'target_key' => key, 'check_type' => 'string_find', 'level' => 'crit',
|
285
|
+
'regexp' => @crit_regexp.inspect, 'value' => record[key], 'message_time' => Time.at(time).to_s
|
286
|
+
}
|
287
|
+
elsif @warn_regexp and @warn_regexp.match(record[key].to_s)
|
288
|
+
{
|
289
|
+
:hashkey => @pattern + "\t" + tag + "\t" + key,
|
290
|
+
:match_def => self,
|
291
|
+
:emit_tag => (@tag_warn || @tag),
|
292
|
+
'pattern' => @pattern, 'target_tag' => tag, 'target_key' => key, 'check_type' => 'string_find', 'level' => 'warn',
|
293
|
+
'regexp' => @warn_regexp.inspect, 'value' => record[key], 'message_time' => Time.at(time).to_s
|
294
|
+
}
|
295
|
+
else
|
296
|
+
nil
|
297
|
+
end
|
298
|
+
else
|
299
|
+
raise ArgumentError, "unknown check type (maybe bug): #{@check}"
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
class State
|
305
|
+
# level: :warn, :crit
|
306
|
+
# stage: 0(1st)/1(2nd)/2(3rd)
|
307
|
+
attr_accessor :pattern, :target_tag, :target_key, :level, :stage, :counter, :first_notified, :last_notified
|
308
|
+
|
309
|
+
def initialize(notification)
|
310
|
+
@pattern = notification[:pattern]
|
311
|
+
@target_tag = notification[:target_tag]
|
312
|
+
@target_key = notification[:target_key]
|
313
|
+
@level = notification['level']
|
314
|
+
@stage = 0
|
315
|
+
@counter = 1
|
316
|
+
t = Fluent::Engine.now
|
317
|
+
@first_notified = t
|
318
|
+
@last_notified = t
|
319
|
+
end
|
320
|
+
|
321
|
+
def suppress?(definition, notification)
|
322
|
+
if @level == notification['level']
|
323
|
+
(Fluent::Engine.now - @last_notified) <= definition.intervals[@stage]
|
324
|
+
else
|
325
|
+
true
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def update_notified(definition, notification)
|
330
|
+
t = Fluent::Engine.now
|
331
|
+
|
332
|
+
if @level == notification['level']
|
333
|
+
rep = definition.repetitions[@stage]
|
334
|
+
if rep and rep > 0
|
335
|
+
@counter += 1
|
336
|
+
if @counter > rep
|
337
|
+
@stage += 1
|
338
|
+
@counter = 0
|
339
|
+
end
|
340
|
+
end
|
341
|
+
else
|
342
|
+
@level = notification['level']
|
343
|
+
@stage = 0
|
344
|
+
@counter = 1
|
345
|
+
@first_notified = t
|
346
|
+
end
|
347
|
+
@last_notified = t
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
+
require 'fluent/test'
|
15
|
+
unless ENV.has_key?('VERBOSE')
|
16
|
+
nulllogger = Object.new
|
17
|
+
nulllogger.instance_eval {|obj|
|
18
|
+
def method_missing(method, *args)
|
19
|
+
# pass
|
20
|
+
end
|
21
|
+
}
|
22
|
+
$log = nulllogger
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'fluent/plugin/out_notifier'
|
26
|
+
|
27
|
+
class Test::Unit::TestCase
|
28
|
+
end
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-notifier
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- TAGOMORI Satoshi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: fluentd
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: fluentd
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: check matched messages and emit alert message with throttling by conditions...
|
47
|
+
email:
|
48
|
+
- tagomoris@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- LICENSE.txt
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- fluent-plugin-notifier.gemspec
|
59
|
+
- lib/fluent/plugin/out_notifier.rb
|
60
|
+
- test/helper.rb
|
61
|
+
- test/plugin/test_out_notifier.rb
|
62
|
+
homepage: https://github.com/tagomoris/fluent-plugin-notifier
|
63
|
+
licenses: []
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.8.21
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: check matched messages and emit alert message
|
86
|
+
test_files:
|
87
|
+
- test/helper.rb
|
88
|
+
- test/plugin/test_out_notifier.rb
|