Logo

0x5a.live

for different kinds of informations and explorations.

GitHub - DeadZen/goldrush: Small, Fast event processing and monitoring for Erlang/OTP applications.

Small, Fast event processing and monitoring for Erlang/OTP applications. - DeadZen/goldrush

Visit SiteGitHub - DeadZen/goldrush: Small, Fast event processing and monitoring for Erlang/OTP applications.

GitHub - DeadZen/goldrush: Small, Fast event processing and monitoring for Erlang/OTP applications.

Small, Fast event processing and monitoring for Erlang/OTP applications. - DeadZen/goldrush

Powered by 0x5a.live ๐Ÿ’—

Goldrush

Goldrush is a small Erlang app that provides fast event stream processing

Features

  • Event processing compiled to a query module
  • per module private event processing statistics
  • query module logic can be combined for any/all filters
  • query module logic can be reduced to efficiently match event processing
  • Complex event processing logic
  • match input events with greater than (gt) logic
  • match input events with less than (lt) logic
  • match input events with equal to (eq) logic
  • match input events with wildcard (wc) logic
  • match input events with notfound (nf) logic
  • match no input events (null blackhole) logic
  • match all input events (null passthrough) logic
  • Handle output events
  • Once a query has been composed the output action can be overriden with one or more erlang functions. The functions will be applied to each output event from the query.
  • Handle low latency retrieval of compile-time stored values.
  • Values stored are also provided to functions called on event output.
  • Handle job execution and timing which can also get values stored
  • create input events that include runtime on successful function executions.
  • Handle fastest lookups of stored values.
  • provide state storage option to compile, caching the values in query module.
  • Usage To use goldrush in your application, you need to define it as a rebar dep or include it in erlang's path.

Before composing modules, you'll need to define a query. The query syntax matches any number of `{erlang, terms}' and is composed as follows:

  • Simple Logic
  • Simple logic is defined as any logic matching a single event filter

Select all events where 'a' exists and is greater than 0. #+BEGIN_EXAMPLE glc:gt(a, 0). #+END_EXAMPLE

Select all events where 'a' exists and is greater than or equal to 0. #+BEGIN_EXAMPLE glc:gte(a, 0). #+END_EXAMPLE

Select all events where 'a' exists and is equal to 0. #+BEGIN_EXAMPLE glc:eq(a, 0). #+END_EXAMPLE

Select all events where 'a' exists and is not equal to 0. #+BEGIN_EXAMPLE glc:neq(a, 0). #+END_EXAMPLE

Select all events where 'a' exists and is less than 0. #+BEGIN_EXAMPLE glc:lt(a, 0). #+END_EXAMPLE

Select all events where 'a' exists and is less than or equal to 0. #+BEGIN_EXAMPLE glc:lte(a, 0). #+END_EXAMPLE

Select all events where 'a' exists. #+BEGIN_EXAMPLE glc:wc(a). #+END_EXAMPLE

Select all events where 'a' does not exist. #+BEGIN_EXAMPLE glc:nf(a). #+END_EXAMPLE

Select no input events. User as a black hole query. #+BEGIN_EXAMPLE glc:null(false). #+END_EXAMPLE

Select all input events. Used as a passthrough query. #+BEGIN_EXAMPLE glc:null(true). #+END_EXAMPLE

  • Combined Logic
  • Combined logic is defined as logic matching multiple event filters

Select all events where both 'a' AND 'b' exists and are greater than 0. #+BEGIN_EXAMPLE glc:all([glc:gt(a, 0), glc:gt(b, 0)]). #+END_EXAMPLE

Select all events where 'a' OR 'b' exists and are greater than 0. #+BEGIN_EXAMPLE glc:any([glc:gt(a, 0), glc:gt(b, 0)]). #+END_EXAMPLE

Select all events where 'a' AND 'b' exists where 'a' is greater than 1 and 'b' is less than 2. #+BEGIN_EXAMPLE glc:all([glc:gt(a, 1), glc:lt(b, 2)]). #+END_EXAMPLE

Select all events where 'a' OR 'b' exists where 'a' is greater than 1 and 'b' is less than 2. #+BEGIN_EXAMPLE glc:any([glc:gt(a, 1), glc:lt(b, 2)]). #+END_EXAMPLE

  • Reduced Logic
  • Reduced logic is defined as logic which can be simplified to improve efficiency.

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. #+BEGIN_EXAMPLE glc_lib:reduce( glc:all([ glc:any([glc:eq(a, 1), glc:eq(b, 2)]), glc:any([glc:eq(a, 1), glc:eq(c, 3)])])). #+END_EXAMPLE

The previous example will produce and is equivalent to: #+BEGIN_EXAMPLE glc:all([glc:eq(a, 1), glc:eq(b, 2), glc:eq(c, 3)]). #+END_EXAMPLE

  • Composing Modules
    • All query modules must be compiled before use

To compose a module you will take your Query defined above and compile it. #+BEGIN_EXAMPLE glc:compile(Module, Query). glc:compile(Module, Query, State). glc:compile(Module, Query, State, ResetStatistics). #+END_EXAMPLE

  • At this point you will be able to handle an event using a compiled query.

Begin by constructing an event list. #+BEGIN_EXAMPLE Event = gre:make([{'a', 2}], [list]). #+END_EXAMPLE

Now pass it to your query module to be handled. #+BEGIN_EXAMPLE glc:handle(Module, Event). #+END_EXAMPLE

  • Handling output events
    • You can override the output action with an erlang function.

Write all input events as info reports to the error logger. #+BEGIN_EXAMPLE glc:with(glc:null(true), fun(E) -> error_logger:info_report(gre:pairs(E)) end). #+END_EXAMPLE

Write all input events where `error_level' exists and is less than 5 as info reports to the error logger. #+BEGIN_EXAMPLE glc:with(glc:lt(error_level, 5), fun(E) -> error_logger:info_report(gre:pairs(E)) end). #+END_EXAMPLE

Write all input events where `error_level' exists and is 3 or 5 as info reports to the error logger. #+BEGIN_EXAMPLE glc:any([ glc:with(glc:lt(error_level, 3), fun(E) -> error_logger:info_report(gre:pairs(E)) end), glc:with(glc:lt(error_level, 5), fun(E) -> error_logger:info_report(gre:pairs(E)) end)]).

#+END_EXAMPLE

Composing Modules with stored state

To compose a module with state data you will add a third argument (orddict). #+BEGIN_EXAMPLE glc:compile(Module, Query, [{stored, value}]). #+END_EXAMPLE

Accessing stored state data

Return the stored value in this query module. #+BEGIN_EXAMPLE {ok, value} = glc:get(stored). #+END_EXAMPLE

Return all stored values in this query module. #+BEGIN_EXAMPLE [...] = Module:get(). #+END_EXAMPLE

  • Composing Modules with stored data
    • You can create query modules with local state to compare to event data in with' and run'

To compose a module with state data you will add a third argument (orddict). #+BEGIN_EXAMPLE glc:compile(Module, Query, [{stored, value}]). #+END_EXAMPLE

  • Accessing stored data in constant time
  • You can use query modules in a way similar to mochiglobal

Return the stored value in this query module. #+BEGIN_EXAMPLE {ok, value} = glc:get(stored). #+END_EXAMPLE

  • Job processing with composed modules
    • You can use query modules to execute jobs, if the job errors or not, process an event.
    • with' is similar to run', the main difference is additional statistics and execution order
    • when a job completes in error, the event data will contain an additional {error, _} item

To execute a job through the query module, inputting an event on success. #+BEGIN_EXAMPLE Event = gre:make([{'a', 2}], [list]). {ExecutionTime, Result}= glc:run(Module, fun(Event, State) -> %% do not end with {error, _} or throw an exception end, Event). #+END_EXAMPLE

  • Event Processing Statistics

Return the number of input events for this query module. #+BEGIN_EXAMPLE glc:input(Module). #+END_EXAMPLE

Return the number of output events for this query module. #+BEGIN_EXAMPLE glc:output(Module). #+END_EXAMPLE

Return the number of filtered events for this query module. #+BEGIN_EXAMPLE glc:filter(Module). #+END_EXAMPLE

  • Job Processing Statistics

Return the number of job runs for this query module. #+BEGIN_EXAMPLE glc:job_run(Module). #+END_EXAMPLE

Return the number of job errors for this query module. #+BEGIN_EXAMPLE glc:job_error(Module). #+END_EXAMPLE

Return the number of job inputs for this query module. #+BEGIN_EXAMPLE glc:job_input(Module). #+END_EXAMPLE

Return the amount of time jobs took for this query module. #+BEGIN_EXAMPLE glc:job_time(Module). #+END_EXAMPLE

  • Some Tips & Tricks
    • This is really just a drop in the bucket.

Return the average time jobs took for this query module. #+BEGIN_EXAMPLE glc:job_time(Module) / glc:job_input(Module) / 1000000. #+END_EXAMPLE

Return the query combining the conditional logic of multiple modules #+BEGIN_EXAMPLE glc_lib:reduce(glc:all([Module1:info('query'), Module2:info('query')]). #+END_EXAMPLE

Return all statistics from this query module. #+BEGIN_EXAMPLE glc:info(Module). #+END_EXAMPLE

  • Build

#+BEGIN_EXAMPLE $ ./rebar compile #+END_EXAMPLE

or

#+BEGIN_EXAMPLE $ make #+END_EXAMPLE

  • CHANGELOG 0.1.9
  • Add support for running jobs

0.1.8

  • Add support for not equal

0.1.7

  • Support multiple functions specified using with/2
  • Add support for greater than or less than operators
  • Add state storage option for output events or lookup

0.1.7

  • Add job execution and timings
  • Add state storage option

0.1.7

  • Add job execution and timings
  • Add state storage option

0.1.6

  • Add notfound event matching

0.1.5

  • Rewrite to make highly crash resilient
    • per module supervision
    • statistics data recovery
  • Add wildcard event matching
  • Add reset counters

Elixir Resources

are all listed below.

Resources

listed to get explored on!!

Made with โค๏ธ

to provide different kinds of informations and resources.