logstash-lib 1.3.2

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.
Files changed (419) hide show
  1. data/.gitignore +24 -0
  2. data/.tailor +8 -0
  3. data/.travis.yml +12 -0
  4. data/CHANGELOG +1185 -0
  5. data/CONTRIBUTING.md +61 -0
  6. data/CONTRIBUTORS +79 -0
  7. data/LICENSE +14 -0
  8. data/Makefile +460 -0
  9. data/README.md +120 -0
  10. data/STYLE.md +96 -0
  11. data/bin/logstash +37 -0
  12. data/bin/logstash-test +4 -0
  13. data/bin/logstash-web +4 -0
  14. data/bin/logstash.lib.sh +78 -0
  15. data/bot/check_pull_changelog.rb +89 -0
  16. data/docs/configuration.md +260 -0
  17. data/docs/docgen.rb +242 -0
  18. data/docs/extending/example-add-a-new-filter.md +121 -0
  19. data/docs/extending/index.md +91 -0
  20. data/docs/flags.md +43 -0
  21. data/docs/generate_index.rb +28 -0
  22. data/docs/index.html.erb +56 -0
  23. data/docs/learn.md +46 -0
  24. data/docs/life-of-an-event.md +109 -0
  25. data/docs/logging-tool-comparisons.md +60 -0
  26. data/docs/plugin-doc.html.erb +91 -0
  27. data/docs/plugin-milestones.md +41 -0
  28. data/docs/plugin-synopsis.html.erb +24 -0
  29. data/docs/release-engineering.md +46 -0
  30. data/docs/release-test-results.md +14 -0
  31. data/docs/repositories.md +35 -0
  32. data/docs/tutorials/10-minute-walkthrough/apache-elasticsearch.conf +35 -0
  33. data/docs/tutorials/10-minute-walkthrough/apache-parse.conf +33 -0
  34. data/docs/tutorials/10-minute-walkthrough/apache_log.1 +1 -0
  35. data/docs/tutorials/10-minute-walkthrough/apache_log.2.bz2 +0 -0
  36. data/docs/tutorials/10-minute-walkthrough/hello-search.conf +25 -0
  37. data/docs/tutorials/10-minute-walkthrough/hello.conf +16 -0
  38. data/docs/tutorials/10-minute-walkthrough/index.md +124 -0
  39. data/docs/tutorials/10-minute-walkthrough/step-5-output.txt +17 -0
  40. data/docs/tutorials/getting-started-centralized-overview-diagram.png +0 -0
  41. data/docs/tutorials/getting-started-centralized-overview-diagram.xml +1 -0
  42. data/docs/tutorials/getting-started-centralized.md +217 -0
  43. data/docs/tutorials/getting-started-simple.md +200 -0
  44. data/docs/tutorials/just-enough-rabbitmq-for-logstash.md +201 -0
  45. data/docs/tutorials/media/frontend-response-codes.png +0 -0
  46. data/docs/tutorials/metrics-from-logs.md +84 -0
  47. data/docs/tutorials/zeromq.md +118 -0
  48. data/extract_services.rb +29 -0
  49. data/gembag.rb +64 -0
  50. data/lib/logstash-event.rb +2 -0
  51. data/lib/logstash.rb +4 -0
  52. data/lib/logstash/JRUBY-6970-openssl.rb +22 -0
  53. data/lib/logstash/JRUBY-6970.rb +102 -0
  54. data/lib/logstash/agent.rb +305 -0
  55. data/lib/logstash/certs/cacert.pem +3895 -0
  56. data/lib/logstash/codecs/base.rb +49 -0
  57. data/lib/logstash/codecs/compress_spooler.rb +50 -0
  58. data/lib/logstash/codecs/dots.rb +18 -0
  59. data/lib/logstash/codecs/edn.rb +28 -0
  60. data/lib/logstash/codecs/edn_lines.rb +36 -0
  61. data/lib/logstash/codecs/fluent.rb +55 -0
  62. data/lib/logstash/codecs/graphite.rb +114 -0
  63. data/lib/logstash/codecs/json.rb +41 -0
  64. data/lib/logstash/codecs/json_lines.rb +52 -0
  65. data/lib/logstash/codecs/json_spooler.rb +22 -0
  66. data/lib/logstash/codecs/line.rb +58 -0
  67. data/lib/logstash/codecs/msgpack.rb +43 -0
  68. data/lib/logstash/codecs/multiline.rb +189 -0
  69. data/lib/logstash/codecs/netflow.rb +342 -0
  70. data/lib/logstash/codecs/netflow/util.rb +212 -0
  71. data/lib/logstash/codecs/noop.rb +19 -0
  72. data/lib/logstash/codecs/oldlogstashjson.rb +56 -0
  73. data/lib/logstash/codecs/plain.rb +48 -0
  74. data/lib/logstash/codecs/rubydebug.rb +22 -0
  75. data/lib/logstash/codecs/spool.rb +38 -0
  76. data/lib/logstash/config/Makefile +4 -0
  77. data/lib/logstash/config/config_ast.rb +380 -0
  78. data/lib/logstash/config/file.rb +39 -0
  79. data/lib/logstash/config/grammar.rb +3504 -0
  80. data/lib/logstash/config/grammar.treetop +241 -0
  81. data/lib/logstash/config/mixin.rb +464 -0
  82. data/lib/logstash/config/registry.rb +13 -0
  83. data/lib/logstash/config/test.conf +18 -0
  84. data/lib/logstash/errors.rb +10 -0
  85. data/lib/logstash/event.rb +262 -0
  86. data/lib/logstash/filters/advisor.rb +178 -0
  87. data/lib/logstash/filters/alter.rb +173 -0
  88. data/lib/logstash/filters/anonymize.rb +93 -0
  89. data/lib/logstash/filters/base.rb +190 -0
  90. data/lib/logstash/filters/checksum.rb +50 -0
  91. data/lib/logstash/filters/cidr.rb +76 -0
  92. data/lib/logstash/filters/cipher.rb +145 -0
  93. data/lib/logstash/filters/clone.rb +35 -0
  94. data/lib/logstash/filters/collate.rb +114 -0
  95. data/lib/logstash/filters/csv.rb +94 -0
  96. data/lib/logstash/filters/date.rb +244 -0
  97. data/lib/logstash/filters/dns.rb +201 -0
  98. data/lib/logstash/filters/drop.rb +32 -0
  99. data/lib/logstash/filters/elapsed.rb +256 -0
  100. data/lib/logstash/filters/elasticsearch.rb +73 -0
  101. data/lib/logstash/filters/environment.rb +27 -0
  102. data/lib/logstash/filters/extractnumbers.rb +84 -0
  103. data/lib/logstash/filters/gelfify.rb +52 -0
  104. data/lib/logstash/filters/geoip.rb +145 -0
  105. data/lib/logstash/filters/grep.rb +153 -0
  106. data/lib/logstash/filters/grok.rb +425 -0
  107. data/lib/logstash/filters/grokdiscovery.rb +75 -0
  108. data/lib/logstash/filters/i18n.rb +51 -0
  109. data/lib/logstash/filters/json.rb +90 -0
  110. data/lib/logstash/filters/json_encode.rb +52 -0
  111. data/lib/logstash/filters/kv.rb +232 -0
  112. data/lib/logstash/filters/metaevent.rb +68 -0
  113. data/lib/logstash/filters/metrics.rb +237 -0
  114. data/lib/logstash/filters/multiline.rb +241 -0
  115. data/lib/logstash/filters/mutate.rb +399 -0
  116. data/lib/logstash/filters/noop.rb +21 -0
  117. data/lib/logstash/filters/prune.rb +149 -0
  118. data/lib/logstash/filters/punct.rb +32 -0
  119. data/lib/logstash/filters/railsparallelrequest.rb +86 -0
  120. data/lib/logstash/filters/range.rb +142 -0
  121. data/lib/logstash/filters/ruby.rb +42 -0
  122. data/lib/logstash/filters/sleep.rb +111 -0
  123. data/lib/logstash/filters/split.rb +64 -0
  124. data/lib/logstash/filters/sumnumbers.rb +73 -0
  125. data/lib/logstash/filters/syslog_pri.rb +107 -0
  126. data/lib/logstash/filters/translate.rb +121 -0
  127. data/lib/logstash/filters/unique.rb +29 -0
  128. data/lib/logstash/filters/urldecode.rb +57 -0
  129. data/lib/logstash/filters/useragent.rb +112 -0
  130. data/lib/logstash/filters/uuid.rb +58 -0
  131. data/lib/logstash/filters/xml.rb +139 -0
  132. data/lib/logstash/filters/zeromq.rb +123 -0
  133. data/lib/logstash/filterworker.rb +122 -0
  134. data/lib/logstash/inputs/base.rb +125 -0
  135. data/lib/logstash/inputs/collectd.rb +306 -0
  136. data/lib/logstash/inputs/drupal_dblog.rb +323 -0
  137. data/lib/logstash/inputs/drupal_dblog/jdbcconnection.rb +66 -0
  138. data/lib/logstash/inputs/elasticsearch.rb +140 -0
  139. data/lib/logstash/inputs/eventlog.rb +129 -0
  140. data/lib/logstash/inputs/eventlog/racob_fix.rb +44 -0
  141. data/lib/logstash/inputs/exec.rb +69 -0
  142. data/lib/logstash/inputs/file.rb +146 -0
  143. data/lib/logstash/inputs/ganglia.rb +127 -0
  144. data/lib/logstash/inputs/ganglia/gmondpacket.rb +146 -0
  145. data/lib/logstash/inputs/ganglia/xdr.rb +327 -0
  146. data/lib/logstash/inputs/gelf.rb +138 -0
  147. data/lib/logstash/inputs/gemfire.rb +222 -0
  148. data/lib/logstash/inputs/generator.rb +97 -0
  149. data/lib/logstash/inputs/graphite.rb +41 -0
  150. data/lib/logstash/inputs/heroku.rb +51 -0
  151. data/lib/logstash/inputs/imap.rb +136 -0
  152. data/lib/logstash/inputs/irc.rb +84 -0
  153. data/lib/logstash/inputs/log4j.rb +136 -0
  154. data/lib/logstash/inputs/lumberjack.rb +53 -0
  155. data/lib/logstash/inputs/pipe.rb +57 -0
  156. data/lib/logstash/inputs/rabbitmq.rb +126 -0
  157. data/lib/logstash/inputs/rabbitmq/bunny.rb +118 -0
  158. data/lib/logstash/inputs/rabbitmq/hot_bunnies.rb +1 -0
  159. data/lib/logstash/inputs/rabbitmq/march_hare.rb +129 -0
  160. data/lib/logstash/inputs/redis.rb +263 -0
  161. data/lib/logstash/inputs/relp.rb +106 -0
  162. data/lib/logstash/inputs/s3.rb +279 -0
  163. data/lib/logstash/inputs/snmptrap.rb +87 -0
  164. data/lib/logstash/inputs/sqlite.rb +185 -0
  165. data/lib/logstash/inputs/sqs.rb +172 -0
  166. data/lib/logstash/inputs/stdin.rb +46 -0
  167. data/lib/logstash/inputs/stomp.rb +84 -0
  168. data/lib/logstash/inputs/syslog.rb +237 -0
  169. data/lib/logstash/inputs/tcp.rb +231 -0
  170. data/lib/logstash/inputs/threadable.rb +18 -0
  171. data/lib/logstash/inputs/twitter.rb +82 -0
  172. data/lib/logstash/inputs/udp.rb +81 -0
  173. data/lib/logstash/inputs/unix.rb +163 -0
  174. data/lib/logstash/inputs/varnishlog.rb +48 -0
  175. data/lib/logstash/inputs/websocket.rb +50 -0
  176. data/lib/logstash/inputs/wmi.rb +72 -0
  177. data/lib/logstash/inputs/xmpp.rb +81 -0
  178. data/lib/logstash/inputs/zenoss.rb +143 -0
  179. data/lib/logstash/inputs/zeromq.rb +165 -0
  180. data/lib/logstash/kibana.rb +113 -0
  181. data/lib/logstash/loadlibs.rb +9 -0
  182. data/lib/logstash/logging.rb +89 -0
  183. data/lib/logstash/monkeypatches-for-bugs.rb +2 -0
  184. data/lib/logstash/monkeypatches-for-debugging.rb +47 -0
  185. data/lib/logstash/monkeypatches-for-performance.rb +66 -0
  186. data/lib/logstash/multiqueue.rb +53 -0
  187. data/lib/logstash/namespace.rb +16 -0
  188. data/lib/logstash/outputs/base.rb +120 -0
  189. data/lib/logstash/outputs/boundary.rb +116 -0
  190. data/lib/logstash/outputs/circonus.rb +78 -0
  191. data/lib/logstash/outputs/cloudwatch.rb +351 -0
  192. data/lib/logstash/outputs/csv.rb +55 -0
  193. data/lib/logstash/outputs/datadog.rb +93 -0
  194. data/lib/logstash/outputs/datadog_metrics.rb +123 -0
  195. data/lib/logstash/outputs/elasticsearch.rb +332 -0
  196. data/lib/logstash/outputs/elasticsearch/elasticsearch-template.json +44 -0
  197. data/lib/logstash/outputs/elasticsearch_http.rb +256 -0
  198. data/lib/logstash/outputs/elasticsearch_river.rb +214 -0
  199. data/lib/logstash/outputs/email.rb +299 -0
  200. data/lib/logstash/outputs/exec.rb +40 -0
  201. data/lib/logstash/outputs/file.rb +180 -0
  202. data/lib/logstash/outputs/ganglia.rb +75 -0
  203. data/lib/logstash/outputs/gelf.rb +208 -0
  204. data/lib/logstash/outputs/gemfire.rb +103 -0
  205. data/lib/logstash/outputs/google_bigquery.rb +570 -0
  206. data/lib/logstash/outputs/google_cloud_storage.rb +431 -0
  207. data/lib/logstash/outputs/graphite.rb +143 -0
  208. data/lib/logstash/outputs/graphtastic.rb +185 -0
  209. data/lib/logstash/outputs/hipchat.rb +80 -0
  210. data/lib/logstash/outputs/http.rb +142 -0
  211. data/lib/logstash/outputs/irc.rb +80 -0
  212. data/lib/logstash/outputs/jira.rb +109 -0
  213. data/lib/logstash/outputs/juggernaut.rb +105 -0
  214. data/lib/logstash/outputs/librato.rb +146 -0
  215. data/lib/logstash/outputs/loggly.rb +93 -0
  216. data/lib/logstash/outputs/lumberjack.rb +51 -0
  217. data/lib/logstash/outputs/metriccatcher.rb +103 -0
  218. data/lib/logstash/outputs/mongodb.rb +81 -0
  219. data/lib/logstash/outputs/nagios.rb +119 -0
  220. data/lib/logstash/outputs/nagios_nsca.rb +123 -0
  221. data/lib/logstash/outputs/null.rb +18 -0
  222. data/lib/logstash/outputs/opentsdb.rb +101 -0
  223. data/lib/logstash/outputs/pagerduty.rb +79 -0
  224. data/lib/logstash/outputs/pipe.rb +132 -0
  225. data/lib/logstash/outputs/rabbitmq.rb +96 -0
  226. data/lib/logstash/outputs/rabbitmq/bunny.rb +135 -0
  227. data/lib/logstash/outputs/rabbitmq/hot_bunnies.rb +1 -0
  228. data/lib/logstash/outputs/rabbitmq/march_hare.rb +143 -0
  229. data/lib/logstash/outputs/redis.rb +245 -0
  230. data/lib/logstash/outputs/riak.rb +152 -0
  231. data/lib/logstash/outputs/riemann.rb +109 -0
  232. data/lib/logstash/outputs/s3.rb +356 -0
  233. data/lib/logstash/outputs/sns.rb +124 -0
  234. data/lib/logstash/outputs/solr_http.rb +78 -0
  235. data/lib/logstash/outputs/sqs.rb +141 -0
  236. data/lib/logstash/outputs/statsd.rb +116 -0
  237. data/lib/logstash/outputs/stdout.rb +53 -0
  238. data/lib/logstash/outputs/stomp.rb +67 -0
  239. data/lib/logstash/outputs/syslog.rb +145 -0
  240. data/lib/logstash/outputs/tcp.rb +145 -0
  241. data/lib/logstash/outputs/udp.rb +38 -0
  242. data/lib/logstash/outputs/websocket.rb +46 -0
  243. data/lib/logstash/outputs/websocket/app.rb +29 -0
  244. data/lib/logstash/outputs/websocket/pubsub.rb +45 -0
  245. data/lib/logstash/outputs/xmpp.rb +78 -0
  246. data/lib/logstash/outputs/zabbix.rb +108 -0
  247. data/lib/logstash/outputs/zeromq.rb +125 -0
  248. data/lib/logstash/pipeline.rb +286 -0
  249. data/lib/logstash/plugin.rb +150 -0
  250. data/lib/logstash/plugin_mixins/aws_config.rb +93 -0
  251. data/lib/logstash/program.rb +15 -0
  252. data/lib/logstash/runner.rb +238 -0
  253. data/lib/logstash/sized_queue.rb +8 -0
  254. data/lib/logstash/test.rb +183 -0
  255. data/lib/logstash/threadwatchdog.rb +37 -0
  256. data/lib/logstash/time_addon.rb +33 -0
  257. data/lib/logstash/util.rb +106 -0
  258. data/lib/logstash/util/buftok.rb +139 -0
  259. data/lib/logstash/util/charset.rb +39 -0
  260. data/lib/logstash/util/fieldreference.rb +50 -0
  261. data/lib/logstash/util/password.rb +25 -0
  262. data/lib/logstash/util/prctl.rb +11 -0
  263. data/lib/logstash/util/relp.rb +326 -0
  264. data/lib/logstash/util/require-helper.rb +18 -0
  265. data/lib/logstash/util/socket_peer.rb +7 -0
  266. data/lib/logstash/util/zenoss.rb +566 -0
  267. data/lib/logstash/util/zeromq.rb +47 -0
  268. data/lib/logstash/version.rb +6 -0
  269. data/locales/en.yml +170 -0
  270. data/logstash-event.gemspec +29 -0
  271. data/logstash.gemspec +128 -0
  272. data/patterns/firewalls +60 -0
  273. data/patterns/grok-patterns +91 -0
  274. data/patterns/haproxy +37 -0
  275. data/patterns/java +3 -0
  276. data/patterns/linux-syslog +14 -0
  277. data/patterns/mcollective +1 -0
  278. data/patterns/mcollective-patterns +4 -0
  279. data/patterns/nagios +108 -0
  280. data/patterns/postgresql +3 -0
  281. data/patterns/redis +3 -0
  282. data/patterns/ruby +2 -0
  283. data/pkg/build.sh +135 -0
  284. data/pkg/centos/after-install.sh +1 -0
  285. data/pkg/centos/before-install.sh +10 -0
  286. data/pkg/centos/before-remove.sh +11 -0
  287. data/pkg/centos/sysconfig +15 -0
  288. data/pkg/debian/after-install.sh +5 -0
  289. data/pkg/debian/before-install.sh +13 -0
  290. data/pkg/debian/before-remove.sh +13 -0
  291. data/pkg/debian/build.sh +34 -0
  292. data/pkg/debian/debian/README +6 -0
  293. data/pkg/debian/debian/changelog +17 -0
  294. data/pkg/debian/debian/compat +1 -0
  295. data/pkg/debian/debian/control +16 -0
  296. data/pkg/debian/debian/copyright +27 -0
  297. data/pkg/debian/debian/dirs +19 -0
  298. data/pkg/debian/debian/docs +0 -0
  299. data/pkg/debian/debian/logstash.default +39 -0
  300. data/pkg/debian/debian/logstash.init +201 -0
  301. data/pkg/debian/debian/logstash.install +1 -0
  302. data/pkg/debian/debian/logstash.logrotate +9 -0
  303. data/pkg/debian/debian/logstash.postinst +68 -0
  304. data/pkg/debian/debian/logstash.postrm +23 -0
  305. data/pkg/debian/debian/manpage.1.ex +59 -0
  306. data/pkg/debian/debian/preinst.ex +37 -0
  307. data/pkg/debian/debian/prerm.ex +40 -0
  308. data/pkg/debian/debian/release.conf +5 -0
  309. data/pkg/debian/debian/rules +80 -0
  310. data/pkg/debian/debian/watch.ex +22 -0
  311. data/pkg/logrotate.conf +8 -0
  312. data/pkg/logstash-web.default +41 -0
  313. data/pkg/logstash-web.sysv.debian +201 -0
  314. data/pkg/logstash-web.upstart.ubuntu +18 -0
  315. data/pkg/logstash.default +45 -0
  316. data/pkg/logstash.sysv.debian +202 -0
  317. data/pkg/logstash.sysv.redhat +158 -0
  318. data/pkg/logstash.upstart.ubuntu +20 -0
  319. data/pkg/rpm/SOURCES/logstash.conf +26 -0
  320. data/pkg/rpm/SOURCES/logstash.init +80 -0
  321. data/pkg/rpm/SOURCES/logstash.logrotate +8 -0
  322. data/pkg/rpm/SOURCES/logstash.sysconfig +3 -0
  323. data/pkg/rpm/SOURCES/logstash.wrapper +105 -0
  324. data/pkg/rpm/SPECS/logstash.spec +180 -0
  325. data/pkg/rpm/readme.md +4 -0
  326. data/pkg/ubuntu/after-install.sh +7 -0
  327. data/pkg/ubuntu/before-install.sh +12 -0
  328. data/pkg/ubuntu/before-remove.sh +13 -0
  329. data/pull_release_note.rb +25 -0
  330. data/require-analyze.rb +22 -0
  331. data/spec/README.md +14 -0
  332. data/spec/codecs/edn.rb +40 -0
  333. data/spec/codecs/edn_lines.rb +53 -0
  334. data/spec/codecs/graphite.rb +96 -0
  335. data/spec/codecs/json.rb +57 -0
  336. data/spec/codecs/json_lines.rb +51 -0
  337. data/spec/codecs/json_spooler.rb +43 -0
  338. data/spec/codecs/msgpack.rb +39 -0
  339. data/spec/codecs/multiline.rb +60 -0
  340. data/spec/codecs/oldlogstashjson.rb +55 -0
  341. data/spec/codecs/plain.rb +35 -0
  342. data/spec/codecs/spool.rb +35 -0
  343. data/spec/conditionals/test.rb +323 -0
  344. data/spec/config.rb +31 -0
  345. data/spec/event.rb +165 -0
  346. data/spec/examples/fail2ban.rb +28 -0
  347. data/spec/examples/graphite-input.rb +41 -0
  348. data/spec/examples/mysql-slow-query.rb +70 -0
  349. data/spec/examples/parse-apache-logs.rb +66 -0
  350. data/spec/examples/parse-haproxy-logs.rb +115 -0
  351. data/spec/examples/syslog.rb +48 -0
  352. data/spec/filters/alter.rb +96 -0
  353. data/spec/filters/anonymize.rb +189 -0
  354. data/spec/filters/checksum.rb +41 -0
  355. data/spec/filters/clone.rb +67 -0
  356. data/spec/filters/collate.rb +122 -0
  357. data/spec/filters/csv.rb +174 -0
  358. data/spec/filters/date.rb +285 -0
  359. data/spec/filters/date_performance.rb +31 -0
  360. data/spec/filters/dns.rb +159 -0
  361. data/spec/filters/drop.rb +19 -0
  362. data/spec/filters/elapsed.rb +294 -0
  363. data/spec/filters/environment.rb +43 -0
  364. data/spec/filters/geoip.rb +62 -0
  365. data/spec/filters/grep.rb +342 -0
  366. data/spec/filters/grok.rb +473 -0
  367. data/spec/filters/grok/timeout2.rb +56 -0
  368. data/spec/filters/grok/timeouts.rb +39 -0
  369. data/spec/filters/i18n.rb +25 -0
  370. data/spec/filters/json.rb +72 -0
  371. data/spec/filters/json_encode.rb +37 -0
  372. data/spec/filters/kv.rb +403 -0
  373. data/spec/filters/metrics.rb +212 -0
  374. data/spec/filters/multiline.rb +119 -0
  375. data/spec/filters/mutate.rb +180 -0
  376. data/spec/filters/noop.rb +221 -0
  377. data/spec/filters/prune.rb +441 -0
  378. data/spec/filters/punct.rb +18 -0
  379. data/spec/filters/railsparallelrequest.rb +112 -0
  380. data/spec/filters/range.rb +169 -0
  381. data/spec/filters/split.rb +58 -0
  382. data/spec/filters/translate.rb +70 -0
  383. data/spec/filters/unique.rb +25 -0
  384. data/spec/filters/useragent.rb +42 -0
  385. data/spec/filters/xml.rb +157 -0
  386. data/spec/inputs/file.rb +107 -0
  387. data/spec/inputs/gelf.rb +52 -0
  388. data/spec/inputs/generator.rb +30 -0
  389. data/spec/inputs/imap.rb +60 -0
  390. data/spec/inputs/redis.rb +63 -0
  391. data/spec/inputs/relp.rb +70 -0
  392. data/spec/inputs/tcp.rb +101 -0
  393. data/spec/jar.rb +21 -0
  394. data/spec/outputs/csv.rb +266 -0
  395. data/spec/outputs/elasticsearch.rb +161 -0
  396. data/spec/outputs/elasticsearch_http.rb +240 -0
  397. data/spec/outputs/email.rb +173 -0
  398. data/spec/outputs/file.rb +82 -0
  399. data/spec/outputs/graphite.rb +236 -0
  400. data/spec/outputs/redis.rb +127 -0
  401. data/spec/speed.rb +20 -0
  402. data/spec/sqlite-test.rb +81 -0
  403. data/spec/support/LOGSTASH-733.rb +21 -0
  404. data/spec/support/LOGSTASH-820.rb +25 -0
  405. data/spec/support/akamai-grok.rb +26 -0
  406. data/spec/support/date-http.rb +17 -0
  407. data/spec/support/postwait1.rb +26 -0
  408. data/spec/support/pull375.rb +21 -0
  409. data/spec/test_utils.rb +125 -0
  410. data/spec/util/fieldeval_spec.rb +44 -0
  411. data/test/jenkins/config.xml.erb +74 -0
  412. data/test/jenkins/create-jobs.rb +23 -0
  413. data/test/jenkins/generatorjob.config.xml +66 -0
  414. data/tools/Gemfile +14 -0
  415. data/tools/Gemfile.jruby-1.9.lock +322 -0
  416. data/tools/Gemfile.rbx-2.1.lock +516 -0
  417. data/tools/Gemfile.ruby-1.9.1.lock +310 -0
  418. data/tools/Gemfile.ruby-2.0.0.lock +310 -0
  419. metadata +629 -0
@@ -0,0 +1,241 @@
1
+ require "treetop"
2
+ require "logstash/config/config_ast"
3
+
4
+ grammar LogStashConfig
5
+ rule config
6
+ _ plugin_section _ (_ plugin_section)* _ <LogStash::Config::AST::Config>
7
+ end
8
+
9
+ rule comment
10
+ (whitespace? "#" [^\r\n]* "\r"? "\n")+ <LogStash::Config::AST::Comment>
11
+ end
12
+
13
+ rule _
14
+ (comment / whitespace)* <LogStash::Config::AST::Whitespace>
15
+ end
16
+
17
+ rule whitespace
18
+ [ \t\r\n]+ <LogStash::Config::AST::Whitespace>
19
+ end
20
+
21
+ rule plugin_section
22
+ plugin_type _ "{"
23
+ _ (branch_or_plugin _)*
24
+ "}"
25
+ <LogStash::Config::AST::PluginSection>
26
+ end
27
+
28
+ rule branch_or_plugin
29
+ branch / plugin
30
+ end
31
+
32
+ rule plugin_type
33
+ ("input" / "filter" / "output")
34
+ end
35
+
36
+ rule plugins
37
+ (plugin (_ plugin)*)?
38
+ <LogStash::Config::AST::Plugins>
39
+ end
40
+
41
+ rule plugin
42
+ name _ "{"
43
+ _
44
+ attributes:( attribute (whitespace _ attribute)*)?
45
+ _
46
+ "}"
47
+ <LogStash::Config::AST::Plugin>
48
+ end
49
+
50
+ rule name
51
+ (
52
+ ([A-Za-z0-9_-]+ <LogStash::Config::AST::Name>)
53
+ / string
54
+ )
55
+ end
56
+
57
+ rule attribute
58
+ name _ "=>" _ value
59
+ <LogStash::Config::AST::Attribute>
60
+ end
61
+
62
+ rule value
63
+ plugin / bareword / string / number / array / hash
64
+ end
65
+
66
+ rule array_value
67
+ bareword / string / number / array / hash
68
+ end
69
+
70
+ rule bareword
71
+ [A-Za-z_] [A-Za-z0-9_]+
72
+ <LogStash::Config::AST::Bareword>
73
+ end
74
+
75
+ rule double_quoted_string
76
+ ( '"' ( '\"' / !'"' . )* '"' <LogStash::Config::AST::String>)
77
+ end
78
+
79
+ rule single_quoted_string
80
+ ( "'" ( "\\'" / !"'" . )* "'" <LogStash::Config::AST::String>)
81
+ end
82
+
83
+ rule string
84
+ double_quoted_string / single_quoted_string
85
+ end
86
+
87
+ rule regexp
88
+ ( '/' ( '\/' / !'/' . )* '/' <LogStash::Config::AST::RegExp>)
89
+ end
90
+
91
+ rule number
92
+ "-"? [0-9]+ ("." [0-9]*)?
93
+ <LogStash::Config::AST::Number>
94
+ end
95
+
96
+ rule array
97
+ "["
98
+ _
99
+ (
100
+ value (_ "," _ value)*
101
+ )?
102
+ _
103
+ "]"
104
+ <LogStash::Config::AST::Array>
105
+ end
106
+
107
+ rule hash
108
+ "{"
109
+ _
110
+ hashentries?
111
+ _
112
+ "}"
113
+ <LogStash::Config::AST::Hash>
114
+ end
115
+
116
+ rule hashentries
117
+ hashentry (whitespace hashentry)*
118
+ <LogStash::Config::AST::HashEntries>
119
+ end
120
+
121
+ rule hashentry
122
+ name:(number / bareword / string) _ "=>" _ value
123
+ <LogStash::Config::AST::HashEntry>
124
+ end
125
+
126
+ # Conditions
127
+ rule branch
128
+ if (_ else_if)* (_ else)?
129
+ <LogStash::Config::AST::Branch>
130
+ end
131
+
132
+ rule if
133
+ "if" _ condition _ "{" _ (branch_or_plugin _)* "}"
134
+ <LogStash::Config::AST::If>
135
+ end
136
+
137
+ rule else_if
138
+ "else" _ "if" _ condition _ "{" _ ( branch_or_plugin _)* "}"
139
+ <LogStash::Config::AST::Elsif>
140
+ end
141
+
142
+ rule else
143
+ "else" _ "{" _ (branch_or_plugin _)* "}"
144
+ <LogStash::Config::AST::Else>
145
+ end
146
+
147
+ rule condition
148
+ expression (_ boolean_operator _ expression)*
149
+ <LogStash::Config::AST::Condition>
150
+ end
151
+
152
+ rule expression
153
+ (
154
+ ("(" _ condition _ ")")
155
+ / negative_expression
156
+ / in_expression
157
+ / not_in_expression
158
+ / compare_expression
159
+ / regexp_expression
160
+ / rvalue
161
+ ) <LogStash::Config::AST::Expression>
162
+ end
163
+
164
+ rule negative_expression
165
+ (
166
+ ("!" _ "(" _ condition _ ")")
167
+ / ("!" _ selector)
168
+ ) <LogStash::Config::AST::NegativeExpression>
169
+ end
170
+
171
+ rule in_expression
172
+ rvalue _ in_operator _ rvalue
173
+ <LogStash::Config::AST::InExpression>
174
+ end
175
+
176
+ rule not_in_expression
177
+ rvalue _ not_in_operator _ rvalue
178
+ <LogStash::Config::AST::NotInExpression>
179
+ end
180
+
181
+ rule in_operator
182
+ "in"
183
+ end
184
+
185
+ rule not_in_operator
186
+ "not " _ "in"
187
+ end
188
+
189
+ rule rvalue
190
+ string / number / selector / array / method_call / regexp
191
+ end
192
+
193
+ rule method_call
194
+ method _ "(" _
195
+ (
196
+ rvalue ( _ "," _ rvalue )*
197
+ )?
198
+ _ ")"
199
+ <LogStash::Config::AST::MethodCall>
200
+ end
201
+
202
+ rule method
203
+ bareword
204
+ end
205
+
206
+ rule compare_expression
207
+ rvalue _ compare_operator _ rvalue
208
+ <LogStash::Config::AST::ComparisonExpression>
209
+ end
210
+
211
+ rule compare_operator
212
+ ("==" / "!=" / "<=" / ">=" / "<" / ">")
213
+ <LogStash::Config::AST::ComparisonOperator>
214
+ end
215
+
216
+ rule regexp_expression
217
+ rvalue _ regexp_operator _ (string / regexp)
218
+ <LogStash::Config::AST::RegexpExpression>
219
+ end
220
+
221
+ rule regexp_operator
222
+ ("=~" / "!~") <LogStash::Config::AST::RegExpOperator>
223
+ end
224
+
225
+
226
+ rule boolean_operator
227
+ ("and" / "or" / "xor" / "nand")
228
+ <LogStash::Config::AST::BooleanOperator>
229
+ end
230
+
231
+ rule selector
232
+ selector_element+
233
+ <LogStash::Config::AST::Selector>
234
+ end
235
+
236
+ rule selector_element
237
+ "[" [^\], ]+ "]"
238
+ <LogStash::Config::AST::SelectorElement>
239
+ end
240
+
241
+ end
@@ -0,0 +1,464 @@
1
+ # encoding: utf-8
2
+
3
+ require "logstash/namespace"
4
+ require "logstash/config/registry"
5
+ require "logstash/logging"
6
+ require "logstash/util/password"
7
+ require "logstash/version"
8
+ require "i18n"
9
+
10
+ # This module is meant as a mixin to classes wishing to be configurable from
11
+ # config files
12
+ #
13
+ # The idea is that you can do this:
14
+ #
15
+ # class Foo < LogStash::Config
16
+ # # Add config file settings
17
+ # config "path" => ...
18
+ # config "tag" => ...
19
+ #
20
+ # # Add global flags (becomes --foo-bar)
21
+ # flag "bar" => ...
22
+ # end
23
+ #
24
+ # And the config file should let you do:
25
+ #
26
+ # foo {
27
+ # "path" => ...
28
+ # "tag" => ...
29
+ # }
30
+ #
31
+ module LogStash::Config::Mixin
32
+ attr_accessor :config
33
+ attr_accessor :original_params
34
+
35
+ CONFIGSORT = {
36
+ Symbol => 0,
37
+ String => 0,
38
+ Regexp => 100,
39
+ }
40
+
41
+ # This method is called when someone does 'include LogStash::Config'
42
+ def self.included(base)
43
+ # Add the DSL methods to the 'base' given.
44
+ base.extend(LogStash::Config::Mixin::DSL)
45
+ end
46
+
47
+ def config_init(params)
48
+ # Validation will modify the values inside params if necessary.
49
+ # For example: converting a string to a number, etc.
50
+
51
+ # Keep a copy of the original config params so that we can later
52
+ # differentiate between explicit configuration and implicit (default)
53
+ # configuration.
54
+ @original_params = params.clone
55
+
56
+ # store the plugin type, turns LogStash::Inputs::Base into 'input'
57
+ @plugin_type = self.class.ancestors.find { |a| a.name =~ /::Base$/ }.config_name
58
+
59
+ # warn about deprecated variable use
60
+ params.each do |name, value|
61
+ opts = self.class.get_config[name]
62
+ if opts && opts[:deprecated]
63
+ extra = opts[:deprecated].is_a?(String) ? opts[:deprecated] : ""
64
+ extra.gsub!("%PLUGIN%", self.class.config_name)
65
+ @logger.warn("You are using a deprecated config setting " +
66
+ "#{name.inspect} set in #{self.class.config_name}. " +
67
+ "Deprecated settings will continue to work, " +
68
+ "but are scheduled for removal from logstash " +
69
+ "in the future. #{extra} If you have any questions " +
70
+ "about this, please visit the #logstash channel " +
71
+ "on freenode irc.", :name => name, :plugin => self)
72
+ end
73
+ end
74
+
75
+ # Set defaults from 'config :foo, :default => somevalue'
76
+ self.class.get_config.each do |name, opts|
77
+ next if params.include?(name.to_s)
78
+ if opts.include?(:default) and (name.is_a?(Symbol) or name.is_a?(String))
79
+ # default values should be cloned if possible
80
+ # cloning prevents
81
+ case opts[:default]
82
+ when FalseClass, TrueClass, NilClass, Numeric
83
+ params[name.to_s] = opts[:default]
84
+ else
85
+ params[name.to_s] = opts[:default].clone
86
+ end
87
+ end
88
+
89
+ # Allow plugins to override default values of config settings
90
+ if self.class.default?(name)
91
+ params[name.to_s] = self.class.get_default(name)
92
+ end
93
+ end
94
+
95
+ if !self.class.validate(params)
96
+ raise LogStash::ConfigurationError,
97
+ I18n.t("logstash.agent.configuration.invalid_plugin_settings")
98
+ end
99
+
100
+ # set instance variables like '@foo' for each config value given.
101
+ params.each do |key, value|
102
+ next if key[0, 1] == "@"
103
+
104
+ # Set this key as an instance variable only if it doesn't start with an '@'
105
+ @logger.debug("config #{self.class.name}/@#{key} = #{value.inspect}")
106
+ instance_variable_set("@#{key}", value)
107
+ end
108
+
109
+ @config = params
110
+ end # def config_init
111
+
112
+ module DSL
113
+ attr_accessor :flags
114
+
115
+ # If name is given, set the name and return it.
116
+ # If no name given (nil), return the current name.
117
+ def config_name(name=nil)
118
+ @config_name = name if !name.nil?
119
+ LogStash::Config::Registry.registry[@config_name] = self
120
+ return @config_name
121
+ end
122
+
123
+ def plugin_status(status=nil)
124
+ milestone(status)
125
+ end
126
+
127
+ def milestone(m=nil)
128
+ @milestone = m if !m.nil?
129
+ return @milestone
130
+ end
131
+
132
+ # Define a new configuration setting
133
+ def config(name, opts={})
134
+ @config ||= Hash.new
135
+ # TODO(sissel): verify 'name' is of type String, Symbol, or Regexp
136
+
137
+ name = name.to_s if name.is_a?(Symbol)
138
+ @config[name] = opts # ok if this is empty
139
+
140
+ if name.is_a?(String)
141
+ define_method(name) { instance_variable_get("@#{name}") }
142
+ define_method("#{name}=") { |v| instance_variable_set("@#{name}", v) }
143
+ end
144
+ end # def config
145
+
146
+ def default(name, value)
147
+ @defaults ||= {}
148
+ @defaults[name.to_s] = value
149
+ end
150
+
151
+ def get_config
152
+ return @config
153
+ end # def get_config
154
+
155
+ def get_default(name)
156
+ return @defaults && @defaults[name]
157
+ end
158
+
159
+ def default?(name)
160
+ return @defaults && @defaults.include?(name)
161
+ end
162
+
163
+ def options(opts)
164
+ # add any options from this class
165
+ prefix = self.name.split("::").last.downcase
166
+ @flags.each do |flag|
167
+ flagpart = flag[:args].first.gsub(/^--/,"")
168
+ # TODO(sissel): logger things here could help debugging.
169
+
170
+ opts.on("--#{prefix}-#{flagpart}", *flag[:args][1..-1], &flag[:block])
171
+ end
172
+ end # def options
173
+
174
+ # This is called whenever someone subclasses a class that has this mixin.
175
+ def inherited(subclass)
176
+ # Copy our parent's config to a subclass.
177
+ # This method is invoked whenever someone subclasses us, like:
178
+ # class Foo < Bar ...
179
+ subconfig = Hash.new
180
+ if !@config.nil?
181
+ @config.each do |key, val|
182
+ subconfig[key] = val
183
+ end
184
+ end
185
+ subclass.instance_variable_set("@config", subconfig)
186
+ @@milestone_notice_given = false
187
+ end # def inherited
188
+
189
+ def validate(params)
190
+ @plugin_name = config_name
191
+ @plugin_type = ancestors.find { |a| a.name =~ /::Base$/ }.config_name
192
+ @logger = Cabin::Channel.get(LogStash)
193
+ is_valid = true
194
+
195
+ is_valid &&= validate_milestone
196
+ is_valid &&= validate_check_invalid_parameter_names(params)
197
+ is_valid &&= validate_check_required_parameter_names(params)
198
+ is_valid &&= validate_check_parameter_values(params)
199
+
200
+ return is_valid
201
+ end # def validate
202
+
203
+ def validate_milestone
204
+ return true if @@milestone_notice_given
205
+ docmsg = "For more information about plugin milestones, see http://logstash.net/docs/#{LOGSTASH_VERSION}/plugin-milestones "
206
+ plugin_type = ancestors.find { |a| a.name =~ /::Base$/ }.config_name
207
+ case @milestone
208
+ when 0,1,2
209
+ @logger.warn(I18n.t("logstash.plugin.milestone.#{@milestone}",
210
+ :type => plugin_type, :name => @config_name,
211
+ :LOGSTASH_VERSION => LOGSTASH_VERSION))
212
+ when 3
213
+ # No message to log for milestone 3 plugins.
214
+ when nil
215
+ raise "#{@config_name} must set a milestone. #{docmsg}"
216
+ else
217
+ raise "#{@config_name} set an invalid plugin status #{@milestone}. Valid values are 0, 1, 2, or 3. #{docmsg}"
218
+ end
219
+ @@milestone_notice_given = true
220
+ return true
221
+ end
222
+
223
+ def validate_check_invalid_parameter_names(params)
224
+ invalid_params = params.keys
225
+ # Filter out parameters that match regexp keys.
226
+ # These are defined in plugins like this:
227
+ # config /foo.*/ => ...
228
+ @config.each_key do |config_key|
229
+ if config_key.is_a?(Regexp)
230
+ invalid_params.reject! { |k| k =~ config_key }
231
+ elsif config_key.is_a?(String)
232
+ invalid_params.reject! { |k| k == config_key }
233
+ end
234
+ end
235
+
236
+ if invalid_params.size > 0
237
+ invalid_params.each do |name|
238
+ @logger.error("Unknown setting '#{name}' for #{@plugin_name}")
239
+ end
240
+ return false
241
+ end # if invalid_params.size > 0
242
+ return true
243
+ end # def validate_check_invalid_parameter_names
244
+
245
+ def validate_check_required_parameter_names(params)
246
+ is_valid = true
247
+
248
+ @config.each do |config_key, config|
249
+ next unless config[:required]
250
+
251
+ if config_key.is_a?(Regexp)
252
+ next if params.keys.select { |k| k =~ config_key }.length > 0
253
+ elsif config_key.is_a?(String)
254
+ next if params.keys.member?(config_key)
255
+ end
256
+ @logger.error(I18n.t("logstash.agent.configuration.setting_missing",
257
+ :setting => config_key, :plugin => @plugin_name,
258
+ :type => @plugin_type))
259
+ is_valid = false
260
+ end
261
+
262
+ return is_valid
263
+ end
264
+
265
+ def validate_check_parameter_values(params)
266
+ # Filter out parametrs that match regexp keys.
267
+ # These are defined in plugins like this:
268
+ # config /foo.*/ => ...
269
+ is_valid = true
270
+
271
+ params.each do |key, value|
272
+ @config.keys.each do |config_key|
273
+ next unless (config_key.is_a?(Regexp) && key =~ config_key) \
274
+ || (config_key.is_a?(String) && key == config_key)
275
+ config_val = @config[config_key][:validate]
276
+ #puts " Key matches."
277
+ success, result = validate_value(value, config_val)
278
+ if success
279
+ # Accept coerced value if success
280
+ # Used for converting values in the config to proper objects.
281
+ params[key] = result if !result.nil?
282
+ else
283
+ @logger.error(I18n.t("logstash.agent.configuration.setting_invalid",
284
+ :plugin => @plugin_name, :type => @plugin_type,
285
+ :setting => key, :value => value.inspect,
286
+ :value_type => config_val,
287
+ :note => result))
288
+ end
289
+ #puts "Result: #{key} / #{result.inspect} / #{success}"
290
+ is_valid &&= success
291
+
292
+ break # done with this param key
293
+ end # config.each
294
+ end # params.each
295
+
296
+ return is_valid
297
+ end # def validate_check_parameter_values
298
+
299
+ def validator_find(key)
300
+ @config.each do |config_key, config_val|
301
+ if (config_key.is_a?(Regexp) && key =~ config_key) \
302
+ || (config_key.is_a?(String) && key == config_key)
303
+ return config_val
304
+ end
305
+ end # @config.each
306
+ return nil
307
+ end
308
+
309
+ def validate_value(value, validator)
310
+ # Validator comes from the 'config' pieces of plugins.
311
+ # They look like this
312
+ # config :mykey => lambda do |value| ... end
313
+ # (see LogStash::Inputs::File for example)
314
+ result = nil
315
+
316
+ if validator.nil?
317
+ return true
318
+ elsif validator.is_a?(Array)
319
+ value = [*value]
320
+ if value.size > 1
321
+ return false, "Expected one of #{validator.inspect}, got #{value.inspect}"
322
+ end
323
+
324
+ if !validator.include?(value.first)
325
+ return false, "Expected one of #{validator.inspect}, got #{value.inspect}"
326
+ end
327
+ result = value.first
328
+ elsif validator.is_a?(Symbol)
329
+ # TODO(sissel): Factor this out into a coersion method?
330
+ # TODO(sissel): Document this stuff.
331
+ value = hash_or_array(value)
332
+
333
+ case validator
334
+ when :codec
335
+ if value.first.is_a?(String)
336
+ value = LogStash::Plugin.lookup("codec", value.first).new
337
+ return true, value
338
+ else
339
+ value = value.first
340
+ return true, value
341
+ end
342
+ when :hash
343
+ if value.is_a?(Hash)
344
+ return true, value
345
+ end
346
+
347
+ if value.size % 2 == 1
348
+ return false, "This field must contain an even number of items, got #{value.size}"
349
+ end
350
+
351
+ # Convert the array the config parser produces into a hash.
352
+ result = {}
353
+ value.each_slice(2) do |key, value|
354
+ entry = result[key]
355
+ if entry.nil?
356
+ result[key] = value
357
+ else
358
+ if entry.is_a?(Array)
359
+ entry << value
360
+ else
361
+ result[key] = [entry, value]
362
+ end
363
+ end
364
+ end
365
+ when :array
366
+ result = value
367
+ when :string
368
+ if value.size > 1 # only one value wanted
369
+ return false, "Expected string, got #{value.inspect}"
370
+ end
371
+ result = value.first
372
+ when :number
373
+ if value.size > 1 # only one value wanted
374
+ return false, "Expected number, got #{value.inspect} (type #{value.class})"
375
+ end
376
+
377
+ v = value.first
378
+ case v
379
+ when Numeric
380
+ result = v
381
+ when String
382
+ if v.to_s.to_f.to_s != v.to_s \
383
+ && v.to_s.to_i.to_s != v.to_s
384
+ return false, "Expected number, got #{v.inspect} (type #{v})"
385
+ end
386
+ if v.include?(".")
387
+ # decimal value, use float.
388
+ result = v.to_f
389
+ else
390
+ result = v.to_i
391
+ end
392
+ end # case v
393
+ when :boolean
394
+ if value.size > 1 # only one value wanted
395
+ return false, "Expected boolean, got #{value.inspect}"
396
+ end
397
+
398
+ bool_value = value.first
399
+ if !!bool_value == bool_value
400
+ # is_a does not work for booleans
401
+ # we have Boolean and not a string
402
+ result = bool_value
403
+ else
404
+ if bool_value !~ /^(true|false)$/
405
+ return false, "Expected boolean 'true' or 'false', got #{bool_value.inspect}"
406
+ end
407
+
408
+ result = (bool_value == "true")
409
+ end
410
+ when :ipaddr
411
+ if value.size > 1 # only one value wanted
412
+ return false, "Expected IPaddr, got #{value.inspect}"
413
+ end
414
+
415
+ octets = value.split(".")
416
+ if octets.length != 4
417
+ return false, "Expected IPaddr, got #{value.inspect}"
418
+ end
419
+ octets.each do |o|
420
+ if o.to_i < 0 or o.to_i > 255
421
+ return false, "Expected IPaddr, got #{value.inspect}"
422
+ end
423
+ end
424
+ result = value.first
425
+ when :password
426
+ if value.size > 1
427
+ return false, "Expected password (one value), got #{value.size} values?"
428
+ end
429
+
430
+ result = ::LogStash::Util::Password.new(value.first)
431
+ when :path
432
+ if value.size > 1 # Only 1 value wanted
433
+ return false, "Expected path (one value), got #{value.size} values?"
434
+ end
435
+
436
+ # Paths must be absolute
437
+ #if !Pathname.new(value.first).absolute?
438
+ #return false, "Require absolute path, got relative path #{value.first}?"
439
+ #end
440
+
441
+ if !File.exists?(value.first) # Check if the file exists
442
+ return false, "File does not exist or cannot be opened #{value.first}"
443
+ end
444
+
445
+ result = value.first
446
+ else
447
+ return false, "Unknown validator symbol #{validator}"
448
+ end # case validator
449
+ else
450
+ return false, "Unknown validator #{validator.class}"
451
+ end
452
+
453
+ # Return the validator for later use, like with type coercion.
454
+ return true, result
455
+ end # def validate_value
456
+
457
+ def hash_or_array(value)
458
+ if !value.is_a?(Hash)
459
+ value = [*value] # coerce scalar to array if necessary
460
+ end
461
+ return value
462
+ end
463
+ end # module LogStash::Config::DSL
464
+ end # module LogStash::Config