trigger_agent.rb 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. module Agents
  2. class TriggerAgent < Agent
  3. cannot_be_scheduled!
  4. VALID_COMPARISON_TYPES = %w[regex !regex field<value 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. The `value` can be a single value or an array of values. In the case of an array, if one or more values match then the rule matches.
  10. 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>`
  11. 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.
  12. MD
  13. event_description <<-MD
  14. Events look like this:
  15. { "message": "Your message" }
  16. MD
  17. def validate_options
  18. unless options['expected_receive_period_in_days'].present? && options['message'].present? && options['rules'].present? &&
  19. options['rules'].all? { |rule| rule['type'].present? && VALID_COMPARISON_TYPES.include?(rule['type']) && rule['value'].present? && rule['path'].present? }
  20. errors.add(:base, "expected_receive_period_in_days, message, and rules, with a type, value, and path for every rule, are required")
  21. end
  22. end
  23. def default_options
  24. {
  25. 'expected_receive_period_in_days' => "2",
  26. 'rules' => [{
  27. 'type' => "regex",
  28. 'value' => "foo\\d+bar",
  29. 'path' => "topkey.subkey.subkey.goal",
  30. }],
  31. 'message' => "Looks like your pattern matched in '<value>'!"
  32. }
  33. end
  34. def working?
  35. last_receive_at && last_receive_at > options['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs?
  36. end
  37. def receive(incoming_events)
  38. incoming_events.each do |event|
  39. match = options['rules'].all? do |rule|
  40. value_at_path = Utils.value_at(event['payload'], rule['path'])
  41. rule_values = rule['value']
  42. rule_values = [rule_values] unless rule_values.is_a?(Array)
  43. match_found = rule_values.any? do |rule_value|
  44. case rule['type']
  45. when "regex"
  46. value_at_path.to_s =~ Regexp.new(rule_value, Regexp::IGNORECASE)
  47. when "!regex"
  48. value_at_path.to_s !~ Regexp.new(rule_value, Regexp::IGNORECASE)
  49. when "field>value"
  50. value_at_path.to_f > rule_value.to_f
  51. when "field>=value"
  52. value_at_path.to_f >= rule_value.to_f
  53. when "field<value"
  54. value_at_path.to_f < rule_value.to_f
  55. when "field<=value"
  56. value_at_path.to_f <= rule_value.to_f
  57. when "field==value"
  58. value_at_path.to_s == rule_value.to_s
  59. when "field!=value"
  60. value_at_path.to_s != rule_value.to_s
  61. else
  62. raise "Invalid type of #{rule['type']} in TriggerAgent##{id}"
  63. end
  64. end
  65. end
  66. if match
  67. create_event :payload => { 'message' => make_message(event[:payload]) } # Maybe this should include the
  68. # original event as well?
  69. end
  70. end
  71. end
  72. end
  73. end