anchor.diff:  
   Alerts are generated when an Alert Trigger fires, based on a set of defined conditions that have been matched, possibly more than once or have held true over a period of time. When fired the trigger can perform actions, typically but not limited to notifications (e-mail, sms, etc). Alerts then start moving through the Open, Acknowledged, Resolved life-cycle.  There are many options on triggers to help ensure that alerts are not generated too frequently, including ways of automatically disabling and enabling the trigger.
   
  -==== Events (Since 0.6.0.Final)
  -
  -As discussed abovem the number of alerts should be small in order to be manageable.  But it can be useful to capture interesting happenings in the monitored world. This is called an Event in Hawkular Alerts.  An event can be roughly thought of as an alert without lifecycle.  Like alerts, an event can be generated by a trigger but unlike an alert, it can also be injected directly via the API, so it is very easy for clients to insert events as desired.  And although trigger-generated events can define actions to be performed, in general an event does not need human intervention.  Instead, it is typically something that can contribute to an alert firing, help investigate an alert, or simply help understand system behavior.
  +==== Events
  +
  +As discussed above the number of alerts should be small in order to be manageable.  But it can be useful to capture interesting happenings in the monitored world. This is called an Event in Hawkular Alerts.  An event can be roughly thought of as an alert without lifecycle.  Like alerts, an event can be generated by a trigger but unlike an alert, it can also be injected directly via the API, so it is very easy for clients to insert events as desired.  And although trigger-generated events can define actions to be performed, in general an event does not need human intervention.  Instead, it is typically something that can contribute to an alert firing, help investigate an alert, or simply help understand system behavior.
   
   It is expected that the number of Events can be very large compared to the number of Alerts. Events (like Alerts), can be flexibly queried.
   
  
positive.code: ** X < 80% Y
  * String
  ** X starts with "ABC", X matches "A.*B"
  * Availability
  ** X is DOWN
  
  
negative.code: === AutoEnable
  
  A trigger can be set for AutoEnable.  If AutoEnable is true then when an alert is resolved, and if all alerts for the trigger are then resolved, the trigger will be enabled if it is currently disabled.  This ensures that the trigger will again go into firing mode, without needing to be manually enabled by the user. The default is false.
  
  === Source
  
  By default both Triggers and Data ignore "source".  This means that the dataIds defined on a trigger's conditions are matched against the dataIds on incoming data (within a tenant) and matching data is evaluated against the conditions.  It is possible to qualify triggers and data with a "source" such that a trigger only evaluates data having the same source.
  
  This mechanism is used automatically by <<Data-Driven Group Triggers>> but can be used manually as well.  If you find that data is better described using a combination source+id, as opposed to just id, then this approach may be appropriate.
  
  
  == Group Triggers
  
  It's often the case that the same alerting needs to be applied to all instances of the same thing.  For example, it may be useful to alert on "System Load > 80%" on 50 different CPUs.  It can be cumbersome to manage 50 individual triggers.
  
  A Group Trigger allows you to define a single trigger and then apply it to a group of logically similar things.  A group trigger could be used in the example above.  Then, a member could be added for each CPU.  The member triggers are basically managed copies of the group trigger.  Changes at the group level are pushed down to the members. So, to change "80%" to "85%", or to change autoDisable from false to true, only the group trigger must be changed.
  
  === Managing DataIds
  
  The group trigger is basically a template, it is not deployed.  Only the member triggers are deployed and actively evaluated because only the member triggers are associated with real dataIds on the conditions.  The group trigger uses "tokens" for the dataIds and each member, when defined, must provide a map of dataId token replacements.
  
  Using the example above, our group trigger would define a condition using a dataId token, like:
  
  [source,java]
  ----
  { type: "threshold",
    dataId: "SystemLoad",
    operator: "GT"
    threshold: "80.0"
  }
  ----
  
  When adding a member for a specific CPU, say CPU-1, we'd map the token to the real dataId, something like:
  
  [source,java]
  ----
  dataIdMap: {
    "SystemLoad":"CPU-1_SystemLoad"
  }
  ----
  
  Where "CPU-1_SystemLoad" reflects the actual id associated with system load data sent to alerts for CPU-1.
  
  When updating conditions at the group level it is necessary to supply dataId mappings for all of the existing members because the dataIds may have changed on the new condition set.
  
  
  === Orphans
  
  There are times when a particular group member may need to managed individually.  For example, if a single CPU is of particular concern it may be useful to change the threshold level on just that member.  It is possible to orphan a member trigger and manage it independently, while maintaining it's association with the group trigger.  It can be unorphaned at any time, and reset to the group settings.
  
  
  === Data-Driven Group Triggers
  
  [since 0.9.0.Final]
  
  Group triggers allow a common definition to be applied to logically similar members. For example, a group trigger could be defined for alerting on CPU SystemLoad and a member trigger would be added for every CPU, each a copy of the group trigger but working against the proper dataId(s) given the CPU instance. When a member is added a map from the group's [token] dataIds to the members [real] dataIds must be provided. And if updating conditions at the group level a map for each existing member must be provided. This makes sense, and is fine, but it can be tedious, or difficult to supply.
  
  It's not uncommon for the member-level dataIds to be a concatenation of id of the source member (e.g. a resourceId, CPU-1, etc) and the group level dataId token (SystemLoad). So you end up with member-level ids like 'CPU-1_SystemLoad' where the "source" is 'CPU-1' and the dataId is 'SystemLoad'.
  
  Data-Driven Group Triggers are able to add member triggers to a group automatically, one for each "source" of the same data. In other words, for a group trigger on CPU SystemLoad, add a member automatically for each source CPU reporting the 'SystemLoad' metric. By reporting data as a combination of source and dataId this should be possible. So, instead of reporting:
  
  [source,java]
  ----
  Data(id:cpu-1-Load, value:123)
  ---
  
  We'd want:
  
  [source,java]
  ----
  Data(source:cpu-1, id:Load, value:123)
  ---
  
  This would then relieve the client from having to add member triggers up front and instead assume that the group will grow as needed, based on the incoming data.
  
  Because dataIds are often defined upstream it is not always possible to supply Hawkular Alerts with data such that the source and id are separated.  But if possible this is a power ful approach.
  
  
  ==== Behavioral Notes
  
  A couple of notes about data-driven group triggers:
  
  * Each member trigger is associated with a single source and only considers data from that source.
  ** True for single and mult-condition triggers.
  * Condition changes in the group trigger will remove all member triggers.
  ** The members will then again be created as the data demands.
  * The <<Source>> mechanism can also be used with manually managed triggers, if desired.
  
  
  == Alert Lifecycle
  