Summary
You should use Cisco's Embedded Syslog Manager. ESM can dynamically modify or throttle syslog messages when they are generated on the router.
I built an example (see bottom of answer) of how to rate-limit configuration messages within a test time window; for the purposes of this demo, I substituted [regexp {CONFIG} $::orig_msg]
instead of [regexp {FAN_LOW_RPM} $::orig_msg]
so I could illustrate rate-limiting messages like %SYS-5-CONFIG_I: Configured from console by vty0
.
I edited the tcl script at the bottom of the answer with [regexp {CONFIG} $::orig_msg]
, and tftp'd the script into flash...
DEN-EDGE-02#copy tftp://172.16.1.5/filterSyslog.tcl flash:
Destination filename [filterSyslog.tcl]?
%Warning:There is a file already existing with this name
Do you want to over write? [confirm]
Accessing tftp://172.16.1.5/filterSyslog.tcl...
Loading filterSyslog.tcl from 172.16.1.5: !
[OK - 684 bytes]
684 bytes copied in 0.104 secs (6577 bytes/sec)
DEN-EDGE-02#
Then I configured my router with the name of the script, and the syslog server's address (172.16.1.5).
logging filter flash:filterSyslog.tcl
logging trap debugging
logging host 172.16.1.5 vrf mgmtVrf filtered
Now when you go into configuration mode on the router, the syslog messages are rate-limited.
[mpenning@tsunami tftpboot]$ sudo tshark -ni eth0 udp and host 172.16.1.204
Running as user "root" and group "root". This could be dangerous.
Capturing on eth0
3.472614 172.16.1.204 -> 172.16.1.5 Syslog 177 LOCAL7.NOTICE: 278: Apr 21 05:37:58.189
CDT: %SYS-5-CONFIG_I: Configured from console by vty0 (172.16.1.5) - This message was
rate-limited by ESM
How it works
The ESM script at the bottom of the answer rate-limits FAN_LOW_RPM
messages. The example leverages the fact that NVMON-4-FAN_LOW_RPM
messages are sent every 30 seconds. For simplicity, I use an absolute 30-second window between 23:59:30 and 23:59:59 to rate-limit the messages. This script assumes the syslogs are sent at a constant rate, and are not intermittent. In the attached script, I use timestamps in HHMMSS
(24-hour) format so they would map easily to integers.
When a syslog message is ready to be sent, IOS stores it in $::orig_msg
. I just built a quick series of if .. else
clauses to detect whether the syslog message:
- Matches the regular expression (in this case,
FAN_LOW_RPM
)
- Occurs in the 30-second window between 23:59:30 and 23:59:59 (inclusive)
If the message contains FAN_LOW_RPM
and is within the time window, the script sends the message. Other messages containing FAN_LOW_RPM
messages are not sent. All other syslogs are sent (because we only want to silence the noisy messages).
FYI, for simplicity I intentionally avoided persisting timestamp values between the last NVMON-4-FAN_LOW_RPM
syslog message seen, although someone could do that too.
ESM syslog rate-limit script:
Save this file in flash as flash:filterSyslog.tcl
## Filename: filterSyslog.tcl
proc forceInteger { x } {
set count [scan $x %d%s n rest]
if { $count <= 0 || ( $count == 2 && ![string is space $rest] ) } {
# This is an error
return "-1"
}
return $n
}
set time_start 235900
set time_end 235959
# See http://wiki.tcl.tk/498 for information about TCL's strange number-handling
set timestamp [forceInteger [clock format [clock seconds] -format %H%M%S]]
### Modify the regexp below and use any message you want to rate-limit...
if { [regexp {FAN_LOW_RPM} $::orig_msg] } {
if {($time_start <= $timestamp) && ($timestamp <= $time_end)} {
# Send syslog messages inside the $time_start and $time_end
return "$::orig_msg - This message was rate-limited by ESM"
} else {
# Drop syslog messages outside $time_start to $time_end
return ""
}
} else {
# Return all other syslog messages as usual
return $::orig_msg
}
Best Answer
Alright, so
doesn't pass arguments to the script - had to switch to
which does, HOWEVER...
EEM actions are unable to capture beyond a newline from a variable. I did find a way out though - trim the newline from
$_syslog_msg
(newline is the first char) and assign to a new variable.Here's the end-to-end solution:
$_string_result
is an EEM built-in variable that collects the output of string trimleftFrom http://www.cisco.com/c/en/us/td/docs/ios-xml/ios/eem/command/eem-cr-book/eem-cr-a2.html:
The above is actually incomplete/misleading/or Cisco has no idea how the language they picked works:
string trimleft
without a second argument trims space, tab, newline, and CR not just white space (See this: http://wiki.tcl.tk/10177).sendevent.tcl
Result
GitHub repo here (code complete): https://github.com/snobu/cisco-syslog-over-http