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,116 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+
5
+ class LogStash::Outputs::Boundary < LogStash::Outputs::Base
6
+ # This output lets you send annotations to
7
+ # Boundary based on Logstash events
8
+ #
9
+ # Note that since Logstash maintains no state
10
+ # these will be one-shot events
11
+ #
12
+ # By default the start and stop time will be
13
+ # the event timestamp
14
+ #
15
+
16
+ config_name "boundary"
17
+ milestone 1
18
+
19
+ # Your Boundary API key
20
+ config :api_key, :validate => :string, :required => true
21
+
22
+ # Your Boundary Org ID
23
+ config :org_id, :validate => :string, :required => true
24
+
25
+ # Start time
26
+ # Override the start time
27
+ # Note that Boundary requires this to be seconds since epoch
28
+ # If overriding, it is your responsibility to type this correctly
29
+ # By default this is set to `event["@timestamp"].to_i`
30
+ config :start_time, :validate => :string
31
+
32
+ # End time
33
+ # Override the stop time
34
+ # Note that Boundary requires this to be seconds since epoch
35
+ # If overriding, it is your responsibility to type this correctly
36
+ # By default this is set to `event["@timestamp"].to_i`
37
+ config :end_time, :validate => :string
38
+
39
+ # Type
40
+ config :btype, :validate => :string
41
+
42
+ # Sub-Type
43
+ config :bsubtype, :validate => :string
44
+
45
+ # Tags
46
+ # Set any custom tags for this event
47
+ # Default are the Logstash tags if any
48
+ config :btags, :validate => :array
49
+
50
+ # Auto
51
+ # If set to true, logstash will try to pull boundary fields out
52
+ # of the event. Any field explicitly set by config options will
53
+ # override these.
54
+ # ['type', 'subtype', 'creation_time', 'end_time', 'links', 'tags', 'loc']
55
+ config :auto, :validate => :boolean, :default => false
56
+
57
+ public
58
+ def register
59
+ require "net/https"
60
+ require "uri"
61
+ @url = "https://api.boundary.com/#{@org_id}/annotations"
62
+ @uri = URI.parse(@url)
63
+ @client = Net::HTTP.new(@uri.host, @uri.port)
64
+ @client.use_ssl = true
65
+ # Boundary cert doesn't verify
66
+ @client.verify_mode = OpenSSL::SSL::VERIFY_NONE
67
+ end # def register
68
+
69
+ public
70
+ def receive(event)
71
+ return unless output?(event)
72
+
73
+ boundary_event = Hash.new
74
+ boundary_keys = ['type', 'subtype', 'creation_time', 'end_time', 'links', 'tags', 'loc']
75
+
76
+ boundary_event['start_time'] = event.sprintf(@start_time) if @start_time
77
+ boundary_event['end_time'] = event.sprintf(@end_time) if @end_time
78
+ boundary_event['type'] = event.sprintf(@btype) if @btype
79
+ boundary_event['subtype'] = event.sprintf(@bsubtype) if @bsubtype
80
+ boundary_event['tags'] = @btags.collect { |x| event.sprintf(x) } if @btags
81
+
82
+ if @auto
83
+ boundary_fields = event['@fields'].select { |k| boundary_keys.member? k }
84
+ boundary_event = boundary_fields.merge boundary_event
85
+ end
86
+
87
+ boundary_event = {
88
+ 'type' => event.sprintf("%{message}"),
89
+ 'subtype' => event.sprintf("%{type}"),
90
+ 'start_time' => event["@timestamp"].to_i,
91
+ 'end_time' => event["@timestamp"].to_i,
92
+ 'links' => [],
93
+ 'tags' => event["tags"],
94
+ }.merge boundary_event
95
+
96
+ request = Net::HTTP::Post.new(@uri.path)
97
+ request.basic_auth(@api_key, '')
98
+
99
+ @logger.debug("Boundary event", :boundary_event => boundary_event)
100
+
101
+ begin
102
+ request.body = boundary_event.to_json
103
+ request.add_field("Content-Type", 'application/json')
104
+ response = @client.request(request)
105
+ @logger.warn("Boundary convo", :request => request.inspect, :response => response.inspect)
106
+ raise unless response.code == '201'
107
+ rescue Exception => e
108
+ @logger.warn(
109
+ "Unhandled exception",
110
+ :request => request.inspect,
111
+ :response => response.inspect,
112
+ :exception => e.inspect
113
+ )
114
+ end
115
+ end # def receive
116
+ end
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+
5
+ class LogStash::Outputs::Circonus < LogStash::Outputs::Base
6
+ # This output lets you send annotations to
7
+ # Circonus based on Logstash events
8
+ #
9
+
10
+ config_name "circonus"
11
+ milestone 1
12
+
13
+ # Your Circonus API Token
14
+ config :api_token, :validate => :string, :required => true
15
+
16
+ # Your Circonus App name
17
+ # This will be passed through `event.sprintf`
18
+ # so variables are allowed here:
19
+ #
20
+ # Example:
21
+ # `app_name => "%{myappname}"`
22
+ config :app_name, :validate => :string, :required => true
23
+
24
+ # Annotations
25
+ # Registers an annotation with Circonus
26
+ # The only required field is `title` and `description`.
27
+ # `start` and `stop` will be set to `event["@timestamp"]`
28
+ # You can add any other optional annotation values as well.
29
+ # All values will be passed through `event.sprintf`
30
+ #
31
+ # Example:
32
+ # ["title":"Logstash event", "description":"Logstash event for %{host}"]
33
+ # or
34
+ # ["title":"Logstash event", "description":"Logstash event for %{host}", "parent_id", "1"]
35
+ config :annotation, :validate => :hash, :required => true, :default => {}
36
+
37
+ public
38
+ def register
39
+ require "net/https"
40
+ require "uri"
41
+ @url = "https://circonus.com/api/json/"
42
+ @uri = URI.parse(@url)
43
+ @client = Net::HTTP.new(@uri.host, @uri.port)
44
+ @client.use_ssl = true
45
+ @client.verify_mode = OpenSSL::SSL::VERIFY_NONE
46
+
47
+ end # def register
48
+
49
+ public
50
+ def receive(event)
51
+ # TODO (lusis)
52
+ # batch and flush
53
+ return unless output?(event)
54
+
55
+ annotation_event = Hash[*@annotation.collect{|k,v| [event.sprintf(k),event.sprintf(v)]}.flatten]
56
+ @logger.warn("Annotation event", :data => annotation_event)
57
+
58
+ annotation_array = []
59
+ annotation_path = "#{@uri.path}annotation"
60
+ @logger.warn("Annotation path", :data => annotation_path)
61
+ request = Net::HTTP::Post.new(annotation_path)
62
+ annotation_event['start'] = event["@timestamp"].to_i unless annotation_event['start']
63
+ annotation_event['stop'] = event["@timestamp"].to_i unless annotation_event['stop']
64
+ @logger.warn("Annotation event", :data => annotation_event)
65
+ annotation_array << annotation_event
66
+ begin
67
+ request.set_form_data(:annotations => annotation_array.to_json)
68
+ @logger.warn(annotation_event)
69
+ request.add_field("X-Circonus-Auth-Token", "#{@api_token}")
70
+ request.add_field("X-Circonus-App-Name", "#{event.sprintf(@app_name)}")
71
+ response = @client.request(request)
72
+ @logger.warn("Circonus convo", :request => request.inspect, :response => response.inspect)
73
+ raise unless response.code == '200'
74
+ rescue Exception => e
75
+ @logger.warn("Unhandled exception", :request => request.inspect, :response => response.inspect, :exception => e.inspect)
76
+ end
77
+ end # def receive
78
+ end
@@ -0,0 +1,351 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+ require "logstash/plugin_mixins/aws_config"
5
+
6
+ # This output lets you aggregate and send metric data to AWS CloudWatch
7
+ #
8
+ # #### Summary:
9
+ # This plugin is intended to be used on a logstash indexer agent (but that
10
+ # is not the only way, see below.) In the intended scenario, one cloudwatch
11
+ # output plugin is configured, on the logstash indexer node, with just AWS API
12
+ # credentials, and possibly a region and/or a namespace. The output looks
13
+ # for fields present in events, and when it finds them, it uses them to
14
+ # calculate aggregate statistics. If the `metricname` option is set in this
15
+ # output, then any events which pass through it will be aggregated & sent to
16
+ # CloudWatch, but that is not recommended. The intended use is to NOT set the
17
+ # metricname option here, and instead to add a `CW_metricname` field (and other
18
+ # fields) to only the events you want sent to CloudWatch.
19
+ #
20
+ # When events pass through this output they are queued for background
21
+ # aggregation and sending, which happens every minute by default. The
22
+ # queue has a maximum size, and when it is full aggregated statistics will be
23
+ # sent to CloudWatch ahead of schedule. Whenever this happens a warning
24
+ # message is written to logstash's log. If you see this you should increase
25
+ # the `queue_size` configuration option to avoid the extra API calls. The queue
26
+ # is emptied every time we send data to CloudWatch.
27
+ #
28
+ # Note: when logstash is stopped the queue is destroyed before it can be processed.
29
+ # This is a known limitation of logstash and will hopefully be addressed in a
30
+ # future version.
31
+ #
32
+ # #### Details:
33
+ # There are two ways to configure this plugin, and they can be used in
34
+ # combination: event fields & per-output defaults
35
+ #
36
+ # Event Field configuration...
37
+ # You add fields to your events in inputs & filters and this output reads
38
+ # those fields to aggregate events. The names of the fields read are
39
+ # configurable via the `field_*` options.
40
+ #
41
+ # Per-output defaults...
42
+ # You set universal defaults in this output plugin's configuration, and
43
+ # if an event does not have a field for that option then the default is
44
+ # used.
45
+ #
46
+ # Notice, the event fields take precedence over the per-output defaults.
47
+ #
48
+ # At a minimum events must have a "metric name" to be sent to CloudWatch.
49
+ # This can be achieved either by providing a default here OR by adding a
50
+ # `CW_metricname` field. By default, if no other configuration is provided
51
+ # besides a metric name, then events will be counted (Unit: Count, Value: 1)
52
+ # by their metric name (either a default or from their `CW_metricname` field)
53
+ #
54
+ # Other fields which can be added to events to modify the behavior of this
55
+ # plugin are, `CW_namespace`, `CW_unit`, `CW_value`, and
56
+ # `CW_dimensions`. All of these field names are configurable in
57
+ # this output. You can also set per-output defaults for any of them.
58
+ # See below for details.
59
+ #
60
+ # Read more about [AWS CloudWatch](http://aws.amazon.com/cloudwatch/),
61
+ # and the specific of API endpoint this output uses,
62
+ # [PutMetricData](http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/API_PutMetricData.html)
63
+ class LogStash::Outputs::CloudWatch < LogStash::Outputs::Base
64
+ include LogStash::PluginMixins::AwsConfig
65
+
66
+ config_name "cloudwatch"
67
+ milestone 1
68
+
69
+ # Constants
70
+ # aggregate_key members
71
+ DIMENSIONS = "dimensions"
72
+ TIMESTAMP = "timestamp"
73
+ METRIC = "metric"
74
+ COUNT = "count"
75
+ UNIT = "unit"
76
+ SUM = "sum"
77
+ MIN = "min"
78
+ MAX = "max"
79
+ # Units
80
+ COUNT_UNIT = "Count"
81
+ NONE = "None"
82
+
83
+ # How often to send data to CloudWatch
84
+ # This does not affect the event timestamps, events will always have their
85
+ # actual timestamp (to-the-minute) sent to CloudWatch.
86
+ #
87
+ # We only call the API if there is data to send.
88
+ #
89
+ # See the Rufus Scheduler docs for an [explanation of allowed values](https://github.com/jmettraux/rufus-scheduler#the-time-strings-understood-by-rufus-scheduler)
90
+ config :timeframe, :validate => :string, :default => "1m"
91
+
92
+ # How many events to queue before forcing a call to the CloudWatch API ahead of `timeframe` schedule
93
+ # Set this to the number of events-per-timeframe you will be sending to CloudWatch to avoid extra API calls
94
+ config :queue_size, :validate => :number, :default => 10000
95
+
96
+ # The default namespace to use for events which do not have a `CW_namespace` field
97
+ config :namespace, :validate => :string, :default => "Logstash"
98
+
99
+ # The name of the field used to set a different namespace per event
100
+ # Note: Only one namespace can be sent to CloudWatch per API call
101
+ # so setting different namespaces will increase the number of API calls
102
+ # and those cost money.
103
+ config :field_namespace, :validate => :string, :default => "CW_namespace"
104
+
105
+ # The default metric name to use for events which do not have a `CW_metricname` field.
106
+ # Beware: If this is provided then all events which pass through this output will be aggregated and
107
+ # sent to CloudWatch, so use this carefully. Furthermore, when providing this option, you
108
+ # will probably want to also restrict events from passing through this output using event
109
+ # type, tag, and field matching
110
+ config :metricname, :validate => :string
111
+
112
+ # The name of the field used to set the metric name on an event
113
+ # The author of this plugin recommends adding this field to events in inputs &
114
+ # filters rather than using the per-output default setting so that one output
115
+ # plugin on your logstash indexer can serve all events (which of course had
116
+ # fields set on your logstash shippers.)
117
+ config :field_metricname, :validate => :string, :default => "CW_metricname"
118
+
119
+ VALID_UNITS = ["Seconds", "Microseconds", "Milliseconds", "Bytes",
120
+ "Kilobytes", "Megabytes", "Gigabytes", "Terabytes",
121
+ "Bits", "Kilobits", "Megabits", "Gigabits", "Terabits",
122
+ "Percent", COUNT_UNIT, "Bytes/Second", "Kilobytes/Second",
123
+ "Megabytes/Second", "Gigabytes/Second", "Terabytes/Second",
124
+ "Bits/Second", "Kilobits/Second", "Megabits/Second",
125
+ "Gigabits/Second", "Terabits/Second", "Count/Second", NONE]
126
+
127
+ # The default unit to use for events which do not have a `CW_unit` field
128
+ # If you set this option you should probably set the "value" option along with it
129
+ config :unit, :validate => VALID_UNITS, :default => COUNT_UNIT
130
+
131
+ # The name of the field used to set the unit on an event metric
132
+ config :field_unit, :validate => :string, :default => "CW_unit"
133
+
134
+ # The default value to use for events which do not have a `CW_value` field
135
+ # If provided, this must be a string which can be converted to a float, for example...
136
+ # "1", "2.34", ".5", and "0.67"
137
+ # If you set this option you should probably set the `unit` option along with it
138
+ config :value, :validate => :string, :default => "1"
139
+
140
+ # The name of the field used to set the value (float) on an event metric
141
+ config :field_value, :validate => :string, :default => "CW_value"
142
+
143
+ # The default dimensions [ name, value, ... ] to use for events which do not have a `CW_dimensions` field
144
+ config :dimensions, :validate => :hash
145
+
146
+ # The name of the field used to set the dimensions on an event metric
147
+ # The field named here, if present in an event, must have an array of
148
+ # one or more key & value pairs, for example...
149
+ # add_field => [ "CW_dimensions", "Environment", "CW_dimensions", "prod" ]
150
+ # or, equivalently...
151
+ # add_field => [ "CW_dimensions", "Environment" ]
152
+ # add_field => [ "CW_dimensions", "prod" ]
153
+ config :field_dimensions, :validate => :string, :default => "CW_dimensions"
154
+
155
+ public
156
+ def aws_service_endpoint(region)
157
+ return {
158
+ :cloud_watch_endpoint => "monitoring.#{region}.amazonaws.com"
159
+ }
160
+ end
161
+
162
+ public
163
+ def register
164
+ require "thread"
165
+ require "rufus/scheduler"
166
+ require "aws"
167
+
168
+ @cw = AWS::CloudWatch.new(aws_options_hash)
169
+
170
+ @event_queue = SizedQueue.new(@queue_size)
171
+ @scheduler = Rufus::Scheduler.start_new
172
+ @job = @scheduler.every @timeframe do
173
+ @logger.info("Scheduler Activated")
174
+ publish(aggregate({}))
175
+ end
176
+ end # def register
177
+
178
+ public
179
+ def receive(event)
180
+ return unless output?(event)
181
+
182
+ if event == LogStash::SHUTDOWN
183
+ job.trigger()
184
+ job.unschedule()
185
+ @logger.info("CloudWatch aggregator thread shutdown.")
186
+ finished
187
+ return
188
+ end
189
+
190
+ return unless (event[@field_metricname] || @metricname)
191
+
192
+ if (@event_queue.length >= @event_queue.max)
193
+ @job.trigger
194
+ @logger.warn("Posted to AWS CloudWatch ahead of schedule. If you see this often, consider increasing the cloudwatch queue_size option.")
195
+ end
196
+
197
+ @logger.info("Queueing event", :event => event)
198
+ @event_queue << event
199
+ end # def receive
200
+
201
+ private
202
+ def publish(aggregates)
203
+ aggregates.each do |namespace, data|
204
+ @logger.info("Namespace, data: ", :namespace => namespace, :data => data)
205
+ metric_data = []
206
+ data.each do |aggregate_key, stats|
207
+ new_data = {
208
+ :metric_name => aggregate_key[METRIC],
209
+ :timestamp => aggregate_key[TIMESTAMP],
210
+ :unit => aggregate_key[UNIT],
211
+ :statistic_values => {
212
+ :sample_count => stats[COUNT],
213
+ :sum => stats[SUM],
214
+ :minimum => stats[MIN],
215
+ :maximum => stats[MAX],
216
+ }
217
+ }
218
+ dims = aggregate_key[DIMENSIONS]
219
+ if (dims.is_a?(Array) && dims.length > 0 && (dims.length % 2) == 0)
220
+ new_data[:dimensions] = Array.new
221
+ i = 0
222
+ while (i < dims.length)
223
+ new_data[:dimensions] << {:name => dims[i], :value => dims[i+1]}
224
+ i += 2
225
+ end
226
+ end
227
+ metric_data << new_data
228
+ end # data.each
229
+
230
+ begin
231
+ @cw.put_metric_data(
232
+ :namespace => namespace,
233
+ :metric_data => metric_data
234
+ )
235
+ @logger.info("Sent data to AWS CloudWatch OK", :namespace => namespace, :metric_data => metric_data)
236
+ rescue Exception => e
237
+ @logger.warn("Failed to send to AWS CloudWatch", :exception => e, :namespace => namespace, :metric_data => metric_data)
238
+ break
239
+ end
240
+ end # aggregates.each
241
+ return aggregates
242
+ end# def publish
243
+
244
+ private
245
+ def aggregate(aggregates)
246
+ @logger.info("QUEUE SIZE ", :queuesize => @event_queue.size)
247
+ while !@event_queue.empty? do
248
+ begin
249
+ count(aggregates, @event_queue.pop(true))
250
+ rescue Exception => e
251
+ @logger.warn("Exception! Breaking count loop", :exception => e)
252
+ break
253
+ end
254
+ end
255
+ return aggregates
256
+ end # def aggregate
257
+
258
+ private
259
+ def count(aggregates, event)
260
+ # If the event doesn't declare a namespace, use the default
261
+ fnamespace = field(event, @field_namespace)
262
+ namespace = (fnamespace ? fnamespace : event.sprintf(@namespace))
263
+
264
+ funit = field(event, @field_unit)
265
+ unit = (funit ? funit : event.sprintf(@unit))
266
+
267
+ fvalue = field(event, @field_value)
268
+ value = (fvalue ? fvalue : event.sprintf(@value))
269
+
270
+ # We may get to this point with valid Units but missing value. Send zeros.
271
+ val = (!value) ? 0.0 : value.to_f
272
+
273
+ # Event provides exactly one (but not both) of value or unit
274
+ if ( (fvalue == nil) ^ (funit == nil) )
275
+ @logger.warn("Likely config error: event has one of #{@field_value} or #{@field_unit} fields but not both.", :event => event)
276
+ end
277
+
278
+ # If Unit is still not set or is invalid warn about misconfiguration & use NONE
279
+ if (!VALID_UNITS.include?(unit))
280
+ unit = NONE
281
+ @logger.warn("Likely config error: invalid or missing Units (#{unit.to_s}), using '#{NONE}' instead", :event => event)
282
+ end
283
+
284
+ if (!aggregates[namespace])
285
+ aggregates[namespace] = {}
286
+ end
287
+
288
+ dims = event[@field_dimensions]
289
+ if (dims) # event provides dimensions
290
+ # validate the structure
291
+ if (!dims.is_a?(Array) || dims.length == 0 || (dims.length % 2) != 0)
292
+ @logger.warn("Likely config error: CloudWatch dimensions field (#{dims.to_s}) found which is not a positive- & even-length array. Ignoring it.", :event => event)
293
+ dims = nil
294
+ end
295
+ # Best case, we get here and exit the conditional because dims...
296
+ # - is an array
297
+ # - with positive length
298
+ # - and an even number of elements
299
+ elsif (@dimensions.is_a?(Hash)) # event did not provide dimensions, but the output has been configured with a default
300
+ dims = @dimensions.flatten.map{|d| event.sprintf(d)} # into the kind of array described just above
301
+ else
302
+ dims = nil
303
+ end
304
+
305
+ fmetric = field(event, @field_metricname)
306
+ aggregate_key = {
307
+ METRIC => (fmetric ? fmetric : event.sprintf(@metricname)),
308
+ DIMENSIONS => dims,
309
+ UNIT => unit,
310
+ TIMESTAMP => event.sprintf("%{+YYYY-MM-dd'T'HH:mm:00Z}")
311
+ }
312
+
313
+ if (!aggregates[namespace][aggregate_key])
314
+ aggregates[namespace][aggregate_key] = {}
315
+ end
316
+
317
+ if (!aggregates[namespace][aggregate_key][MAX] || val > aggregates[namespace][aggregate_key][MAX])
318
+ aggregates[namespace][aggregate_key][MAX] = val
319
+ end
320
+
321
+ if (!aggregates[namespace][aggregate_key][MIN] || val < aggregates[namespace][aggregate_key][MIN])
322
+ aggregates[namespace][aggregate_key][MIN] = val
323
+ end
324
+
325
+ if (!aggregates[namespace][aggregate_key][COUNT])
326
+ aggregates[namespace][aggregate_key][COUNT] = 1
327
+ else
328
+ aggregates[namespace][aggregate_key][COUNT] += 1
329
+ end
330
+
331
+ if (!aggregates[namespace][aggregate_key][SUM])
332
+ aggregates[namespace][aggregate_key][SUM] = val
333
+ else
334
+ aggregates[namespace][aggregate_key][SUM] += val
335
+ end
336
+ end # def count
337
+
338
+ private
339
+ def field(event, fieldname)
340
+ if !event[fieldname]
341
+ return nil
342
+ else
343
+ if event[fieldname].is_a?(Array)
344
+ return event[fieldname][0]
345
+ else
346
+ return event[fieldname]
347
+ end
348
+ end
349
+ end # def field
350
+
351
+ end # class LogStash::Outputs::CloudWatch