diff --git a/EcAlerter.h b/EcAlerter.h index cd77508..e34d951 100644 --- a/EcAlerter.h +++ b/EcAlerter.h @@ -76,6 +76,16 @@ * whose duration in minutes is less than the supplied integer value. * If this is not specified, messages of any duration may match. * + * ReminderAbove + * For [EcAlarm] messages, this may be used to match any message + * for an alarm which has triggered more than the specified number of + * alerts. + * + * ReminderBelow + * For [EcAlarm] messages, this may be used to match any message + * for an alarm which has triggered more than the specified number of + * alerts. + * * SeverityCode * For [EcAlarm] messages, this may be used to match an integer alarm * severity code (one of the EcAlarmSeverity enumerated type values). @@ -177,6 +187,9 @@ * The number of hours for which an alarm has been active. * Minutes * The number of minutes in the hour for. + * Reminder + * The count of alerts previously sent for the alarm represented + * by this message (not present if this is not an alarm). * *

The Log array specifies a list of log destinations which are * normally treated as filenames (stored in the standard log directory). @@ -313,6 +326,9 @@ * indicated in the final argument. The alarm may be may 'cleared' by a * later event with the same identfier and with the severity set to * EcAlarmSeverityCleared.
+ * The reminder field counts the number of copies of an alarm previously + * sent to the alerting system, and should be set to -1 if the alert is + * not an alarm.
* The use of an empty string as an identifier is permitted for events which * should not be buffered, but which will never be matched by a clear. *

@@ -331,7 +347,8 @@ andServer: (NSString*)serverName timestamp: (NSDate*)timestamp identifier: (NSString*)identifier - severity: (int)severity; + severity: (int)severity + reminder: (int)reminder; /**

This method handles error/alert messages. It is able to handle * multiple (newline separated messages. diff --git a/EcAlerter.m b/EcAlerter.m index 609f68e..fbb34bf 100644 --- a/EcAlerter.m +++ b/EcAlerter.m @@ -405,6 +405,7 @@ replaceFields(NSDictionary *fields, NSString *template) timestamp: (NSDate*)timestamp identifier: (NSString*)identifier severity: (int)severity + reminder: (int)reminder { if (nil == identifier) { @@ -448,12 +449,17 @@ replaceFields(NSDictionary *fields, NSString *template) forKey: @"SeverityCode"]; [m setObject: severityText forKey: @"SeverityText"]; [m setObject: [timestamp description] forKey: @"Timestamp"]; - [m setObject: [NSString stringWithFormat: @"%d", duration] - forKey: @"Duration"]; + if (reminder >= 0) + { + [m setObject: [NSString stringWithFormat: @"%d", reminder] + forKey: @"Reminder"]; + } if ([identifier length] > 0) { [m setObject: identifier forKey: @"Identifier"]; } + [m setObject: [NSString stringWithFormat: @"%d", duration] + forKey: @"Duration"]; [m setObject: [NSString stringWithFormat: @"%d", duration / 60] forKey: @"Hours"]; [m setObject: [NSString stringWithFormat: @"%02d", duration % 60] @@ -477,21 +483,48 @@ replaceFields(NSDictionary *fields, NSString *template) { continue; // Not a match. } - s = [d objectForKey: @"SeverityCode"]; - if (s != nil && [s intValue] != severity) + + /* This can be used to decide whether an alert is + * for an alarm or not. + */ + e = [d objectForKey: @"SeverityTextRegex"]; + if (e != nil && [e match: severityText] == nil) { continue; // Not a match. } - s = [d objectForKey: @"DurationAbove"]; - if (s != nil && duration <= [s intValue]) + + /* The next set are performed only for alarms, + * since a non-alarm can never match them. + */ + if (reminder >= 0) { - continue; // Not a match. - } - s = [d objectForKey: @"DurationBelow"]; - if (s != nil && duration >= [s intValue]) - { - continue; // Not a match. + s = [d objectForKey: @"SeverityCode"]; + if (s != nil && [s intValue] != severity) + { + continue; // Not a match. + } + s = [d objectForKey: @"DurationAbove"]; + if (s != nil && duration <= [s intValue]) + { + continue; // Not a match. + } + s = [d objectForKey: @"DurationBelow"]; + if (s != nil && duration >= [s intValue]) + { + continue; // Not a match. + } + s = [d objectForKey: @"ReminderAbove"]; + if (s != nil && reminder <= [s intValue]) + { + continue; // Not a match. + } + s = [d objectForKey: @"ReminderBelow"]; + if (s != nil && reminder >= [s intValue]) + { + continue; // Not a match. + } } + e = [d objectForKey: @"ServerRegex"]; if (e != nil && [e match: serverName] == nil) { @@ -502,11 +535,6 @@ replaceFields(NSDictionary *fields, NSString *template) { continue; // Not a match. } - e = [d objectForKey: @"SeverityTextRegex"]; - if (e != nil && [e match: severityText] == nil) - { - continue; // Not a match. - } e = [d objectForKey: @"PatternRegex"]; if (e != nil && (match = [e match: text]) == nil) { @@ -774,7 +802,8 @@ replaceFields(NSDictionary *fields, NSString *template) andServer: serverName timestamp: timestamp identifier: (YES == immediate) ? (id)@"" : (id)nil - severity: EcAlarmSeverityIndeterminate]; + severity: EcAlarmSeverityIndeterminate + reminder: -1]; } } NS_HANDLER diff --git a/EcControl.m b/EcControl.m index 0690982..657bc41 100644 --- a/EcControl.m +++ b/EcControl.m @@ -50,7 +50,7 @@ static EcAlarmSinkSNMP *sink = nil; -static NSMutableDictionary *lastAlerted = nil; +static NSMutableDictionary *lastAlertInfo = nil; static NSTimeInterval pingDelay = 240.0; @@ -363,7 +363,9 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) name: (NSString*)n pass: (NSString*)p; - (void) reply: (NSString*) msg to: (NSString*)n from: (NSString*)c; -- (void) reportAlarm: (EcAlarm*)alarm severity: (EcAlarmSeverity)severity; +- (void) reportAlarm: (EcAlarm*)alarm + severity: (EcAlarmSeverity)severity + reminder: (int)reminder; - (void) reportAlarms; - (void) servers: (NSData*)d on: (id)s; @@ -398,14 +400,20 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) severity = [old perceivedSeverity]; if (severity <= alertAlarmThreshold) { - NSString *key; + NSDictionary *info; + NSString *key; key = [NSString stringWithFormat: @"%d", [old notificationID]]; - if (nil != [lastAlerted objectForKey: key]) + if (nil != (info = [lastAlertInfo objectForKey: key])) { - [lastAlerted removeObjectForKey: key]; - [self reportAlarm: old severity: EcAlarmSeverityCleared]; + int reminder; + + reminder = [[info objectForKey: @"Reminder"] intValue]; + [lastAlertInfo removeObjectForKey: key]; + [self reportAlarm: old + severity: EcAlarmSeverityCleared + reminder: reminder]; } } } @@ -1725,7 +1733,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) NSDictionary *alertConf = [[self cmdDefaults] dictionaryForKey: @"Alerter"]; NSString *host = [alertConf objectForKey: @"SNMPMasterAgentHost"]; NSString *port = [alertConf objectForKey: @"SNMPMasterAgentPort"]; - lastAlerted = [NSMutableDictionary new]; + lastAlertInfo = [NSMutableDictionary new]; sink = [[EcAlarmSinkSNMP alloc] initWithHost: host name: port]; result = [super ecRun]; @@ -1964,7 +1972,9 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) [self information: msg type: LT_AUDIT to: n from: c]; } -- (void) reportAlarm: (EcAlarm*)alarm severity: (EcAlarmSeverity)severity +- (void) reportAlarm: (EcAlarm*)alarm + severity: (EcAlarmSeverity)severity + reminder: (int)reminder { NSString *additional; NSString *component; @@ -2050,7 +2060,8 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) andServer: [alarm moProcess] timestamp: [alarm eventDate] identifier: identifier - severity: severity]; + severity: severity + reminder: reminder]; } - (void) reportAlarms @@ -2073,32 +2084,50 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) if (notificationID > 0 && severity <= alertAlarmThreshold) { + NSDictionary *info; NSDate *when; + int reminder; NSTimeInterval ti; ti = reminderInterval * 60.0; key = [NSString stringWithFormat: @"%d", notificationID]; [current setObject: alarm forKey: key]; - when = [lastAlerted objectForKey: key]; + info = [lastAlertInfo objectForKey: key]; + if (nil == info) + { + when = nil; + reminder = 0; + } + else + { + when = [info objectForKey: @"When"]; + reminder = [[info objectForKey: @"Reminder"] intValue]; + } if (nil == when || (ti > 0.0 && [now timeIntervalSinceDate: when] > ti)) { - [self reportAlarm: alarm severity: [alarm perceivedSeverity]]; - [lastAlerted setObject: now forKey: key]; + [self reportAlarm: alarm + severity: [alarm perceivedSeverity] + reminder: reminder]; + info = [NSDictionary dictionaryWithObjectsAndKeys: + now, @"When", + [NSNumber numberWithInt: reminder + 1], @"Reminder", + nil]; + [lastAlertInfo setObject: info forKey: key]; } } } /* Remove any alarms which no longer exist. */ - enumerator = [[lastAlerted allKeys] objectEnumerator]; + enumerator = [[lastAlertInfo allKeys] objectEnumerator]; while (nil != (key = [enumerator nextObject])) { alarm = [current objectForKey: key]; if (nil == alarm) { - [lastAlerted removeObjectForKey: key]; + [lastAlertInfo removeObjectForKey: key]; } } }