trigger_agent.rb 3.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. module Agents
  2. class TriggerAgent < Agent
  3. cannot_be_scheduled!
  4. VALID_COMPARISON_TYPES = %w[regex field<value field<=value field==value field>=value field>value]
  5. description <<-MD
  6. Use a TriggerAgent to watch for a specific value in an Event payload.
  7. The `rules` array contains hashes of `path`, `value`, and `type`. The `path` value is a dotted path through a hash in [JSONPaths](http://goessner.net/articles/JsonPath/) syntax.
  8. The `type` can be one of #{VALID_COMPARISON_TYPES.map { |t| "`#{t}`" }.to_sentence} and compares with the `value`.
  9. All rules must match for the Agent to match. The resulting Event will have a payload message of `message`. You can include extractions in the message, for example: `I saw a bar of: <foo.bar>`
  10. Set `expected_receive_period_in_days` to the maximum amount of time that you'd expect to pass between Events being received by this Agent.
  11. MD
  12. event_description <<-MD
  13. Events look like this:
  14. { :message => "Your message" }
  15. MD
  16. def validate_options
  17. unless options[:expected_receive_period_in_days].present? && options[:message].present? && options[:rules].present? &&
  18. options[:rules].all? { |rule| rule[:type].present? && VALID_COMPARISON_TYPES.include?(rule[:type]) && rule[:value].present? && rule[:path].present? }
  19. errors.add(:base, "expected_receive_period_in_days, message, and rules, with a type, value, and path for every rule, are required")
  20. end
  21. end
  22. def default_options
  23. {
  24. :expected_receive_period_in_days => "2",
  25. :rules => [{
  26. :type => "regex",
  27. :value => "foo\\d+bar",
  28. :path => "topkey.subkey.subkey.goal",
  29. }],
  30. :message => "Looks like your pattern matched in '<value>'!"
  31. }
  32. end
  33. def working?
  34. last_receive_at && last_receive_at > options[:expected_receive_period_in_days].to_i.days.ago
  35. end
  36. def receive(incoming_events)
  37. incoming_events.each do |event|
  38. match = options[:rules].all? do |rule|
  39. value_at_path = Utils.value_at(event[:payload], rule[:path])
  40. case rule[:type]
  41. when "regex"
  42. value_at_path.to_s =~ Regexp.new(rule[:value], Regexp::IGNORECASE)
  43. when "field>value"
  44. value_at_path.to_f > rule[:value].to_f
  45. when "field>=value"
  46. value_at_path.to_f >= rule[:value].to_f
  47. when "field<value"
  48. value_at_path.to_f < rule[:value].to_f
  49. when "field<=value"
  50. value_at_path.to_f <= rule[:value].to_f
  51. when "field==value"
  52. value_at_path.to_s == rule[:value].to_s
  53. else
  54. raise "Invalid :type of #{rule[:type]} in TriggerAgent##{id}"
  55. end
  56. end
  57. if match
  58. create_event :payload => { :message => make_message(event[:payload]) } # Maybe this should include the
  59. # original event as well?
  60. end
  61. end
  62. end
  63. end
  64. end