You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
6.5 KiB

  1. # Goldrush #
  2. Goldrush is a small Erlang app that provides fast event stream processing
  3. # Features #
  4. * Event processing compiled to a query module
  5. - per module protected event processing statistics
  6. - query module logic can be combined for any/all filters
  7. - query module logic can be reduced to efficiently match event processing
  8. * Complex event processing logic
  9. - match input events with greater than (gt) logic
  10. - match input events with less than (lt) logic
  11. - match input events with equal to (eq) logic
  12. - match input events with wildcard (wc) logic
  13. - match input events with notfound (nf) logic
  14. - match no input events (null blackhole) logic
  15. - match all input events (null passthrough) logic
  16. * Handle output events
  17. - Once a query has been composed the output action can be overriden
  18. with an erlang function. The function will be applied to each
  19. output event from the query.
  20. * Handle job execution and timing
  21. - create input events that include runtime on successful function executions.
  22. * Handle fastest lookups of stored values.
  23. - provide state storage option to compile, caching the values in query module.
  24. * Usage
  25. To use goldrush in your application, you need to define it as a rebar dep or
  26. include it in erlang's path.
  27. Before composing modules, you'll need to define a query. The query syntax
  28. matches any number of `{erlang, terms}' and is composed as follows:
  29. * Simple Logic
  30. - Simple logic is defined as any logic matching a single event filter
  31. Select all events where 'a' exists and is greater than 0.
  32. #+BEGIN_EXAMPLE
  33. glc:gt(a, 0).
  34. #+END_EXAMPLE
  35. Select all events where 'a' exists and is equal to 0.
  36. #+BEGIN_EXAMPLE
  37. glc:eq(a, 0).
  38. #+END_EXAMPLE
  39. Select all events where 'a' exists and is less than 0.
  40. #+BEGIN_EXAMPLE
  41. glc:lt(a, 0).
  42. #+END_EXAMPLE
  43. Select all events where 'a' exists.
  44. #+BEGIN_EXAMPLE
  45. glc:wc(a).
  46. #+END_EXAMPLE
  47. Select all events where 'a' does not exist.
  48. #+BEGIN_EXAMPLE
  49. glc:nf(a).
  50. #+END_EXAMPLE
  51. Select no input events. User as a black hole query.
  52. #+BEGIN_EXAMPLE
  53. glc:null(false).
  54. #+END_EXAMPLE
  55. Select all input events. Used as a passthrough query.
  56. #+BEGIN_EXAMPLE
  57. glc:null(true).
  58. #+END_EXAMPLE
  59. * Combined Logic
  60. - Combined logic is defined as logic matching multiple event filters
  61. Select all events where both 'a' AND 'b' exists and are greater than 0.
  62. #+BEGIN_EXAMPLE
  63. glc:all([glc:gt(a, 0), glc:gt(b, 0)]).
  64. #+END_EXAMPLE
  65. Select all events where 'a' OR 'b' exists and are greater than 0.
  66. #+BEGIN_EXAMPLE
  67. glc:any([glc:gt(a, 0), glc:gt(b, 0)]).
  68. #+END_EXAMPLE
  69. Select all events where 'a' AND 'b' exists where 'a' is greater than 1 and 'b' is less than 2.
  70. #+BEGIN_EXAMPLE
  71. glc:all([glc:gt(a, 1), glc:lt(b, 2)]).
  72. #+END_EXAMPLE
  73. Select all events where 'a' OR 'b' exists where 'a' is greater than 1 and 'b' is less than 2.
  74. #+BEGIN_EXAMPLE
  75. glc:any([glc:gt(a, 1), glc:lt(b, 2)]).
  76. #+END_EXAMPLE
  77. * Reduced Logic
  78. - Reduced logic is defined as logic which can be simplified to improve efficiency.
  79. Select all events where 'a' is equal to 1, 'b' is equal to 2 and 'c' is equal to 3 and collapse any duplicate logic.
  80. #+BEGIN_EXAMPLE
  81. glc_lib:reduce(
  82. glc:all([
  83. glc:any([glc:eq(a, 1), glc:eq(b, 2)]),
  84. glc:any([glc:eq(a, 1), glc:eq(c, 3)])])).
  85. #+END_EXAMPLE
  86. The previous example will produce and is equivalent to:
  87. #+BEGIN_EXAMPLE
  88. glc:all([glc:eq(a, 1), glc:eq(b, 2), glc:eq(c, 3)]).
  89. #+END_EXAMPLE
  90. # Composing Modules #
  91. To compose a module you will take your Query defined above and compile it.
  92. #+BEGIN_EXAMPLE
  93. glc:compile(Module, Query).
  94. #+END_EXAMPLE
  95. - At this point you will be able to handle an event using a compiled query.
  96. Begin by constructing an event list.
  97. #+BEGIN_EXAMPLE
  98. Event = gre:make([{'a', 2}], [list]).
  99. #+END_EXAMPLE
  100. Now pass it to your query module to be handled.
  101. #+BEGIN_EXAMPLE
  102. glc:handle(Module, Event).
  103. #+END_EXAMPLE
  104. * Handling output events
  105. - You can override the output action with an erlang function.
  106. Write all input events as info reports to the error logger.
  107. #+BEGIN_EXAMPLE
  108. glc:with(glc:null(true), fun(E) ->
  109. error_logger:info_report(gre:pairs(E)) end).
  110. #+END_EXAMPLE
  111. Write all input events where `error_level' exists and is less than 5 as info reports to the error logger.
  112. #+BEGIN_EXAMPLE
  113. glc:with(glc:lt(error_level, 5), fun(E) ->
  114. error_logger:info_report(gre:pairs(E)) end).
  115. #+END_EXAMPLE
  116. # Composing Modules with stored state #
  117. To compose a module with state data you will add a third argument (orddict).
  118. #+BEGIN_EXAMPLE
  119. glc:compile(Module, Query, [{stored, value}]).
  120. #+END_EXAMPLE
  121. # Accessing stored state data #
  122. Return the stored value in this query module.
  123. #+BEGIN_EXAMPLE
  124. {ok, value} = glc:get(stored).
  125. #+END_EXAMPLE
  126. # Executing jobs #
  127. To execute a job through the query module, inputting an event on success.
  128. #+BEGIN_EXAMPLE
  129. Event = gre:make([{'a', 2}], [list]).
  130. Result = glc:run(Module, fun(Event, State) ->
  131. %% do not end with {error, _} or throw an exception
  132. end, Event).
  133. #+END_EXAMPLE
  134. # Event Processing Statistics #
  135. Return the number of input events for this query module.
  136. #+BEGIN_EXAMPLE
  137. glc:input(Module).
  138. #+END_EXAMPLE
  139. Return the number of output events for this query module.
  140. #+BEGIN_EXAMPLE
  141. glc:output(Module).
  142. #+END_EXAMPLE
  143. Return the number of filtered events for this query module.
  144. #+BEGIN_EXAMPLE
  145. glc:filter(Module).
  146. #+END_EXAMPLE
  147. # Job Processing Statistics #
  148. Return the number of job runs for this query module.
  149. #+BEGIN_EXAMPLE
  150. glc:job_run(Module).
  151. #+END_EXAMPLE
  152. Return the number of job errors for this query module.
  153. #+BEGIN_EXAMPLE
  154. glc:job_error(Module).
  155. #+END_EXAMPLE
  156. Return the number of job inputs for this query module.
  157. #+BEGIN_EXAMPLE
  158. glc:job_input(Module).
  159. #+END_EXAMPLE
  160. Return the amount of time jobs took for this query module.
  161. #+BEGIN_EXAMPLE
  162. glc:job_time(Module).
  163. #+END_EXAMPLE
  164. # Tips & Tricks #
  165. Return the average time jobs took for this query module.
  166. #+BEGIN_EXAMPLE
  167. glc:job_time(Module) / glc:job_input(Module) / 1000000.
  168. #+END_EXAMPLE
  169. Return the query combining the conditional logic of multiple modules
  170. #+BEGIN_EXAMPLE
  171. glc_lib:reduce(glc:all([Module1:info('query'), Module2:info('query')]).
  172. #+END_EXAMPLE
  173. * Build
  174. #+BEGIN_EXAMPLE
  175. $ ./rebar compile
  176. #+END_EXAMPLE
  177. or
  178. #+BEGIN_EXAMPLE
  179. $ make
  180. #+END_EXAMPLE
  181. * CHANGELOG
  182. 0.1.7
  183. - Add job execution and timings
  184. - Add state storage option
  185. 0.1.6
  186. - Add notfound event matching
  187. 0.1.5
  188. - Rewrite to make highly crash resilient
  189. - per module supervision
  190. - statistics data recovery
  191. - Add wildcard event matching
  192. - Add reset counters