example-watch-meetupdata.asciidoc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. [role="xpack"]
  2. [[watching-meetup-data]]
  3. === Watching event data
  4. If you are indexing event data, such as log messages, network traffic, or a web feed, you can create a watch to email notifications when certain events occur.
  5. For example, if you index a feed of RSVPs for meetup events happening around the world, you can create a watch that alerts you to interesting events.
  6. To index the meetup data, you can use https://www.elastic.co/products/logstash[Logstash] to ingest live data from the Meetup.com streaming API, `http://stream.meetup.com/2/rsvps`.
  7. To ingest this data with Logstash:
  8. . https://www.elastic.co/downloads/logstash[Download Logstash] and unpack the
  9. archive file.
  10. . Create a Logstash configuration file that uses the {logstash-ref}/plugins-inputs-stdin.html[Logstash standard input] and the {logstash-ref}/plugins-outputs-stdout.html[Logstash standard output] and save it in `logstash-{version}` directory as `livestream.conf`:
  11. +
  12. --
  13. [source,ruby]
  14. ----------------------------------------------------------
  15. input {
  16. stdin {
  17. codec => json <1>
  18. }
  19. }
  20. filter {
  21. date {
  22. match => [ "event.time", "UNIX_MS" ]
  23. target => "event_time"
  24. }
  25. }
  26. output { <2>
  27. stdout {
  28. codec => rubydebug
  29. }
  30. elasticsearch {
  31. hosts => "http://localhost:9200"
  32. user => "elastic"
  33. password => "x-pack-test-password"
  34. }
  35. }
  36. ----------------------------------------------------------
  37. // NOTCONSOLE
  38. <1> The meetup data is formatted in JSON.
  39. <2> Index the meetup data into Elasticsearch.
  40. --
  41. . To start indexing the meetup data, pipe the RSVP stream into Logstash and specify your `livestream.conf` configuration file.
  42. +
  43. --
  44. [source,shell]
  45. ----------------------------------------------------------
  46. curl http://stream.meetup.com/2/rsvps | bin/logstash -f livestream.conf
  47. ----------------------------------------------------------
  48. // NOTCONSOLE
  49. --
  50. Now that you're indexing the meetup RSVPs, you can set up a watch that lets you know about events you might be interested in. For example, let's create a watch that runs every hour, looks for events that talk about _Open Source_, and sends an email with information about the events.
  51. To set up the watch:
  52. . Specify how often you want to run the watch by adding a schedule trigger to the watch:
  53. +
  54. --
  55. [source,js]
  56. --------------------------------------------------
  57. {
  58. "trigger": {
  59. "schedule": {
  60. "interval": "1h"
  61. }
  62. },
  63. --------------------------------------------------
  64. // NOTCONSOLE
  65. --
  66. . Load data into the watch payload by creating an input that searches the meetup data for events that have _Open Source_ as a topic. You can use aggregations to group the data by city, consolidate references to the same events, and sort the events by date.
  67. +
  68. --
  69. [source,js]
  70. -------------------------------------------------
  71. "input": {
  72. "search": {
  73. "request": {
  74. "indices": [
  75. "logstash" <1>
  76. ],
  77. "body": {
  78. "size": 0,
  79. "query": {
  80. "bool": {
  81. "filter": [
  82. {
  83. "range": {
  84. "@timestamp": {
  85. "gte": "now-3h"
  86. }
  87. }
  88. },
  89. {
  90. "match": {
  91. "group.group_topics.topic_name": "Open Source" <2>
  92. }
  93. }
  94. ]
  95. }
  96. },
  97. "aggs": {
  98. "group_by_city": {
  99. "terms": {
  100. "field": "group.group_city.keyword", <3>
  101. "size": 5
  102. },
  103. "aggs": {
  104. "group_by_event": {
  105. "terms": {
  106. "field": "event.event_url.keyword", <4>
  107. "size": 5
  108. },
  109. "aggs": {
  110. "get_latest": {
  111. "terms": {
  112. "field": "@timestamp", <5>
  113. "size": 1,
  114. "order": {
  115. "_key": "desc"
  116. }
  117. },
  118. "aggs": {
  119. "group_by_event_name": {
  120. "terms": {
  121. "field": "event.event_name.keyword" <6>
  122. }
  123. }
  124. }
  125. }
  126. }
  127. }
  128. }
  129. }
  130. }
  131. }
  132. }
  133. }
  134. },
  135. -------------------------------------------------
  136. // NOTCONSOLE
  137. <1> `logstash` is the default <<indices-add-alias,index alias>> for the {ls}
  138. indices containing the meetup data. By default, the {ls}
  139. <<index-lifecycle-management,{ilm} ({ilm-init})>> policy rolls this alias to a
  140. new index when the index size reaches 50GB or becomes 30 days old. For more
  141. information, see
  142. {logstash-ref}/plugins-outputs-elasticsearch.html#plugins-outputs-elasticsearch-ilm[{ilm-init}
  143. defaults in Logstash].
  144. <2> Find all of the RSVPs with `Open Source` as a topic.
  145. <3> Group the RSVPs by city.
  146. <4> Consolidate multiple RSVPs for the same event.
  147. <5> Sort the events so the latest events are listed first.
  148. <6> Group the events by name.
  149. --
  150. . To determine whether or not there are any Open Source events, add a compare condition that checks the watch payload to see if there were any search hits.
  151. +
  152. --
  153. [source,js]
  154. --------------------------------------------------
  155. "compare" : { "ctx.payload.hits.total" : { "gt" : 0 }}
  156. --------------------------------------------------
  157. // NOTCONSOLE
  158. --
  159. . To send an email when _Open Source_ events are found, add an email action:
  160. +
  161. --
  162. [source,js]
  163. ---------------------------------------------------
  164. "actions": {
  165. "email_me": {
  166. "throttle_period": "10m",
  167. "email": {
  168. "from": "<from:email address>",
  169. "to": "<to:email address>",
  170. "subject": "Open Source Events",
  171. "body": {
  172. "html": "Found events matching Open Source: <ul>{{#ctx.payload.aggregations.group_by_city.buckets}}< li>{{key}} ({{doc_count}})<ul>{{#group_by_event.buckets}}
  173. <li><a href=\"{{key}}\">{{get_latest.buckets.0.group_by_event_name.buckets.0.key}}</a>
  174. ({{doc_count}})</li>{{/group_by_event.buckets}}</ul></li>
  175. {{/ctx.payload.aggregations.group_by_city.buckets}}</ul>"
  176. }
  177. }
  178. }
  179. }
  180. ---------------------------------------------------
  181. // NOTCONSOLE
  182. --
  183. NOTE: To enable Watcher to send emails, you must configure an email account in `elasticsearch.yml`. For more information, see <<configuring-email>>.
  184. The complete watch looks like this:
  185. [source,console]
  186. --------------------------------------------------
  187. PUT _watcher/watch/meetup
  188. {
  189. "trigger": {
  190. "schedule": {
  191. "interval": "1h"
  192. }
  193. },
  194. "input": {
  195. "search": {
  196. "request": {
  197. "indices": [
  198. "logstash"
  199. ],
  200. "body": {
  201. "size": 0,
  202. "query": {
  203. "bool": {
  204. "filter": [
  205. {
  206. "range": {
  207. "@timestamp": {
  208. "gte": "now-3h"
  209. }
  210. }
  211. },
  212. {
  213. "match": {
  214. "group.group_topics.topic_name": "Open Source"
  215. }
  216. }
  217. ]
  218. }
  219. },
  220. "aggs": {
  221. "group_by_city": {
  222. "terms": {
  223. "field": "group.group_city.keyword",
  224. "size": 5
  225. },
  226. "aggs": {
  227. "group_by_event": {
  228. "terms": {
  229. "field": "event.event_url.keyword",
  230. "size": 5
  231. },
  232. "aggs": {
  233. "get_latest": {
  234. "terms": {
  235. "field": "@timestamp",
  236. "size": 1,
  237. "order": {
  238. "_key": "desc"
  239. }
  240. },
  241. "aggs": {
  242. "group_by_event_name": {
  243. "terms": {
  244. "field": "event.event_name.keyword"
  245. }
  246. }
  247. }
  248. }
  249. }
  250. }
  251. }
  252. }
  253. }
  254. }
  255. }
  256. }
  257. },
  258. "condition": {
  259. "compare": {
  260. "ctx.payload.hits.total": {
  261. "gt": 0
  262. }
  263. }
  264. },
  265. "actions": { <1>
  266. "email_me": {
  267. "throttle_period": "10m",
  268. "email": {
  269. "from": "username@example.org", <2>
  270. "to": "recipient@example.org", <3>
  271. "subject": "Open Source events",
  272. "body": {
  273. "html": "Found events matching Open Source: <ul>{{#ctx.payload.aggregations.group_by_city.buckets}}<li>{{key}} ({{doc_count}})<ul>{{#group_by_event.buckets}}<li><a href=\"{{key}}\">{{get_latest.buckets.0.group_by_event_name.buckets.0.key}}</a> ({{doc_count}})</li>{{/group_by_event.buckets}}</ul></li>{{/ctx.payload.aggregations.group_by_city.buckets}}</ul>"
  274. }
  275. }
  276. }
  277. }
  278. }
  279. --------------------------------------------------
  280. <1> The email body can include Mustache templates to reference data in the watch payload. By default,it will be <<email-html-sanitization,sanitized>> to block dangerous content.
  281. <2> Replace the `from` address with the email address you configured in `elasticsearch.yml`.
  282. <3> Replace the `to` address with your email address to receive notifications.
  283. Now that you've created your watch, you can use the
  284. {ref}/watcher-api-execute-watch.html[`_execute` API] to run it without waiting for the schedule to trigger execution:
  285. [source,console]
  286. --------------------------------------------------
  287. POST _watcher/watch/meetup/_execute
  288. --------------------------------------------------
  289. // TEST[continued]