fluent-plugin-nsca 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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +240 -0
- data/Rakefile +13 -0
- data/fluent-plugin-nsca.gemspec +26 -0
- data/lib/fluent/plugin/out_nsca.rb +177 -0
- data/test/helper.rb +36 -0
- data/test/plugin/test_out_nsca.rb +330 -0
- metadata +143 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2015- MIYAKAWA Taku
|
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,240 @@
|
|
1
|
+
# fluent-plugin-nsca
|
2
|
+
|
3
|
+
[Fluentd](http://fluentd.org) output plugin to send service checks to an
|
4
|
+
[NSCA](http://exchange.nagios.org/directory/Addons/Passive-Checks/NSCA--2D-Nagios-Service-Check-Acceptor/details)
|
5
|
+
/ [Nagios](http://www.nagios.org/) monitoring server.
|
6
|
+
|
7
|
+
The plugin sends a service check to the NSCA server for each record.
|
8
|
+
|
9
|
+
## Configuration
|
10
|
+
|
11
|
+
### Examples
|
12
|
+
|
13
|
+
```apache
|
14
|
+
<match ddos>
|
15
|
+
type nsca
|
16
|
+
|
17
|
+
# Connection settings
|
18
|
+
server monitor.example.com
|
19
|
+
port 5667
|
20
|
+
password aoxomoxoa
|
21
|
+
|
22
|
+
# Payload settings
|
23
|
+
|
24
|
+
## The monitored host name is "web.example.com"
|
25
|
+
host_name web.example.com
|
26
|
+
|
27
|
+
## The service is "ddos_detection"
|
28
|
+
service_description ddos_detection
|
29
|
+
|
30
|
+
## The return code is read from the field "severity"
|
31
|
+
return_code_field severity
|
32
|
+
|
33
|
+
## The plugin output is not specified;
|
34
|
+
## hence the plugin sends the JSON notation of the record.
|
35
|
+
|
36
|
+
</match>
|
37
|
+
```
|
38
|
+
|
39
|
+
### Plugin type
|
40
|
+
|
41
|
+
The type of this plugin is `nsca`.
|
42
|
+
Specify `type nsca` in the `match` section.
|
43
|
+
|
44
|
+
### Connection
|
45
|
+
|
46
|
+
* `server` (default is "localhost")
|
47
|
+
* The IP address or the hostname of the host running the NSCA daemon.
|
48
|
+
* `port` (default i 5667)
|
49
|
+
* The port on which the NSCA daemon is running.
|
50
|
+
* `password` (default is empty string)
|
51
|
+
* The password for authentication and encryption.
|
52
|
+
|
53
|
+
### Payload
|
54
|
+
|
55
|
+
A service check for the NSCA server
|
56
|
+
comprises the following four fields.
|
57
|
+
|
58
|
+
* Host name
|
59
|
+
* The name of the monitored host.
|
60
|
+
* The corresponding property in the Nagios configuration is
|
61
|
+
`host_name` property in a `host` definition.
|
62
|
+
* Service description
|
63
|
+
* The name of the monitored service.
|
64
|
+
* The corresponding property in the Nagios configuration is
|
65
|
+
`service_description` property in a `service` definition.
|
66
|
+
* Return code
|
67
|
+
* The severity of the service status.
|
68
|
+
* 0 (OK), 1 (WARNING), 2 (CRITICAL) or 3 (UNKNOWN).
|
69
|
+
* Plugin output
|
70
|
+
* A description of the service status.
|
71
|
+
|
72
|
+
The destination of checks
|
73
|
+
are identified by the pair of the host name and the service description.
|
74
|
+
|
75
|
+
#### Host name
|
76
|
+
|
77
|
+
The host name is determined as below.
|
78
|
+
|
79
|
+
1. The host name of the fluentd server (lowest priority)
|
80
|
+
2. `host_name` option
|
81
|
+
3. The field specified by `host_name_field` option (highest priority)
|
82
|
+
|
83
|
+
For example,
|
84
|
+
let the fluentd server have the host name "fluent",
|
85
|
+
and the configuration file contain the section below:
|
86
|
+
|
87
|
+
```apache
|
88
|
+
<match ddos>
|
89
|
+
type nsca
|
90
|
+
...snip...
|
91
|
+
host_name_field monitee
|
92
|
+
</match>
|
93
|
+
```
|
94
|
+
|
95
|
+
When the record `{"num" => 42, "monitee" => "web.example.org"}`
|
96
|
+
is input to the tag `ddos`,
|
97
|
+
the plugin sends a service check with the host name "web.example.org".
|
98
|
+
|
99
|
+
When the record `{"num" => 42}` is input to the tag `ddos`,
|
100
|
+
the plugin sends a service check with the host name "fluent"
|
101
|
+
(the host name of the fluentd server).
|
102
|
+
|
103
|
+
Be aware that if the host name exceeds 64 bytes, it will be truncated.
|
104
|
+
|
105
|
+
#### Service description
|
106
|
+
|
107
|
+
The service description is determined as below.
|
108
|
+
|
109
|
+
1. The tag name (lowest priority)
|
110
|
+
2. `service_description` option
|
111
|
+
3. The field specified by `service_description_field` option (highest priority)
|
112
|
+
|
113
|
+
For example,
|
114
|
+
let the configuration file contain the section below:
|
115
|
+
|
116
|
+
```apache
|
117
|
+
<match ddos>
|
118
|
+
type nsca
|
119
|
+
...snip...
|
120
|
+
service_description_field monitee_service
|
121
|
+
</match>
|
122
|
+
```
|
123
|
+
|
124
|
+
When the record
|
125
|
+
`{"num" => 42, "monitee_service" => "ddos_detection"}`
|
126
|
+
is input to the tag `ddos`,
|
127
|
+
the plugin sends a service check with the service description
|
128
|
+
"ddos\_detection".
|
129
|
+
|
130
|
+
When the record
|
131
|
+
`{"num" => 42}` is input to the tag `ddos`,
|
132
|
+
the plugin sends a service check with the service description
|
133
|
+
"ddos" (the tag name).
|
134
|
+
|
135
|
+
Be aware that if the service description exceeds 128 bytes,
|
136
|
+
it will be truncated.
|
137
|
+
|
138
|
+
#### Return code
|
139
|
+
|
140
|
+
The return code is determined as below.
|
141
|
+
|
142
|
+
1. 3 or UNKNOWN (lowest priority)
|
143
|
+
2. `return_code` option
|
144
|
+
* The permitted values are `0`, `1`, `2`, `3`,
|
145
|
+
and `OK`, `WARNING`, `CRITICAL`, `UNKNOWN`.
|
146
|
+
3. The field specified by `return_code_field` option (highest priority)
|
147
|
+
* The values permitted for the field are integers `0`, `1`, `2`, `3`
|
148
|
+
and strings `"0"`, `"1"`, `"2"`, `"3"`,
|
149
|
+
`"OK"`, `"WARNING"`, `"CRITICAL"`, `"UNKNOWN"`.
|
150
|
+
* If the field contains a value not permitted,
|
151
|
+
the plugin falls back to `return_code` if present, or to 3 (UNKNOWN).
|
152
|
+
|
153
|
+
For example,
|
154
|
+
let the configuration file contain the section below:
|
155
|
+
|
156
|
+
```apache
|
157
|
+
<match ddos>
|
158
|
+
type nsca
|
159
|
+
...snip...
|
160
|
+
return_code_field retcode
|
161
|
+
</match>
|
162
|
+
```
|
163
|
+
|
164
|
+
When the record
|
165
|
+
`{"num" => 42, "retcode" => "WARNING"}` is input to the tag `ddos`,
|
166
|
+
the plugin sends a service check with the return code `1`,
|
167
|
+
which means WARNING.
|
168
|
+
|
169
|
+
When the record
|
170
|
+
`{"num" => 42}` is input to the tag `ddos`,
|
171
|
+
the plugin sends a service check with the default return code `3`.
|
172
|
+
|
173
|
+
#### Plugin output
|
174
|
+
|
175
|
+
The plugin output is determined as below.
|
176
|
+
|
177
|
+
1. JSON notation of the record (lowest priority)
|
178
|
+
2. `plugin_output` option
|
179
|
+
3. The field specified by `plugin_output_field` option (highest priority)
|
180
|
+
|
181
|
+
For example,
|
182
|
+
let the configuration file contain the section below:
|
183
|
+
|
184
|
+
```apache
|
185
|
+
<match ddos>
|
186
|
+
type nsca
|
187
|
+
...snip...
|
188
|
+
plugin_output_field status
|
189
|
+
</match>
|
190
|
+
```
|
191
|
+
|
192
|
+
When the record
|
193
|
+
`{"num" => 42, "status" => "DDOS detected"}` is input to the tag `ddos`,
|
194
|
+
the plugin sends a service check with the plugin output "DDOS detected".
|
195
|
+
|
196
|
+
When the record
|
197
|
+
`{"num" => 42}` is input to the tag `ddos`,
|
198
|
+
the plugin sends a service check with the plugin output '{"num":42}'.
|
199
|
+
|
200
|
+
Be aware that if the plugin output exceeds 512 bytes,
|
201
|
+
it will be truncated.
|
202
|
+
|
203
|
+
### Buffering
|
204
|
+
|
205
|
+
The default value of `flush_interval` option is set to 1 second.
|
206
|
+
It means that checks are sent for every 1 second.
|
207
|
+
|
208
|
+
Except for `flush_interval`,
|
209
|
+
the plugin uses default options
|
210
|
+
for buffered output plugins (defined in Fluent::BufferedOutput class).
|
211
|
+
|
212
|
+
You can override buffering options in the configuration.
|
213
|
+
For example:
|
214
|
+
|
215
|
+
```apache
|
216
|
+
<match ddos>
|
217
|
+
type nsca
|
218
|
+
...snip...
|
219
|
+
buffer_type file
|
220
|
+
buffer_path /var/lib/td-agent/buffer/ddos
|
221
|
+
flush_interval 0.1
|
222
|
+
try_flush_interval 0.1
|
223
|
+
</match>
|
224
|
+
```
|
225
|
+
|
226
|
+
## Installation
|
227
|
+
|
228
|
+
If you are using td-agent, execute the command below.
|
229
|
+
|
230
|
+
$ sudo /usr/lib64/fluent/ruby/bin/fluent-gem fluent-plugin-nsca
|
231
|
+
|
232
|
+
Then add `match` section to your configuration file.
|
233
|
+
|
234
|
+
## Contributing
|
235
|
+
|
236
|
+
1. Fork it
|
237
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
238
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
239
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
240
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: et sw=2 sts=2
|
3
|
+
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
require 'rake/testtask'
|
6
|
+
|
7
|
+
Rake::TestTask.new(:test) do |test|
|
8
|
+
test.libs << 'lib' << 'test'
|
9
|
+
test.pattern = 'test/**/test_*.rb'
|
10
|
+
test.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :test
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fluent-plugin-nsca"
|
8
|
+
spec.version = '0.0.1'
|
9
|
+
spec.authors = ["MIYAKAWA Taku"]
|
10
|
+
spec.email = ["miyakawa.taku@gmail.com"]
|
11
|
+
spec.description = %q{Fluentd output plugin to send service checks to a Nagios NSCA daemon}
|
12
|
+
spec.summary = %q{Fluentd output plugin to send service checks to a Nagios NSCA daemon}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rr"
|
24
|
+
spec.add_runtime_dependency "send_nsca", "0.5.0"
|
25
|
+
spec.add_runtime_dependency "fluentd"
|
26
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: et sw=2 sts=2
|
3
|
+
|
4
|
+
module Fluent
|
5
|
+
class NscaOutput < Fluent::BufferedOutput
|
6
|
+
Fluent::Plugin.register_output('nsca', self)
|
7
|
+
|
8
|
+
# These max bytes are specified in the pack string in send_nsca library
|
9
|
+
MAX_HOST_NAME_BYTES = 64
|
10
|
+
MAX_SERVICE_DESCRIPTION_BYTES = 128
|
11
|
+
MAX_PLUGIN_OUTPUT_BYTES = 512
|
12
|
+
|
13
|
+
# The IP address or the hostname of the host running the NSCA daemon.
|
14
|
+
config_param :server, :string, :default => 'localhost'
|
15
|
+
|
16
|
+
# The port on which the NSCA daemon is running.
|
17
|
+
config_param :port, :integer, :default => 5667
|
18
|
+
|
19
|
+
# The password for authentication and encryption.
|
20
|
+
config_param :password, :string, :default => ''
|
21
|
+
|
22
|
+
# Host name options: default = the host name of the fluentd server
|
23
|
+
config_param :host_name, :string, :default => nil
|
24
|
+
config_param :host_name_field, :string, :default => nil
|
25
|
+
|
26
|
+
# Service description options: default=tag
|
27
|
+
config_param :service_description, :string, :default => nil
|
28
|
+
config_param :service_description_field, :string, :default => nil
|
29
|
+
|
30
|
+
# Return code options: default=3 (UNKNOWN)
|
31
|
+
config_param :return_code_field, :string, :default => nil
|
32
|
+
config_param(:return_code, :default => 3) { |return_code|
|
33
|
+
if not @@valid_return_codes.has_key?(return_code)
|
34
|
+
raise Fluent::ConfigError,
|
35
|
+
"invalid 'return_code': #{return_code}; 'return_code' must be" +
|
36
|
+
" 0, 1, 2, 3, OK, WARNING, CRITICAL, or UNKNOWN"
|
37
|
+
end
|
38
|
+
@@valid_return_codes[return_code]
|
39
|
+
}
|
40
|
+
@@valid_return_codes = {
|
41
|
+
0 => 0, 1 => 1, 2 => 2, 3 => 3,
|
42
|
+
'0' => 0, '1' => 1, '2' => 2, '3' => 3,
|
43
|
+
'OK' => 0, 'WARNING' => 1, 'CRITICAL' => 2, 'UNKNOWN' => 3
|
44
|
+
}
|
45
|
+
|
46
|
+
# Plugin output options: default = JSON notation of the record
|
47
|
+
config_param :plugin_output, :string, :default => nil
|
48
|
+
config_param :plugin_output_field, :string, :default => nil
|
49
|
+
|
50
|
+
# Overrides a buffering option
|
51
|
+
config_param :flush_interval, :time, :default => 1
|
52
|
+
|
53
|
+
private
|
54
|
+
def initialize
|
55
|
+
super
|
56
|
+
require 'send_nsca'
|
57
|
+
end
|
58
|
+
|
59
|
+
public
|
60
|
+
def configure(conf)
|
61
|
+
super
|
62
|
+
@host_name ||= Socket.gethostname
|
63
|
+
warn_if_host_name_exceeds_max_bytes(@host_name)
|
64
|
+
warn_if_service_description_exceeds_max_bytes(@service_description)
|
65
|
+
warn_if_plugin_output_exceeds_max_bytes(@plugin_output)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def warn_if_host_name_exceeds_max_bytes(host_name)
|
70
|
+
if host_name.bytesize > MAX_HOST_NAME_BYTES
|
71
|
+
log.warn("Host name exceeds the max bytes; it will be truncated",
|
72
|
+
:max_host_name_bytes => MAX_HOST_NAME_BYTES,
|
73
|
+
:host_name => host_name)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def warn_if_service_description_exceeds_max_bytes(service_description)
|
79
|
+
if service_description and
|
80
|
+
service_description.bytesize > MAX_SERVICE_DESCRIPTION_BYTES
|
81
|
+
log.warn(
|
82
|
+
"Service description exceeds the max bytes; it will be truncated.",
|
83
|
+
:max_service_description_bytes => MAX_SERVICE_DESCRIPTION_BYTES,
|
84
|
+
:service_description => service_description)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
def warn_if_plugin_output_exceeds_max_bytes(plugin_output)
|
90
|
+
if plugin_output and plugin_output.bytesize > MAX_PLUGIN_OUTPUT_BYTES
|
91
|
+
log.warn("Plugin output exceeds the max bytes; it will be truncated.",
|
92
|
+
:max_plugin_output_bytes => MAX_PLUGIN_OUTPUT_BYTES,
|
93
|
+
:plugin_output => plugin_output)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
public
|
98
|
+
def format(tag, time, record)
|
99
|
+
[tag, time, record].to_msgpack
|
100
|
+
end
|
101
|
+
|
102
|
+
public
|
103
|
+
def write(chunk)
|
104
|
+
results = []
|
105
|
+
chunk.msgpack_each { |(tag, time, record)|
|
106
|
+
nsca_check = SendNsca::NscaConnection.new({
|
107
|
+
:nscahost => @server,
|
108
|
+
:port => @port,
|
109
|
+
:password => @password,
|
110
|
+
:hostname => determine_host_name(record),
|
111
|
+
:service => determine_service_description(tag, record),
|
112
|
+
:return_code => determine_return_code(record),
|
113
|
+
:status => determine_plugin_output(record)
|
114
|
+
})
|
115
|
+
results.push(nsca_check.send_nsca)
|
116
|
+
}
|
117
|
+
|
118
|
+
# Returns the results of send_nsca for tests
|
119
|
+
return results
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
def determine_host_name(record)
|
124
|
+
if @host_name_field and record[@host_name_field]
|
125
|
+
host_name = record[@host_name_field].to_s
|
126
|
+
warn_if_host_name_exceeds_max_bytes(host_name)
|
127
|
+
return host_name
|
128
|
+
else
|
129
|
+
return @host_name
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
def determine_service_description(tag, record)
|
135
|
+
if @service_description_field and record[@service_description_field]
|
136
|
+
service_description = record[@service_description_field]
|
137
|
+
warn_if_service_description_exceeds_max_bytes(service_description)
|
138
|
+
return service_description
|
139
|
+
elsif @service_description
|
140
|
+
return @service_description
|
141
|
+
else
|
142
|
+
warn_if_service_description_exceeds_max_bytes(tag)
|
143
|
+
return tag
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
def determine_return_code(record)
|
149
|
+
if @return_code_field and record[@return_code_field]
|
150
|
+
return_code = @@valid_return_codes[record[@return_code_field]]
|
151
|
+
if return_code
|
152
|
+
return return_code
|
153
|
+
end
|
154
|
+
log.warn('Invalid return code.',
|
155
|
+
:return_code_field => @return_code_field,
|
156
|
+
:value => record[@return_code_field],
|
157
|
+
:fall_back_to => @return_code)
|
158
|
+
end
|
159
|
+
return @return_code
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
def determine_plugin_output(record)
|
164
|
+
if @plugin_output_field and record[@plugin_output_field]
|
165
|
+
plugin_output = record[@plugin_output_field]
|
166
|
+
warn_if_plugin_output_exceeds_max_bytes(plugin_output)
|
167
|
+
return plugin_output
|
168
|
+
elsif @plugin_output
|
169
|
+
return @plugin_output
|
170
|
+
else
|
171
|
+
plugin_output = record.to_json
|
172
|
+
warn_if_plugin_output_exceeds_max_bytes(plugin_output)
|
173
|
+
return plugin_output
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: et sw=2 sts=2
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
|
7
|
+
begin
|
8
|
+
Bundler.setup(:default, :development)
|
9
|
+
rescue Bundler::BundlerError => e
|
10
|
+
$stderr.puts e.message
|
11
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
12
|
+
exit e.status_code
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'test/unit'
|
16
|
+
require 'rr'
|
17
|
+
|
18
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
19
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
20
|
+
|
21
|
+
require 'fluent/test'
|
22
|
+
|
23
|
+
unless ENV.has_key?('VERBOSE')
|
24
|
+
nulllogger = Object.new
|
25
|
+
nulllogger.instance_eval {|obj|
|
26
|
+
def method_missing(method, *args)
|
27
|
+
# pass
|
28
|
+
end
|
29
|
+
}
|
30
|
+
$log = nulllogger
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'fluent/plugin/out_nsca'
|
34
|
+
|
35
|
+
class Test::Unit::TestCase
|
36
|
+
end
|
@@ -0,0 +1,330 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: et sw=2 sts=2
|
3
|
+
|
4
|
+
require 'helper'
|
5
|
+
require 'socket'
|
6
|
+
require 'send_nsca'
|
7
|
+
|
8
|
+
class NscaOutputTest < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
Fluent::Test.setup
|
11
|
+
stub.proxy(SendNsca::NscaConnection).new { |obj|
|
12
|
+
stub(obj).send_nsca {
|
13
|
+
obj.instance_eval {
|
14
|
+
[@nscahost, @port, @password, @hostname, @service, @return_code, @status]
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
CONFIG = %[
|
21
|
+
server monitor.example.com
|
22
|
+
port 4242
|
23
|
+
password aoxomoxoa
|
24
|
+
]
|
25
|
+
|
26
|
+
def create_driver(conf = CONFIG, tag='test')
|
27
|
+
Fluent::Test::BufferedOutputTestDriver.new(Fluent::NscaOutput, tag).configure(conf)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Connection settings are read
|
31
|
+
def test_connection_settings
|
32
|
+
driver = create_driver(CONFIG)
|
33
|
+
assert_equal 'monitor.example.com', driver.instance.instance_eval{ @server }
|
34
|
+
assert_equal 4242, driver.instance.instance_eval{ @port }
|
35
|
+
assert_equal 'aoxomoxoa', driver.instance.instance_eval{ @password }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Default values are set to connection values
|
39
|
+
def test_default_connection_settings
|
40
|
+
driver = create_driver('')
|
41
|
+
assert_equal 'localhost', driver.instance.instance_eval{ @server }
|
42
|
+
assert_equal 5667, driver.instance.instance_eval{ @port }
|
43
|
+
assert_equal '', driver.instance.instance_eval{ @password }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Rejects invalid return codes
|
47
|
+
def test_reject_invalid_return_codes
|
48
|
+
config = %[
|
49
|
+
#{CONFIG}
|
50
|
+
return_code invalid_return_code
|
51
|
+
]
|
52
|
+
message = "invalid 'return_code': invalid_return_code;" +
|
53
|
+
" 'return_code' must be 0, 1, 2, 3," +
|
54
|
+
" OK, WARNING, CRITICAL, or UNKNOWN"
|
55
|
+
assert_raise(Fluent::ConfigError, message) {
|
56
|
+
create_driver(config)
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# flush_interval is set to 1
|
61
|
+
def test_flush_interval
|
62
|
+
driver = create_driver('')
|
63
|
+
assert_equal 1, driver.instance.instance_eval { @flush_interval }
|
64
|
+
end
|
65
|
+
|
66
|
+
# Format to MessagePack(tag, time, record)
|
67
|
+
def test_format
|
68
|
+
driver = create_driver('', 'ddos')
|
69
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
70
|
+
driver.emit({"name" => "Stephen"}, time)
|
71
|
+
driver.emit({"name" => "Aggi"}, time)
|
72
|
+
driver.expect_format(['ddos', time, {"name" => "Stephen"}].to_msgpack)
|
73
|
+
driver.expect_format(['ddos', time, {"name" => "Aggi"}].to_msgpack)
|
74
|
+
driver.run
|
75
|
+
end
|
76
|
+
|
77
|
+
# Sends a service check with constant values
|
78
|
+
def test_write_constant_values
|
79
|
+
config = %[
|
80
|
+
#{CONFIG}
|
81
|
+
host_name web.example.org
|
82
|
+
service_description ddos_monitor
|
83
|
+
return_code 2
|
84
|
+
plugin_output possible attacks
|
85
|
+
]
|
86
|
+
driver = create_driver(config, 'ddos')
|
87
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
88
|
+
driver.emit({"name" => "Stephen"}, time)
|
89
|
+
output = driver.run
|
90
|
+
assert_equal [['monitor.example.com', 4242, 'aoxomoxoa', 'web.example.org', 'ddos_monitor', 2, 'possible attacks']], output
|
91
|
+
end
|
92
|
+
|
93
|
+
# Sends a service check with host_name and host_name_field
|
94
|
+
def test_write_check_with_host_name_and_host_name_field
|
95
|
+
config = %[
|
96
|
+
#{CONFIG}
|
97
|
+
host_name_field host
|
98
|
+
host_name fallback.example.org
|
99
|
+
|
100
|
+
service_description ddos_monitor
|
101
|
+
return_code 2
|
102
|
+
plugin_output possible attacks
|
103
|
+
]
|
104
|
+
driver = create_driver(config, 'ddos')
|
105
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
106
|
+
driver.emit({"name" => "Stephen", "host" => "app.example.org"}, time)
|
107
|
+
driver.emit({"name" => "Aggi"}, time)
|
108
|
+
output = driver.run
|
109
|
+
expected_first = [
|
110
|
+
'monitor.example.com', 4242, 'aoxomoxoa', 'app.example.org', 'ddos_monitor', 2, 'possible attacks'
|
111
|
+
]
|
112
|
+
expected_second = [
|
113
|
+
'monitor.example.com', 4242, 'aoxomoxoa', 'fallback.example.org', 'ddos_monitor', 2, 'possible attacks'
|
114
|
+
]
|
115
|
+
assert_equal [expected_first, expected_second], output
|
116
|
+
end
|
117
|
+
|
118
|
+
# Sends a service check with host_name_field
|
119
|
+
def test_write_check_with_host_name_field
|
120
|
+
config = %[
|
121
|
+
#{CONFIG}
|
122
|
+
host_name_field host
|
123
|
+
|
124
|
+
service_description ddos_monitor
|
125
|
+
return_code 2
|
126
|
+
plugin_output possible attacks
|
127
|
+
]
|
128
|
+
driver = create_driver(config, 'ddos')
|
129
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
130
|
+
driver.emit({"name" => "Stephen", "host" => "app.example.org"}, time)
|
131
|
+
driver.emit({"name" => "Aggi"}, time)
|
132
|
+
output = driver.run
|
133
|
+
expected_first = [
|
134
|
+
'monitor.example.com', 4242, 'aoxomoxoa', 'app.example.org', 'ddos_monitor', 2, 'possible attacks'
|
135
|
+
]
|
136
|
+
expected_second = [
|
137
|
+
'monitor.example.com', 4242, 'aoxomoxoa', Socket.gethostname, 'ddos_monitor', 2, 'possible attacks'
|
138
|
+
]
|
139
|
+
assert_equal [expected_first, expected_second], output
|
140
|
+
end
|
141
|
+
|
142
|
+
# Sends a service check with service_description and service_description_field
|
143
|
+
def test_write_check_with_service_description_and_service_description_field
|
144
|
+
config = %[
|
145
|
+
#{CONFIG}
|
146
|
+
service_description ddos_detection
|
147
|
+
service_description_field service
|
148
|
+
|
149
|
+
host_name web.example.org
|
150
|
+
return_code 2
|
151
|
+
plugin_output possible attacks
|
152
|
+
]
|
153
|
+
driver = create_driver(config, 'ddos')
|
154
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
155
|
+
driver.emit({"name" => "Stephen", "service" => "possible_ddos"})
|
156
|
+
driver.emit({"name" => "Aggi"})
|
157
|
+
output = driver.run
|
158
|
+
expected_first = [
|
159
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
160
|
+
'web.example.org', 'possible_ddos', 2, 'possible attacks'
|
161
|
+
]
|
162
|
+
expected_second = [
|
163
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
164
|
+
'web.example.org', 'ddos_detection', 2, 'possible attacks'
|
165
|
+
]
|
166
|
+
assert_equal [expected_first, expected_second], output
|
167
|
+
end
|
168
|
+
|
169
|
+
# Sends a service check with service_description_field
|
170
|
+
def test_write_check_with_service_description_field
|
171
|
+
config = %[
|
172
|
+
#{CONFIG}
|
173
|
+
service_description_field service
|
174
|
+
|
175
|
+
host_name web.example.org
|
176
|
+
return_code 2
|
177
|
+
plugin_output possible attacks
|
178
|
+
]
|
179
|
+
driver = create_driver(config, 'ddos')
|
180
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
181
|
+
driver.emit({"name" => "Stephen", "service" => "possible_ddos"})
|
182
|
+
driver.emit({"name" => "Aggi"})
|
183
|
+
output = driver.run
|
184
|
+
expected_first = [
|
185
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
186
|
+
'web.example.org', 'possible_ddos', 2, 'possible attacks'
|
187
|
+
]
|
188
|
+
expected_second = [
|
189
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
190
|
+
'web.example.org', 'ddos', 2, 'possible attacks'
|
191
|
+
]
|
192
|
+
assert_equal [expected_first, expected_second], output
|
193
|
+
end
|
194
|
+
|
195
|
+
# Sends a service check with return_code and return_code_field
|
196
|
+
def test_write_check_with_return_code_and_return_code_field
|
197
|
+
config = %[
|
198
|
+
#{CONFIG}
|
199
|
+
return_code OK
|
200
|
+
return_code_field retcode
|
201
|
+
|
202
|
+
host_name web.example.org
|
203
|
+
service_description ddos_monitor
|
204
|
+
plugin_output possible attacks
|
205
|
+
]
|
206
|
+
driver = create_driver(config, 'ddos')
|
207
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
208
|
+
driver.emit({"name" => "Stephen", "retcode" => "UNKNOWN"})
|
209
|
+
driver.emit({"name" => "Aggi", "retcode" => "2"})
|
210
|
+
driver.emit({"name" => "Katrina", "retcode" => 1})
|
211
|
+
driver.emit({"name" => "Brian", "retcode" => "invalid-value"})
|
212
|
+
driver.emit({"name" => "Martin"})
|
213
|
+
output = driver.run
|
214
|
+
expected1 = [
|
215
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
216
|
+
'web.example.org', 'ddos_monitor', 3, 'possible attacks'
|
217
|
+
]
|
218
|
+
expected2 = [
|
219
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
220
|
+
'web.example.org', 'ddos_monitor', 2, 'possible attacks'
|
221
|
+
]
|
222
|
+
expected3 = [
|
223
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
224
|
+
'web.example.org', 'ddos_monitor', 1, 'possible attacks'
|
225
|
+
]
|
226
|
+
expected4 = [
|
227
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
228
|
+
'web.example.org', 'ddos_monitor', 0, 'possible attacks'
|
229
|
+
]
|
230
|
+
expected5 = [
|
231
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
232
|
+
'web.example.org', 'ddos_monitor', 0, 'possible attacks'
|
233
|
+
]
|
234
|
+
assert_equal [expected1, expected2, expected3, expected4, expected5], output
|
235
|
+
end
|
236
|
+
|
237
|
+
# Sends a service check with return_code_field
|
238
|
+
def test_write_check_with_return_code_field
|
239
|
+
config = %[
|
240
|
+
#{CONFIG}
|
241
|
+
return_code_field retcode
|
242
|
+
|
243
|
+
host_name web.example.org
|
244
|
+
service_description ddos_monitor
|
245
|
+
plugin_output possible attacks
|
246
|
+
]
|
247
|
+
driver = create_driver(config, 'ddos')
|
248
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
249
|
+
driver.emit({"name" => "Stephen", "retcode" => "OK"})
|
250
|
+
driver.emit({"name" => "Aggi", "retcode" => "1"})
|
251
|
+
driver.emit({"name" => "Katrina", "retcode" => 2})
|
252
|
+
driver.emit({"name" => "Brian", "retcode" => "invalid-value"})
|
253
|
+
driver.emit({"name" => "Martin"})
|
254
|
+
output = driver.run
|
255
|
+
expected1 = [
|
256
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
257
|
+
'web.example.org', 'ddos_monitor', 0, 'possible attacks'
|
258
|
+
]
|
259
|
+
expected2 = [
|
260
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
261
|
+
'web.example.org', 'ddos_monitor', 1, 'possible attacks'
|
262
|
+
]
|
263
|
+
expected3 = [
|
264
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
265
|
+
'web.example.org', 'ddos_monitor', 2, 'possible attacks'
|
266
|
+
]
|
267
|
+
expected4 = [
|
268
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
269
|
+
'web.example.org', 'ddos_monitor', 3, 'possible attacks'
|
270
|
+
]
|
271
|
+
expected5 = [
|
272
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
273
|
+
'web.example.org', 'ddos_monitor', 3, 'possible attacks'
|
274
|
+
]
|
275
|
+
assert_equal [expected1, expected2, expected3, expected4, expected5], output
|
276
|
+
end
|
277
|
+
|
278
|
+
# Sends a service check with plugin_output and plugin_output_field
|
279
|
+
def test_write_check_with_plugin_output_and_plugin_output_field
|
280
|
+
config = %[
|
281
|
+
#{CONFIG}
|
282
|
+
plugin_output DDOS detected
|
283
|
+
plugin_output_field status
|
284
|
+
|
285
|
+
host_name web.example.org
|
286
|
+
service_description ddos_monitor
|
287
|
+
return_code 2
|
288
|
+
]
|
289
|
+
driver = create_driver(config, 'ddos')
|
290
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
291
|
+
driver.emit({"name" => "Stephen", "status" => "Possible DDOS detected"})
|
292
|
+
driver.emit({"name" => "Aggi"})
|
293
|
+
output = driver.run
|
294
|
+
expected1 = [
|
295
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
296
|
+
'web.example.org', 'ddos_monitor', 2, 'Possible DDOS detected'
|
297
|
+
]
|
298
|
+
expected2 = [
|
299
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
300
|
+
'web.example.org', 'ddos_monitor', 2, 'DDOS detected'
|
301
|
+
]
|
302
|
+
assert_equal [expected1, expected2], output
|
303
|
+
end
|
304
|
+
|
305
|
+
# Sends a service check with plugin_output_field
|
306
|
+
def test_write_check_with_plugin_output_field
|
307
|
+
config = %[
|
308
|
+
#{CONFIG}
|
309
|
+
plugin_output_field status
|
310
|
+
|
311
|
+
host_name web.example.org
|
312
|
+
service_description ddos_monitor
|
313
|
+
return_code 2
|
314
|
+
]
|
315
|
+
driver = create_driver(config, 'ddos')
|
316
|
+
time = Time.parse('2015-01-03 12:34:56 UTC').to_i
|
317
|
+
driver.emit({"name" => "Stephen", "status" => "Possible DDOS detected"})
|
318
|
+
driver.emit({"name" => "Aggi"})
|
319
|
+
output = driver.run
|
320
|
+
expected1 = [
|
321
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
322
|
+
'web.example.org', 'ddos_monitor', 2, 'Possible DDOS detected'
|
323
|
+
]
|
324
|
+
expected2 = [
|
325
|
+
'monitor.example.com', 4242, 'aoxomoxoa',
|
326
|
+
'web.example.org', 'ddos_monitor', 2, '{"name":"Aggi"}'
|
327
|
+
]
|
328
|
+
assert_equal [expected1, expected2], output
|
329
|
+
end
|
330
|
+
end
|
metadata
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-nsca
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- MIYAKAWA Taku
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-02-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
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: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
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
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rr
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: send_nsca
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - '='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.5.0
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.5.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: fluentd
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Fluentd output plugin to send service checks to a Nagios NSCA daemon
|
95
|
+
email:
|
96
|
+
- miyakawa.taku@gmail.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- Gemfile
|
103
|
+
- LICENSE.txt
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- fluent-plugin-nsca.gemspec
|
107
|
+
- lib/fluent/plugin/out_nsca.rb
|
108
|
+
- test/helper.rb
|
109
|
+
- test/plugin/test_out_nsca.rb
|
110
|
+
homepage: ''
|
111
|
+
licenses:
|
112
|
+
- MIT
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
hash: -559361203854015159
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
segments:
|
133
|
+
- 0
|
134
|
+
hash: -559361203854015159
|
135
|
+
requirements: []
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 1.8.23
|
138
|
+
signing_key:
|
139
|
+
specification_version: 3
|
140
|
+
summary: Fluentd output plugin to send service checks to a Nagios NSCA daemon
|
141
|
+
test_files:
|
142
|
+
- test/helper.rb
|
143
|
+
- test/plugin/test_out_nsca.rb
|