fluent-plugin-nsca 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.
data/README.md CHANGED
@@ -8,7 +8,7 @@ The plugin sends a service check to the NSCA server for each record.
8
8
 
9
9
  ## Configuration
10
10
 
11
- ### Examples
11
+ ### Example configuration
12
12
 
13
13
  ```apache
14
14
  <match ddos>
@@ -27,8 +27,8 @@ The plugin sends a service check to the NSCA server for each record.
27
27
  ## The service is "ddos_detection"
28
28
  service_description ddos_detection
29
29
 
30
- ## The return code is read from the field "severity"
31
- return_code_field severity
30
+ ## The return code is read from the field "level"
31
+ return_code_field level
32
32
 
33
33
  ## The plugin output is not specified;
34
34
  ## hence the plugin sends the JSON notation of the record.
@@ -41,16 +41,16 @@ The plugin sends a service check to the NSCA server for each record.
41
41
  The type of this plugin is `nsca`.
42
42
  Specify `type nsca` in the `match` section.
43
43
 
44
- ### Connection
44
+ ### Connection setting
45
45
 
46
46
  * `server` (default is "localhost")
47
47
  * The IP address or the hostname of the host running the NSCA daemon.
48
- * `port` (default i 5667)
48
+ * `port` (default is 5667)
49
49
  * The port on which the NSCA daemon is running.
50
- * `password` (default is empty string)
50
+ * `password` (default is an empty string)
51
51
  * The password for authentication and encryption.
52
52
 
53
- ### Payload
53
+ ### Check payload
54
54
 
55
55
  A service check for the NSCA server
56
56
  comprises the following four fields.
@@ -59,15 +59,18 @@ comprises the following four fields.
59
59
  * The name of the monitored host.
60
60
  * The corresponding property in the Nagios configuration is
61
61
  `host_name` property in a `host` definition.
62
+ * Limited to the maximum 64 bytes.
62
63
  * Service description
63
64
  * The name of the monitored service.
64
65
  * The corresponding property in the Nagios configuration is
65
66
  `service_description` property in a `service` definition.
67
+ * Limited to the maximum 128 bytes.
66
68
  * Return code
67
- * The severity of the service status.
69
+ * The severity level of the service status.
68
70
  * 0 (OK), 1 (WARNING), 2 (CRITICAL) or 3 (UNKNOWN).
69
71
  * Plugin output
70
72
  * A description of the service status.
73
+ * Limited to the maximum 512 bytes.
71
74
 
72
75
  The destination of checks
73
76
  are identified by the pair of the host name and the service description.
@@ -76,13 +79,17 @@ are identified by the pair of the host name and the service description.
76
79
 
77
80
  The host name is determined as below.
78
81
 
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
+ 1. The field specified by `host_name_field` option,
83
+ if present (highest priority)
84
+ * If the value exceeds the maximum 64 bytes, it will be truncated.
85
+ 2. or `host_name` option, if present
86
+ * If the value exceeds the maximum 64 bytes, it causes a config error.
87
+ 3. or the host name of the fluentd server (lowest priority)
88
+ * If the value exceeds the maximum 64 bytes, it causes a config error.
82
89
 
83
90
  For example,
84
- let the fluentd server have the host name "fluent",
85
- and the configuration file contain the section below:
91
+ assume that the fluentd server has the host name "fluent",
92
+ and the configuration file contains the section below:
86
93
 
87
94
  ```apache
88
95
  <match ddos>
@@ -100,18 +107,20 @@ When the record `{"num" => 42}` is input to the tag `ddos`,
100
107
  the plugin sends a service check with the host name "fluent"
101
108
  (the host name of the fluentd server).
102
109
 
103
- Be aware that if the host name exceeds 64 bytes, it will be truncated.
104
-
105
110
  #### Service description
106
111
 
107
112
  The service description is determined as below.
108
113
 
109
- 1. The tag name (lowest priority)
110
- 2. `service_description` option
111
- 3. The field specified by `service_description_field` option (highest priority)
114
+ 1. The field specified by `service_description_field` option,
115
+ if present (highest priority)
116
+ * If the value exceeds the maximum 128 bytes, it will be truncated.
117
+ 2. or `service_description` option, if present
118
+ * If the value exceeds the maximum 128 bytes, it causes a config error.
119
+ 3. or the tag name (lowest priority)
120
+ * If the value exceeds the maximum 128 bytes, it will be truncated.
112
121
 
113
122
  For example,
114
- let the configuration file contain the section below:
123
+ assume that the configuration file contains the section below:
115
124
 
116
125
  ```apache
117
126
  <match ddos>
@@ -132,54 +141,59 @@ When the record
132
141
  the plugin sends a service check with the service description
133
142
  "ddos" (the tag name).
134
143
 
135
- Be aware that if the service description exceeds 128 bytes,
136
- it will be truncated.
137
-
138
144
  #### Return code
139
145
 
140
146
  The return code is determined as below.
141
147
 
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)
148
+ 1. The field specified by `return_code_field` option,
149
+ if present (highest priority)
147
150
  * The values permitted for the field are integers `0`, `1`, `2`, `3`
148
151
  and strings `"0"`, `"1"`, `"2"`, `"3"`,
149
152
  `"OK"`, `"WARNING"`, `"CRITICAL"`, `"UNKNOWN"`.
150
153
  * If the field contains a value not permitted,
151
- the plugin falls back to `return_code` if present, or to 3 (UNKNOWN).
154
+ the plugin falls back to `return_code` option if present,
155
+ or to `3` (UNKNOWN).
156
+ 2. or `return_code` option, if present
157
+ * The permitted values are `0`, `1`, `2`, `3`,
158
+ and `OK`, `WARNING`, `CRITICAL`, `UNKNOWN`.
159
+ * If the value is invalid, it causes a config error.
160
+ 3. or `3`, which means UNKNOWN (lowest priority)
152
161
 
153
162
  For example,
154
- let the configuration file contain the section below:
163
+ assume that the configuration file contains the section below:
155
164
 
156
165
  ```apache
157
166
  <match ddos>
158
167
  type nsca
159
168
  ...snip...
160
- return_code_field retcode
169
+ return_code_field level
161
170
  </match>
162
171
  ```
163
172
 
164
173
  When the record
165
- `{"num" => 42, "retcode" => "WARNING"}` is input to the tag `ddos`,
174
+ `{"num" => 42, "level" => "WARNING"}` is input to the tag `ddos`,
166
175
  the plugin sends a service check with the return code `1`,
167
176
  which means WARNING.
168
177
 
169
178
  When the record
170
179
  `{"num" => 42}` is input to the tag `ddos`,
171
- the plugin sends a service check with the default return code `3`.
180
+ the plugin sends a service check with the default return code `3`,
181
+ which means UNKNOWN.
172
182
 
173
183
  #### Plugin output
174
184
 
175
185
  The plugin output is determined as below.
176
186
 
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)
187
+ 1. The field specified by `plugin_output_field` option,
188
+ if present (highest priority)
189
+ * If the value exceeds the maximum 512 bytes, it will be truncated.
190
+ 2. or `plugin_output` option
191
+ * If the value exceeds the maximum 512 bytes, it causes a config error.
192
+ 3. or JSON notation of the record (lowest priority)
193
+ * If the value exceeds the maximum 512 bytes, it will be truncated.
180
194
 
181
195
  For example,
182
- let the configuration file contain the section below:
196
+ assume that the configuration file contains the section below:
183
197
 
184
198
  ```apache
185
199
  <match ddos>
@@ -197,13 +211,11 @@ When the record
197
211
  `{"num" => 42}` is input to the tag `ddos`,
198
212
  the plugin sends a service check with the plugin output '{"num":42}'.
199
213
 
200
- Be aware that if the plugin output exceeds 512 bytes,
201
- it will be truncated.
202
-
203
214
  ### Buffering
204
215
 
205
216
  The default value of `flush_interval` option is set to 1 second.
206
- It means that checks are sent for every 1 second.
217
+ It means that service checks are delayed at most 1 second
218
+ before being sent.
207
219
 
208
220
  Except for `flush_interval`,
209
221
  the plugin uses default options
@@ -223,6 +235,113 @@ For example:
223
235
  </match>
224
236
  ```
225
237
 
238
+ ## Use case: "too many server errors" alert
239
+
240
+ ### Situation
241
+
242
+ You have
243
+
244
+ * "web" server (192.168.42.123) which runs Apache HTTP Server and Fluentd, and
245
+ * "monitor" server (192.168.42.210) which runs Nagios and NSCA.
246
+
247
+ You want to be notified when Apache responds too many server errors,
248
+ for example 5 errors per minute as WARNING,
249
+ and 50 errors per minute as CRITICAL.
250
+
251
+ ### Nagios configuration on "monitor" server
252
+
253
+ Create web.cfg file shown as below,
254
+ under the Nagios configuration direcotry.
255
+
256
+ ```
257
+ # File: web.cfg
258
+
259
+ # "web" server definition
260
+ define host {
261
+ use generic-host
262
+ host_name web
263
+ alias web
264
+ address 192.168.42.123
265
+ }
266
+
267
+ # Server errors service definition
268
+ define service {
269
+ use generic-service
270
+ name server_errors
271
+ active_checks_enabled 0
272
+ passive_checks_enabled 1
273
+ flap_detection_enabled 0
274
+ max_check_attempts 1
275
+ check_command check_dummy!0
276
+ }
277
+
278
+ # Delete this section if check_dummy command is defined elsewhere
279
+ define command {
280
+ command_name check_dummy
281
+ command_line $USER1$/check_dummy $ARG1$
282
+ }
283
+ ```
284
+
285
+ ### Fluentd configuration on "web" server
286
+
287
+ This setting utilizes [fluent-plugin-datacounter](
288
+ https://github.com/tagomoris/fluent-plugin-datacounter),
289
+ [fluent-plugin-record-reformer](
290
+ https://github.com/sonots/fluent-plugin-record-reformer),
291
+ and of course `fluent-plugin-nsca`.
292
+ So, first of all, install those gems.
293
+
294
+ Next, add these lines to the Fluentd configuration file.
295
+
296
+ ```apache
297
+ # Parse Apache access log
298
+ <source>
299
+ type tail
300
+ tag access
301
+ format apache2
302
+
303
+ # The paths vary by setup
304
+ path /var/log/httpd/access_log
305
+ pos_file /var/log/fluentd/httpd-access_log.pos
306
+ </source>
307
+
308
+ # Count 5xx errors per minute
309
+ <match access>
310
+ type datacounter
311
+ tag count.access
312
+ unit minute
313
+ aggregate all
314
+ count_key code
315
+ pattern1 error ^5\d\d$
316
+ </match>
317
+
318
+ # Calculate the severity level
319
+ <match count.access>
320
+ type record_reformer
321
+ tag server_errors
322
+ enable_ruby true
323
+ <record>
324
+ level ${error_count < 5 ? 'OK' : error_count < 50 ? 'WARNING' : 'CRITICAL'}
325
+ </record>
326
+ </match>
327
+
328
+ # Send checks to NSCA
329
+ <match server_errors>
330
+ type nsca
331
+ server 192.168.42.210
332
+ port 5667
333
+ # Empty password!
334
+
335
+ host_name web
336
+ service_description server_errors
337
+ return_code_field level
338
+ </match>
339
+ ```
340
+
341
+ You can use `record_transformer` filter
342
+ instead of `fluent-plugin-record-reformer`
343
+ on Fluentd 0.12.0 and above.
344
+
226
345
  ## Installation
227
346
 
228
347
  1. Install fluent-plugin-nsca gem from rubygems.org.
@@ -230,6 +349,13 @@ For example:
230
349
 
231
350
  ## Contributing
232
351
 
352
+ Create an [issue](https://github.com/miyakawataku/fluent-plugin-nsca/issues).
353
+
354
+ Or ask questions on Twitter to
355
+ [@miyakawa\_taku](https://twitter.com/miyakawa_taku).
356
+
357
+ Or submit a pull request as follows:
358
+
233
359
  1. Fork it
234
360
  2. Create your feature branch (`git checkout -b my-new-feature`)
235
361
  3. Commit your changes (`git commit -am 'Add some feature'`)
@@ -5,12 +5,13 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "fluent-plugin-nsca"
8
- spec.version = '0.0.3'
8
+ spec.version = '0.0.4'
9
9
  spec.authors = ["MIYAKAWA Taku"]
10
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 = "https://github.com/miyakawataku/fluent-plugin-nsca/"
11
+ spec.description = 'Fluentd output plugin to send service checks' +
12
+ ' to an NSCA / Nagios monitoring server'
13
+ spec.summary = spec.description
14
+ spec.homepage = "https://github.com/miyakawataku/fluent-plugin-nsca"
14
15
  spec.license = "Apache License, v2.0"
15
16
 
16
17
  spec.files = `git ls-files`.split($/)
@@ -2,14 +2,61 @@
2
2
  # vim: et sw=2 sts=2
3
3
 
4
4
  module Fluent
5
+
6
+ # Fluentd output plugin to send service checks
7
+ # to an NSCA / Nagios monitoring servers.
5
8
  class NscaOutput < Fluent::BufferedOutput
6
9
  Fluent::Plugin.register_output('nsca', self)
7
10
 
8
- # These max bytes are specified in the pack string in send_nsca library
11
+ #
12
+ # Maximum bytes specified in the pack string in send_nsca library
13
+ #
14
+
15
+ # The maximum bytes for host names.
9
16
  MAX_HOST_NAME_BYTES = 64
17
+
18
+ # The maximum bytes for service descriptions.
10
19
  MAX_SERVICE_DESCRIPTION_BYTES = 128
20
+
21
+ # The maximum bytes for plugin outputs.
11
22
  MAX_PLUGIN_OUTPUT_BYTES = 512
12
23
 
24
+ #
25
+ # Return codes
26
+ #
27
+
28
+ # OK return code (0).
29
+ OK = 0
30
+
31
+ # WARNING return code (1).
32
+ WARNING = 1
33
+
34
+ # CRITICAL return code (2).
35
+ CRITICAL = 2
36
+
37
+ # UNKNOWN return code (3).
38
+ UNKNOWN = 3
39
+
40
+ # Mapping from the permitted return code representations
41
+ # to the normalized return codes.
42
+ VALID_RETURN_CODES = {
43
+ # OK
44
+ OK => OK, OK.to_s => OK, 'OK' => OK,
45
+
46
+ # WARNING
47
+ WARNING => WARNING, WARNING.to_s => WARNING, 'WARNING' => WARNING,
48
+
49
+ # CRITICAL
50
+ CRITICAL => CRITICAL, CRITICAL.to_s => CRITICAL, 'CRITICAL' => CRITICAL,
51
+
52
+ # UNKNOWN
53
+ UNKNOWN => UNKNOWN, UNKNOWN.to_s => UNKNOWN, 'UNKNOWN' => UNKNOWN
54
+ }
55
+
56
+ #
57
+ # Config parameters
58
+ #
59
+
13
60
  # The IP address or the hostname of the host running the NSCA daemon.
14
61
  config_param :server, :string, :default => 'localhost'
15
62
 
@@ -19,86 +66,85 @@ module Fluent
19
66
  # The password for authentication and encryption.
20
67
  config_param :password, :string, :default => ''
21
68
 
22
- # Host name options: default = the host name of the fluentd server
69
+ # Host name options: default = the host name of the fluentd server.
23
70
  config_param :host_name, :string, :default => nil
24
71
  config_param :host_name_field, :string, :default => nil
25
72
 
26
- # Service description options: default=tag
73
+ # Service description options: default=tag.
27
74
  config_param :service_description, :string, :default => nil
28
75
  config_param :service_description_field, :string, :default => nil
29
76
 
30
- # Return code options: default=3 (UNKNOWN)
77
+ # Return code options: default=UNKNOWN.
31
78
  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)
79
+ config_param(:return_code, :default => UNKNOWN) { |return_code|
80
+ if not VALID_RETURN_CODES.has_key?(return_code)
34
81
  raise Fluent::ConfigError,
35
82
  "invalid 'return_code': #{return_code}; 'return_code' must be" +
36
83
  " 0, 1, 2, 3, OK, WARNING, CRITICAL, or UNKNOWN"
37
84
  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
85
+ VALID_RETURN_CODES[return_code]
44
86
  }
45
87
 
46
- # Plugin output options: default = JSON notation of the record
88
+ # Plugin output options: default = JSON notation of the record.
47
89
  config_param :plugin_output, :string, :default => nil
48
90
  config_param :plugin_output_field, :string, :default => nil
49
91
 
50
- # Overrides a buffering option
92
+ # Overrides a buffering option.
51
93
  config_param :flush_interval, :time, :default => 1
52
94
 
95
+ # Load SendNsca module.
53
96
  private
54
97
  def initialize
55
98
  super
99
+ require 'socket'
56
100
  require 'send_nsca'
57
101
  end
58
102
 
103
+ # Read and validate the configuration.
59
104
  public
60
105
  def configure(conf)
61
106
  super
62
107
  @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)
108
+ reject_host_name_option_exceeding_max_bytes
109
+ reject_service_description_option_exceeding_max_bytes
110
+ reject_plugin_output_option_exceeding_max_bytes
66
111
  end
67
112
 
113
+ # Reject host_name option exceeding the max bytes.
68
114
  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)
115
+ def reject_host_name_option_exceeding_max_bytes
116
+ if host_name_exceeds_max_bytes?(@host_name)
117
+ raise ConfigError,
118
+ "host_name must not exceed #{MAX_HOST_NAME_BYTES} bytes"
74
119
  end
75
120
  end
76
121
 
122
+ # Reject service_description option exceeding the max bytes.
77
123
  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)
124
+ def reject_service_description_option_exceeding_max_bytes
125
+ if service_description_exceeds_max_bytes?(@service_description)
126
+ raise ConfigError,
127
+ "service_description must not exceed" +
128
+ " #{MAX_SERVICE_DESCRIPTION_BYTES} bytes"
85
129
  end
86
130
  end
87
131
 
132
+ # Reject plugin_output option exceeding the max bytes.
88
133
  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)
134
+ def reject_plugin_output_option_exceeding_max_bytes
135
+ if plugin_output_exceeds_max_bytes?(@plugin_output)
136
+ raise ConfigError,
137
+ "plugin_output must not exceed #{MAX_PLUGIN_OUTPUT_BYTES} bytes"
94
138
  end
95
139
  end
96
140
 
141
+ # Pack the tuple (tag, time, record).
97
142
  public
98
143
  def format(tag, time, record)
99
144
  [tag, time, record].to_msgpack
100
145
  end
101
146
 
147
+ # Send a service check.
102
148
  public
103
149
  def write(chunk)
104
150
  results = []
@@ -119,6 +165,7 @@ module Fluent
119
165
  return results
120
166
  end
121
167
 
168
+ # Determines the host name.
122
169
  private
123
170
  def determine_host_name(record)
124
171
  if @host_name_field and record[@host_name_field]
@@ -130,6 +177,7 @@ module Fluent
130
177
  end
131
178
  end
132
179
 
180
+ # Determines the service description.
133
181
  private
134
182
  def determine_service_description(tag, record)
135
183
  if @service_description_field and record[@service_description_field]
@@ -144,10 +192,11 @@ module Fluent
144
192
  end
145
193
  end
146
194
 
195
+ # Determines the return code.
147
196
  private
148
197
  def determine_return_code(record)
149
198
  if @return_code_field and record[@return_code_field]
150
- return_code = @@valid_return_codes[record[@return_code_field]]
199
+ return_code = VALID_RETURN_CODES[record[@return_code_field]]
151
200
  if return_code
152
201
  return return_code
153
202
  end
@@ -159,6 +208,7 @@ module Fluent
159
208
  return @return_code
160
209
  end
161
210
 
211
+ # Determines the plugin output.
162
212
  private
163
213
  def determine_plugin_output(record)
164
214
  if @plugin_output_field and record[@plugin_output_field]
@@ -173,5 +223,57 @@ module Fluent
173
223
  return plugin_output
174
224
  end
175
225
  end
226
+
227
+ # Log a warning if the host name exceeds the max bytes.
228
+ private
229
+ def warn_if_host_name_exceeds_max_bytes(host_name)
230
+ if host_name_exceeds_max_bytes?(host_name)
231
+ log.warn("Host name exceeds the max bytes; it will be truncated",
232
+ :max_host_name_bytes => MAX_HOST_NAME_BYTES,
233
+ :host_name => host_name)
234
+ end
235
+ end
236
+
237
+ # Log a warning if the service description exceeds the max bytes.
238
+ private
239
+ def warn_if_service_description_exceeds_max_bytes(service_description)
240
+ if service_description_exceeds_max_bytes?(service_description)
241
+ log.warn(
242
+ "Service description exceeds the max bytes; it will be truncated.",
243
+ :max_service_description_bytes => MAX_SERVICE_DESCRIPTION_BYTES,
244
+ :service_description => service_description)
245
+ end
246
+ end
247
+
248
+ # Log a warning if the plugin output exceeds the max bytes.
249
+ private
250
+ def warn_if_plugin_output_exceeds_max_bytes(plugin_output)
251
+ if plugin_output_exceeds_max_bytes?(plugin_output)
252
+ log.warn("Plugin output exceeds the max bytes; it will be truncated.",
253
+ :max_plugin_output_bytes => MAX_PLUGIN_OUTPUT_BYTES,
254
+ :plugin_output => plugin_output)
255
+ end
256
+ end
257
+
258
+ # Returns true if host_name exceeds the max bytes
259
+ private
260
+ def host_name_exceeds_max_bytes?(host_name)
261
+ return !! host_name && host_name.bytesize > MAX_HOST_NAME_BYTES
262
+ end
263
+
264
+ # Returns true if service_description exceeds the max bytes
265
+ private
266
+ def service_description_exceeds_max_bytes?(service_description)
267
+ return !! service_description &&
268
+ service_description.bytesize > MAX_SERVICE_DESCRIPTION_BYTES
269
+ end
270
+
271
+ # Returns true if plugin_output exceeds the max bytes
272
+ private
273
+ def plugin_output_exceeds_max_bytes?(plugin_output)
274
+ return !! plugin_output &&
275
+ plugin_output.bytesize > MAX_PLUGIN_OUTPUT_BYTES
276
+ end
277
+
176
278
  end
177
279
  end
@@ -2,29 +2,39 @@
2
2
  # vim: et sw=2 sts=2
3
3
 
4
4
  require 'helper'
5
- require 'socket'
6
5
  require 'send_nsca'
7
6
 
7
+ # Test class for Fluent::NscaOutput
8
8
  class NscaOutputTest < Test::Unit::TestCase
9
+
10
+ # Sets up the test env and the stub
9
11
  def setup
10
12
  Fluent::Test.setup
13
+
14
+ # Stub NscaConnection
15
+ # whose send_nsca method returns the connection info and the check payload
16
+ # instead of sending the service check.
11
17
  stub.proxy(SendNsca::NscaConnection).new { |obj|
12
18
  stub(obj).send_nsca {
13
19
  obj.instance_eval {
14
- [@nscahost, @port, @password, @hostname, @service, @return_code, @status]
20
+ [@nscahost, @port, @password,
21
+ @hostname, @service, @return_code, @status]
15
22
  }
16
23
  }
17
24
  }
18
25
  end
19
26
 
27
+ # Common settings
20
28
  CONFIG = %[
21
29
  server monitor.example.com
22
30
  port 4242
23
31
  password aoxomoxoa
24
32
  ]
25
33
 
34
+ # Returns a driver of the plugin
26
35
  def create_driver(conf = CONFIG, tag='test')
27
- Fluent::Test::BufferedOutputTestDriver.new(Fluent::NscaOutput, tag).configure(conf)
36
+ driver = Fluent::Test::BufferedOutputTestDriver.new(Fluent::NscaOutput, tag)
37
+ driver.configure(conf)
28
38
  end
29
39
 
30
40
  # Connection settings are read
@@ -43,6 +53,102 @@ class NscaOutputTest < Test::Unit::TestCase
43
53
  assert_equal '', driver.instance.instance_eval{ @password }
44
54
  end
45
55
 
56
+ # Reject host_name option exceeding the max bytes
57
+ def test_reject_host_name_option_exceeding_max_bytes
58
+ max_bytes = Fluent::NscaOutput::MAX_HOST_NAME_BYTES
59
+ config = %[
60
+ #{CONFIG}
61
+ host_name #{'x' * (max_bytes + 1)}
62
+ ]
63
+ assert_raise(Fluent::ConfigError) {
64
+ create_driver(config)
65
+ }
66
+ end
67
+
68
+ # Decide if host name exceeds the max bytes
69
+ def test_host_name_exceeds_max_bytes()
70
+ max_bytes = Fluent::NscaOutput::MAX_HOST_NAME_BYTES
71
+ driver = create_driver('')
72
+
73
+ max_bytes_host_name = 'x' * max_bytes
74
+ assert_equal false, driver.instance.instance_eval{
75
+ host_name_exceeds_max_bytes?(max_bytes_host_name)
76
+ }
77
+
78
+ invalid_host_name = 'x' * (max_bytes + 1)
79
+ assert_equal true, driver.instance.instance_eval{
80
+ host_name_exceeds_max_bytes?(invalid_host_name)
81
+ }
82
+
83
+ assert_equal false, driver.instance.instance_eval{
84
+ host_name_exceeds_max_bytes?(nil)
85
+ }
86
+ end
87
+
88
+ # Reject service_description option exceeding the max bytes
89
+ def test_reject_service_description_option_exceeding_max_bytes
90
+ max_bytes = Fluent::NscaOutput::MAX_SERVICE_DESCRIPTION_BYTES
91
+ config = %[
92
+ #{CONFIG}
93
+ service_description #{'x' * (max_bytes + 1)}
94
+ ]
95
+ assert_raise(Fluent::ConfigError) {
96
+ create_driver(config)
97
+ }
98
+ end
99
+
100
+ # Decide if service description exceeds the max bytes
101
+ def test_service_description_exceeds_max_bytes()
102
+ max_bytes = Fluent::NscaOutput::MAX_SERVICE_DESCRIPTION_BYTES
103
+ driver = create_driver('')
104
+
105
+ max_bytes_service = 'x' * max_bytes
106
+ assert_equal false, driver.instance.instance_eval{
107
+ service_description_exceeds_max_bytes?(max_bytes_service)
108
+ }
109
+
110
+ invalid_service = 'x' * (max_bytes + 1)
111
+ assert_equal true, driver.instance.instance_eval{
112
+ service_description_exceeds_max_bytes?(invalid_service)
113
+ }
114
+
115
+ assert_equal false, driver.instance.instance_eval{
116
+ service_description_exceeds_max_bytes?(nil)
117
+ }
118
+ end
119
+
120
+ # Reject plugin_output option exceeding the max bytes
121
+ def test_reject_plugin_output_exceeding_max_bytes
122
+ max_bytes = Fluent::NscaOutput::MAX_PLUGIN_OUTPUT_BYTES
123
+ config = %[
124
+ #{CONFIG}
125
+ plugin_output #{'x' * (max_bytes + 1)}
126
+ ]
127
+ assert_raise(Fluent::ConfigError) {
128
+ create_driver(config)
129
+ }
130
+ end
131
+
132
+ # Decide if plugin output exceeds the max bytes
133
+ def test_plugin_output_exceeds_max_bytes()
134
+ max_bytes = Fluent::NscaOutput::MAX_PLUGIN_OUTPUT_BYTES
135
+ driver = create_driver('')
136
+
137
+ max_bytes_plugin_output = 'x' * max_bytes
138
+ assert_equal false, driver.instance.instance_eval{
139
+ plugin_output_exceeds_max_bytes?(max_bytes_plugin_output)
140
+ }
141
+
142
+ invalid_plugin_output = 'x' * (max_bytes + 1)
143
+ assert_equal true, driver.instance.instance_eval{
144
+ plugin_output_exceeds_max_bytes?(invalid_plugin_output)
145
+ }
146
+
147
+ assert_equal false, driver.instance.instance_eval{
148
+ plugin_output_exceeds_max_bytes?(nil)
149
+ }
150
+ end
151
+
46
152
  # Rejects invalid return codes
47
153
  def test_reject_invalid_return_codes
48
154
  config = %[
@@ -87,7 +193,9 @@ class NscaOutputTest < Test::Unit::TestCase
87
193
  time = Time.parse('2015-01-03 12:34:56 UTC').to_i
88
194
  driver.emit({"name" => "Stephen"}, time)
89
195
  output = driver.run
90
- assert_equal [['monitor.example.com', 4242, 'aoxomoxoa', 'web.example.org', 'ddos_monitor', 2, 'possible attacks']], output
196
+ expected = ['monitor.example.com', 4242, 'aoxomoxoa',
197
+ 'web.example.org', 'ddos_monitor', 2, 'possible attacks']
198
+ assert_equal [expected], output
91
199
  end
92
200
 
93
201
  # Sends a service check with host_name and host_name_field
@@ -106,13 +214,11 @@ class NscaOutputTest < Test::Unit::TestCase
106
214
  driver.emit({"name" => "Stephen", "host" => "app.example.org"}, time)
107
215
  driver.emit({"name" => "Aggi"}, time)
108
216
  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
217
+ expected1 = ['monitor.example.com', 4242, 'aoxomoxoa',
218
+ 'app.example.org', 'ddos_monitor', 2, 'possible attacks']
219
+ expected2 = ['monitor.example.com', 4242, 'aoxomoxoa',
220
+ 'fallback.example.org', 'ddos_monitor', 2, 'possible attacks']
221
+ assert_equal [expected1, expected2], output
116
222
  end
117
223
 
118
224
  # Sends a service check with host_name_field
@@ -130,13 +236,12 @@ class NscaOutputTest < Test::Unit::TestCase
130
236
  driver.emit({"name" => "Stephen", "host" => "app.example.org"}, time)
131
237
  driver.emit({"name" => "Aggi"}, time)
132
238
  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
239
+ require 'socket'
240
+ expected1 = ['monitor.example.com', 4242, 'aoxomoxoa',
241
+ 'app.example.org', 'ddos_monitor', 2, 'possible attacks']
242
+ expected2 = ['monitor.example.com', 4242, 'aoxomoxoa',
243
+ Socket.gethostname, 'ddos_monitor', 2, 'possible attacks']
244
+ assert_equal [expected1, expected2], output
140
245
  end
141
246
 
142
247
  # Sends a service check with service_description and service_description_field
@@ -155,15 +260,11 @@ class NscaOutputTest < Test::Unit::TestCase
155
260
  driver.emit({"name" => "Stephen", "service" => "possible_ddos"})
156
261
  driver.emit({"name" => "Aggi"})
157
262
  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
263
+ expected1 = ['monitor.example.com', 4242, 'aoxomoxoa',
264
+ 'web.example.org', 'possible_ddos', 2, 'possible attacks']
265
+ expected2 = ['monitor.example.com', 4242, 'aoxomoxoa',
266
+ 'web.example.org', 'ddos_detection', 2, 'possible attacks']
267
+ assert_equal [expected1, expected2], output
167
268
  end
168
269
 
169
270
  # Sends a service check with service_description_field
@@ -181,15 +282,11 @@ class NscaOutputTest < Test::Unit::TestCase
181
282
  driver.emit({"name" => "Stephen", "service" => "possible_ddos"})
182
283
  driver.emit({"name" => "Aggi"})
183
284
  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
285
+ expected1 = ['monitor.example.com', 4242, 'aoxomoxoa',
286
+ 'web.example.org', 'possible_ddos', 2, 'possible attacks']
287
+ expected2 = ['monitor.example.com', 4242, 'aoxomoxoa',
288
+ 'web.example.org', 'ddos', 2, 'possible attacks']
289
+ assert_equal [expected1, expected2], output
193
290
  end
194
291
 
195
292
  # Sends a service check with return_code and return_code_field
@@ -211,26 +308,16 @@ class NscaOutputTest < Test::Unit::TestCase
211
308
  driver.emit({"name" => "Brian", "retcode" => "invalid-value"})
212
309
  driver.emit({"name" => "Martin"})
213
310
  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
- ]
311
+ expected1 = ['monitor.example.com', 4242, 'aoxomoxoa',
312
+ 'web.example.org', 'ddos_monitor', 3, 'possible attacks']
313
+ expected2 = ['monitor.example.com', 4242, 'aoxomoxoa',
314
+ 'web.example.org', 'ddos_monitor', 2, 'possible attacks']
315
+ expected3 = ['monitor.example.com', 4242, 'aoxomoxoa',
316
+ 'web.example.org', 'ddos_monitor', 1, 'possible attacks']
317
+ expected4 = ['monitor.example.com', 4242, 'aoxomoxoa',
318
+ 'web.example.org', 'ddos_monitor', 0, 'possible attacks']
319
+ expected5 = ['monitor.example.com', 4242, 'aoxomoxoa',
320
+ 'web.example.org', 'ddos_monitor', 0, 'possible attacks']
234
321
  assert_equal [expected1, expected2, expected3, expected4, expected5], output
235
322
  end
236
323
 
@@ -252,26 +339,16 @@ class NscaOutputTest < Test::Unit::TestCase
252
339
  driver.emit({"name" => "Brian", "retcode" => "invalid-value"})
253
340
  driver.emit({"name" => "Martin"})
254
341
  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
- ]
342
+ expected1 = ['monitor.example.com', 4242, 'aoxomoxoa',
343
+ 'web.example.org', 'ddos_monitor', 0, 'possible attacks']
344
+ expected2 = ['monitor.example.com', 4242, 'aoxomoxoa',
345
+ 'web.example.org', 'ddos_monitor', 1, 'possible attacks']
346
+ expected3 = ['monitor.example.com', 4242, 'aoxomoxoa',
347
+ 'web.example.org', 'ddos_monitor', 2, 'possible attacks']
348
+ expected4 = ['monitor.example.com', 4242, 'aoxomoxoa',
349
+ 'web.example.org', 'ddos_monitor', 3, 'possible attacks']
350
+ expected5 = ['monitor.example.com', 4242, 'aoxomoxoa',
351
+ 'web.example.org', 'ddos_monitor', 3, 'possible attacks']
275
352
  assert_equal [expected1, expected2, expected3, expected4, expected5], output
276
353
  end
277
354
 
@@ -291,14 +368,10 @@ class NscaOutputTest < Test::Unit::TestCase
291
368
  driver.emit({"name" => "Stephen", "status" => "Possible DDOS detected"})
292
369
  driver.emit({"name" => "Aggi"})
293
370
  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
- ]
371
+ expected1 = ['monitor.example.com', 4242, 'aoxomoxoa',
372
+ 'web.example.org', 'ddos_monitor', 2, 'Possible DDOS detected']
373
+ expected2 = ['monitor.example.com', 4242, 'aoxomoxoa',
374
+ 'web.example.org', 'ddos_monitor', 2, 'DDOS detected']
302
375
  assert_equal [expected1, expected2], output
303
376
  end
304
377
 
@@ -317,14 +390,10 @@ class NscaOutputTest < Test::Unit::TestCase
317
390
  driver.emit({"name" => "Stephen", "status" => "Possible DDOS detected"})
318
391
  driver.emit({"name" => "Aggi"})
319
392
  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
- ]
393
+ expected1 = ['monitor.example.com', 4242, 'aoxomoxoa',
394
+ 'web.example.org', 'ddos_monitor', 2, 'Possible DDOS detected']
395
+ expected2 = ['monitor.example.com', 4242, 'aoxomoxoa',
396
+ 'web.example.org', 'ddos_monitor', 2, '{"name":"Aggi"}']
328
397
  assert_equal [expected1, expected2], output
329
398
  end
330
399
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-nsca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-02-15 00:00:00.000000000 Z
12
+ date: 2015-03-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -91,7 +91,8 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
- description: Fluentd output plugin to send service checks to a Nagios NSCA daemon
94
+ description: Fluentd output plugin to send service checks to an NSCA / Nagios monitoring
95
+ server
95
96
  email:
96
97
  - miyakawa.taku@gmail.com
97
98
  executables: []
@@ -107,7 +108,7 @@ files:
107
108
  - lib/fluent/plugin/out_nsca.rb
108
109
  - test/helper.rb
109
110
  - test/plugin/test_out_nsca.rb
110
- homepage: https://github.com/miyakawataku/fluent-plugin-nsca/
111
+ homepage: https://github.com/miyakawataku/fluent-plugin-nsca
111
112
  licenses:
112
113
  - Apache License, v2.0
113
114
  post_install_message:
@@ -122,7 +123,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
123
  version: '0'
123
124
  segments:
124
125
  - 0
125
- hash: -2882737187850770047
126
+ hash: 2216937057751646696
126
127
  required_rubygems_version: !ruby/object:Gem::Requirement
127
128
  none: false
128
129
  requirements:
@@ -131,13 +132,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
132
  version: '0'
132
133
  segments:
133
134
  - 0
134
- hash: -2882737187850770047
135
+ hash: 2216937057751646696
135
136
  requirements: []
136
137
  rubyforge_project:
137
138
  rubygems_version: 1.8.23
138
139
  signing_key:
139
140
  specification_version: 3
140
- summary: Fluentd output plugin to send service checks to a Nagios NSCA daemon
141
+ summary: Fluentd output plugin to send service checks to an NSCA / Nagios monitoring
142
+ server
141
143
  test_files:
142
144
  - test/helper.rb
143
145
  - test/plugin/test_out_nsca.rb