Skip to content

Instantly share code, notes, and snippets.

@lpar
Last active August 29, 2016 16:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lpar/1092788 to your computer and use it in GitHub Desktop.
Save lpar/1092788 to your computer and use it in GitHub Desktop.
Ruby code to pump IBM Lotus Domino server logs to regular Unix syslog
#!/usr/bin/env ruby
# encoding: UTF-8
# Script to take IBM Lotus Domino console input on stdin, and send it to
# syslog.
#
# Allows you to do all your logging via syslog, rather than having to
# keep weeks of data in log.nsf.
#
# In rsyslog, filter like this:
# :programname, isequal, "domino" -/var/log/domino.log
#
# See https://gist.github.com/1092764 for how to incorporate this into
# Domino startup using Daniel Nashed's rc_domino scripts.
#
# This code is placed in the public domain in order to aid integration of IBM
# software with standard POSIX logging.
require 'syslog'
require 'date'
# Syslog ident to use.
SYSLOG_IDENT = 'domino'
# The strptime format used to parse Domino timestamps
# Note that we add the (missing) current time zone before parsing them,
# hence the %z at the end.
TIMESTAMP_STRPTIME = '%m/%d/%Y %I:%M:%S %p %z'
# The regular expression used to spot thread IDs prepended to console output
LOG_THREADID = Regexp.new(/^\[([\d:-]+)\]\s+/)
# The regular expression used to parse the rest of the line
LOG_REGEXP = Regexp.new(/^(\d\d\/\d\d\/\d\d\d\d \d\d:\d\d:\d\d [AP]M){0,1}\s+(.*)$/)
# Number of seconds by which the parsed timestamp can differ from what
# we think the system date/time is, before we append the parsed timestamp
# to the end of the syslog message
TIMESTAMP_ACCURACY = 2
# Strings and regexps used to work out severity
# LOG_EMERG - System is unusable
# LOG_ALERT - Action needs to be taken immediately
# LOG_CRIT - A critical condition has occurred
# LOG_ERR - An error occurred
# LOG_WARNING - Warning of a possible problem
# LOG_NOTICE - A normal but significant condition occurred
# LOG_INFO - Informational message
# LOG_DEBUG - Debugging information
SEVERITIES = {
Regexp.new(/Access control is set in .* to not allow replication from/) => Syslog::LOG_WARNING,
Regexp.new(/Access control is set in .* to not replicate/) => Syslog::LOG_WARNING,
"not authorized to" => Syslog::LOG_WARNING,
"Unable to find path to server." => Syslog::LOG_CRIT,
"No route is known from this host to " => Syslog::LOG_CRIT,
"The server is not responding" => Syslog::LOG_CRIT,
"Server not reachable on Cluster Port" => Syslog::LOG_CRIT,
Regexp.new(/Full text operations on database .* which is not full text indexed/) => Syslog::LOG_WARNING,
Regexp.new(/ATTEMPT TO ACCESS SERVER by .* was denied/) => Syslog::LOG_ERR,
Regexp.new(/Directory Assistance could not/) => Syslog::LOG_ERR,
"Corrupt Data Exception" => Syslog::LOG_ERR,
"Couldn't find design note" => Syslog::LOG_ERR,
Regexp.new(/\berror\b/) => Syslog::LOG_ERR,
"Warning:" => Syslog::LOG_WARNING
}
def severity(text)
SEVERITIES.each_pair do |condition, severity|
if text.match(condition)
return severity
end
end
return Syslog::LOG_INFO
end
syslog = Syslog.open(SYSLOG_IDENT,
Syslog::LOG_NDELAY | Syslog::LOG_PID, Syslog::LOG_DAEMON)
begin
# Domino still writes its console output in Latin-1, so convert on the fly
input = STDIN.set_encoding('iso-8859-1:UTF-8')
while line = input.gets
now = DateTime.now
zone = now.strftime('%z')
line.gsub!(/\s\s+/, ' ')
line.chop!
m = LOG_THREADID.match(line)
if m
threadid = m[1]
line.sub!(LOG_THREADID, '')
else
threadid = nil
end
m = LOG_REGEXP.match(line)
if m
message = m[2]
if m[1]
dt = "#{m[1]} #{zone}"
dts = DateTime.strptime(dt, TIMESTAMP_STRPTIME)
tdiff = 86400 * (dts - now).abs
if tdiff > TIMESTAMP_ACCURACY
message << " [#{m[0]}]"
end
sev = severity(message)
else
sev = severity(message)
end
syslog.log(sev, "%s", message)
end
end
rescue => e
syslog.log(Syslog::LOG_CRIT, 'Ruby exception in %s: %s', $0, e.inspect)
e.backtrace.each {|line|
syslog.log(Syslog::LOG_DEBUG, "%s", line)}
end
@thampel
Copy link

thampel commented Aug 26, 2016

Why dont you use nartive Domino functions to write to syslog ?
Just create an event handler in events4.nsf to forward everything to Unix syslog.

@halr9000
Copy link

@lpar, I found this helpful today when a customer was looking to get their Domino logs in Splunk. Thanks for posting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment