|
By popular demand, here are examples of how to configure Syslog via XML files to do various things. Whenever you see text in double-qotes, like this: "true" you should leave the quotes off when entering the text in the config file. The quotes are there to offset the text from the rest of the paragraph.
You can sanity-check a configuration file by handing it to the SyslogXML from a command line, like this:
java com.protomatter.syslog.xml.SyslogXML config-file |
The file will be parsed, loaded and used to configure Syslog. It will then be printed back out to the console after having all default values for unspecified parameters filled in. It's also a nice way to re-format an otherwise ugly config file.
The default Syslog configuration looks like this:
<?xml version="1.0" encoding="UTF-8"?> <Syslog defaultMask="WARNING"> <Logger name="PrintWriterLog.err" class="com.protomatter.syslog.PrintWriterLog"> <Format class="com.protomatter.syslog.SimpleSyslogTextFormatter"> <showChannel>false</showChannel> <showThreadName>false</showThreadName> <showHostName>false</showHostName> <dateFormat>MM/dd/yyyy HH:mm:ss</dateFormat> <dateFormatCacheTime>1000</dateFormatCacheTime> <dateFormatTimeZone>America/Denver</dateFormatTimeZone> </Format> <Policy class="com.protomatter.syslog.SimpleLogPolicy"> <channels>ALL_CHANNEL</channels> <logMask>INHERIT_MASK</logMask> </Policy> <stream>System.err</stream> </Logger> </Syslog> |
Configuration files for Syslog are composed of a <Syslog> tag which contains one or more <Logger> tags. Each <Logger> tag contains a <Format> tag, a <Policy> tag and logger-specific tags.
In the above example, the <Syslog> tag is colored black, the <Format> tag is colored blue, the <Policy> tag is colored green, and the logger-specific tags are colored brown. Those conventions will be used throughout this document.
Throughout this document, I'll give examples of configurations for each "chunk" that can be assembled into complete configurations.
There's not really a lot of configuration to do with this tag. You can set the defaultMask and hostname attributes, and that's it.
The hostname attribute is required if you are using the DatabaseLog logger, which is discussed later. Syslog will attempt to set this value to whatever the local host thinks its name is, but it should be explicitly set on systems that are hosting multiple applications on multiple IP addresses, etc.
The defaultMask attribute sets the "system-wide" log mask that log policies can inherit. Log masks can be one of two things:
Here is an example of a <Syslog> tag with a default mask set to accept only INFO messages, and the hostname attribute set:
<?xml version="1.0" encoding="UTF-8"?> <Syslog defaultMask="=INFO" hostname="sillysailor.protomatter.com"> </Syslog> |
Each <Logger> tag can have an optional <Format> tag inside it. If it is omitted, the default is this:
<Format class="com.protomatter.syslog.SimpleSyslogTextFormatter"> <classWidth>20</classWidth> <channelWidth>15</channelWidth> <threadWidth>15</threadWidth> <hostWidth>15</hostWidth> <showChannel>false</showChannel> <showThreadName>false</showThreadName> <showHostName>false</showHostName> <dateFormat>MM/dd/yyyy HH:mm:ss</dateFormat> <dateFormatCacheTime>1000</dateFormatCacheTime> <dateFormatTimeZone>America/Denver</dateFormatTimeZone> </Format> |
The default formatting class is com.protomatter.syslog.SimpleSyslogTextFormatter which is all most people use.
The value for the dateFormatTimeZone is actually set to whatever TimeZone.getDefault() returns.
The value for the <dateFormat> element is anything that the java.text.SimpleDateFormat class will take as a date format string. Refer to the JavaDoc for that class to see all the format options. For instance, if you wanted the above format to look basically the same except for using a 12 hour time format rather than a 24 hour format, you would specify "MM/dd/yyyy hh:mm:ss a" as the format.
If you want the message channel name to appear in the output, set the value of the <showChannel> element to "true". The meaning of the other options is fairly obvious -- each of the "width" parameters are field width settings, and the "show" parameters toggle the visibility of certain fields.
The <Policy> tag for a logger determines what messages will be received by the logger.
The default <Policy> tag is as follows:
<Policy class="com.protomatter.syslog.SimpleLogPolicy"> <channels>ALL_CHANNEL</channels> <logMask>INHERIT_MASK</logMask> </Policy> |
The default log policy class is the com.protomatter.syslog.SimpleLogPolicy. This configuration specifies that the logger will receive messages on any channel, and will inherit its mask from Syslog itself. This means that whatever the defaultMask attribute of the <Syslog> tag is set to will be used as the mask for this logger.
Let's say that you wanted to have the logger only listen to the channel named "com.yourcompany.admin" channel. You would use the following configuration (changes in red):
<Policy class="com.protomatter.syslog.SimpleLogPolicy"> <channels>com.yourcompany.admin</channels> <logMask>INHERIT_MASK</logMask> </Policy> |
You can also specify a list of channels (commas and spaces are used as separators, so don't use them in channel names), like this:
<Policy class="com.protomatter.syslog.SimpleLogPolicy"> <channels>com.yourcompany.admin, com.yourcompany.user</channels> <logMask>INHERIT_MASK</logMask> </Policy> |
The other thing the default policy can do is filter messages based on their level (or severity as it is sometimes called). The log severities are (from least to most severe): DEBUG, INFO, WARNING, ERROR, FATAL.
If you specify the mask as the name of a level (like "WARNING"), all messages at or above that level will be received by the logger. If you want to only have the logger receive messages at a set of levels (let's say INFO and WARNING) but not any other levels, you can specify a comma-separated list of level names with an "=" prepended to the name. Consider this:
<Policy class="com.protomatter.syslog.SimpleLogPolicy"> <channels>ALL_CHANNEL</channels> <logMask>=INFO, =WARNING</logMask> </Policy> |
That configuration will log messages coming in on any channel at the INFO or WARNING levels.
Another policy class that comes with Syslog is the com.protomatter.syslog.PerClassPolicy, which allows you to specify different channel lists and levels to be logged by messages coming from different classes. Its configuration can be pretty complex. The basic look of this policy's configuration is:
<Policy class="com.protomatter.syslog.PerClassPolicy"> <channels>ALL_CHANNEL</channels> <logMask>INHERIT_MASK</logMask> <PolicyGroup> <channels>ALL_CHANNEL</channels> <logMask>INHERIT_MASK</logMask> <!-- specify explicit class names --> <className>some.class.Name</className> <className>some.other.class.Name</className> <!-- specify Perl5 regular expressions matches against class names --> <classPattern>some.class.*</classPattern> <classPattern>some.foo.class.*</classPattern> </PolicyGroup> <!-- add more PolicyGoup elements as needed --> </Policy> |
The basic way that this works is that the policy asks each policy group in turn if a given message should be logged. If any of those groups says yes, the message is sent to the logger. If none of the groups gives its blessing, the policy asks itself (it is a subclass of SimpleLogPolicy) if the message should be logged. This means that the channel list and log mask for the policy itself is used.
Each policy group has its own channel list and log mask. It also has a list of class names, and Perl5 regular expressions. If the message passes the channel and mask test, the name of the class making the log request is compared against the list of explicit class names and the list of Perl5 regular expressions. You don't have to specify any explict class names or regular expressions, but it makes sense to have at least one.
So, if that still sounds complicated, let's try an example. The following example will:
<Policy class="com.protomatter.syslog.PerClassPolicy"> <channels>com.yourcompany.admin</channels> <logMask>WARNING</logMask> <PolicyGroup> <channels>com.yourcompany.jibber, com.yourcompany.jabber</channels> <logMask>=INFO, =ERROR</logMask> <className>com.protomatter.blah.BlahBlah</className> <className>com.protomatter.blah.FooBar</className> </PolicyGroup> <PolicyGroup> <channels>com.yourcompany.user</channels> <logMask>DEBUG</logMask> <className>com.protomatter.foo.BazBuz</className> <classPattern>com.yourcompany.user.*</classPattern> </PolicyGroup> <!-- add more PolicyGoup elements as needed --> </Policy> |
As you can see, this policy can be extremely picky about what it pays attention to. This is really only useful if you are having problems with a certain class and want to be more verbose about logging messages coming from it. Be aware that if you use the patterns, it's fairly slow because it is using the ORO regular expression package to match class names. It's generally better to use the SimpleLogPolicy if you can.
Syslog also offers a the PerChannelPolicy, which is like the PerClassPolicy with "class" replaced with "channel" -- it offers a great deal of flexability where channels are used extensively. Please refer to the JavaDoc for PerChannelPolicy and its XML configuration class for configuration information.
This logger writes to either standard out or standard error. It's configuration looks like this:
<Logger name="loggerName" class="com.protomatter.syslog.PrintWriterLog"> <!-- format declaration --> <!-- policy declaration --> <stream>System.err</stream> </Logger> |
This one will write to standard error. If you want it to write to standard out, replace "System.err" with "System.out".
This logger simply writes to a file on the filesystem. It's configuration looks like this:
<Logger name="loggerName" class="com.protomatter.syslog.FileLog"> <!-- format declaration --> <!-- policy declaration --> <fileName>path/to/file.log</fileName> <append>true</append> <autoFlush>true</autoFlush> </Logger> |
The path specified can either be a an absolute path like "/var/log/blah.log" or a relative path like "logs/blah.log" in which case the file is relative to where the Java VM was started.
If <autoFlush> is set to true, then the stream going to the file is flushed each time a message is received by the logger. If it's set to false then output to the file is buffered. Buffering output is much faster if there's lots of log messages, but it may also appear that the logger isn't writing to the file at times because the messages are waiting in the buffer.
If <append> is set to true, then any existing file will be appended to when the logger starts writing. If it's set to false an existing file will be clobbered by the logger when it starts writing.
This logger writes to a file, and rotates that file at certain intervals. It can be set to rotate when the minute, hour day or month changes. It's important to note that this doesn't mean that an hour after the application starts it'll roll the log -- it means that when 9:59pm turns to 10:00pm it'll rotate.
Its configuration looks like this:
<Logger name="loggerName" class="com.protomatter.syslog.TimeRolloverLog"> <!-- format declaration --> <!-- policy declaration --> <baseName>path/to/log-</baseName> <nameFormat>yyyy.MM.dd-HH</nameFormat> <extension>.txt</extension> <roll>ROLL_HOURLY</roll> <append>true</append> <autoFlush>true</autoFlush> </Logger> |
The name of the file that the logger writes to is the basename concatenated with the time the log was started (formatted with the date format given in <nameFormat>) concatenated with the extension. Given the above example, if the log was started at 9:00am on October 13, 2001, the log file would be named "path/to/log-2001.10.13.00.txt"
The value for <roll> is either ROLL_MINUTELY, ROLL_HOURLY, ROLL_DAILY, or ROLL_MONTHLY. It should be obvious what each of these mean.
The <append> and <autoFlush> parameters behave the same way as they do in the FileLog logger.
This logger writes to a file, and rotates that file before it gets to a certain size. Its configuration looks like this:
<Logger name="loggerName" class="com.protomatter.syslog.LengthRolloverLog"> <!-- format declaration --> <!-- policy declaration --> <baseName>path/to/log-</baseName> <extension>.txt</extension> <rollsize>1048576</rollsize> <autoFlush>true</autoFlush> </Logger> |
The name of the file that the logger writes to is the basename concatenated with a number concatenated with the extension. Given the above example, the log file would be named "path/to/log-12.txt" if there were already logs number 1 to 11 present in that directory. When the logger starts writing or rolls the log, it looks in that directory to see what other files are present and picks the next number.
The value for <rollsize> is the size (in bytes) that the log should not be larger than. The above configuration will roll the file before it gets to be 1MB in size.
The <autoFlush> parameter behaves the same way as it does in the FileLog logger.
To be honest, most people prefer the TimeRolloverLog to this one.
This logger writes messages into a database table. Its configuration looks like this:
<Syslog defaultMask="INFO" hostname="sillysailor.protomatter.com"> <Logger name="loggerName" class="com.protomatter.syslog.DatabaseLog"> <!-- The <Format> tag is included here, as it is used to set field truncation sizes. --> <Format class="com.protomatter.syslog.SimpleSyslogTextFormatter"> <classWidth>128</classWidth> <channelWidth>32</channelWidth> <threadWidth>32</threadWidth> <hostWidth>32</hostWidth> </Format> <!-- policy declaration --> <driver>oracle.jdbc.driver.OracleDriver</driver> <url>jdbc:oracle:thin:@database-server:1521:ORCL</url> <messageWidth>255</messageWidth> <detailWidth>4000</detailWidth> <statementAdapter> com.protomatter.syslog.StringDatabaseLogStatementAdapter </statementAdapter> <ConnectionProperties> <property> <name>user</name> <value>some-user-name</value> </property> <property> <name>password</name> <value>some-password</value> </property> </ConnectionProperties> </Logger> </Syslog> |
That example will connect to an Oracle database on the database-server machine as the some-user-name user using the some-password password. It will use the Oracle thin driver. Other connection properties will be driver-specific, so you'll need to consult the documentation for that driver to see what they are. The URL is also specific to your database driver.
By default, this logger will write to a database table called SYSLOG_LOG. You may want to have multiple loggers writing to the same database, but use different tables. If this is the case, you can use the <tablePrefix> parameter, like this:
<Syslog defaultMask="INFO" hostname="sillysailor.protomatter.com"> <Logger name="loggerName" class="com.protomatter.syslog.DatabaseLog"> <!-- The <Format> tag is included here, as it is used to set field truncation sizes. --> <Format class="com.protomatter.syslog.SimpleSyslogTextFormatter"> <classWidth>128</classWidth> <channelWidth>32</channelWidth> <threadWidth>32</threadWidth> <hostWidth>32</hostWidth> </Format> <!-- policy declaration --> <driver>oracle.jdbc.driver.OracleDriver</driver> <url>jdbc:oracle:thin:@database-server:1521:ORCL</url> <messageWidth>255</messageWidth> <detailWidth>4000</detailWidth> <statementAdapter> com.protomatter.syslog.StringDatabaseLogStatementAdapter </statementAdapter> <tablePrefix>MY_APP_</tablePrefix> <ConnectionProperties> <property> <name>user</name> <value>some-user-name</value> </property> <property> <name>password</name> <value>some-password</value> </property> </ConnectionProperties> </Logger> </Syslog> |
Note that the hostname attribute on the <Syslog> tag has been set. This logger requires that the hostname attribute be set, so that it can be written into the database.
This example would write to a table called MY_APP_SYSLOG_LOG. By default, the logger will make 5 attempts to write each record to the database. If all those attempts fail, the message will be written out to System.err with an explanation of the JDBC error that prevented it from writing the record to the database. You can change the number of retries by setting the <numRetries> parameter.
You may want to experiment with the different implementations of DatabaseLogStatementAdapter implementations depending on what database you're using and the data type you choose for the DETAIL column. Your choices are: StringDatabaseLogStatementAdapter, AsciiStreamDatabaseLogStatementAdapter, CharacterStreamDatabaseLogStatementAdapter, or something you write yourself (if you have to do this, please let me know and I can work with you to include it in a later release).
This logger writes log messages out as mail messages to some SMTP mail server. It does not work with MS Exchange Server if you have authentication turned on. It should work with pretty much any UNIX mail server.
Here's an example configuration:
<Logger name="loggerName" class="com.protomatter.syslog.MailLog"> <Format class="com.protomatter.syslog.SimpleSyslogTextFormatter" > <showChannel>true</showChannel> <showThreadName>true</showThreadName> <showHostName>true</showHostName> </Format> <!-- policy declaration --> <SubjectFormat class="com.protomatter.syslog.SimpleSyslogMailSubjectFormatter" > <showChannel>true</showChannel> <showThreadName>false</showThreadName> <showHostName>true</showHostName> </Format> <workQueue>mailQueue</workQueue> <server>your-smtp-server-name</server> <port>25</port> <html>false</html> <to>jim@yourcompany.com, george@yourcompany.com</to> <cc>operations@yourcompany.com</cc> <bcc>root@yourcompany.com</bcc> <from>syslog@project-name.yourcompany.com</from> <fromName>Syslog from some application</fromName> </Logger> </Syslog> |
This will send email to jim@yourcompany.com, george@yourcompany.com, CC it to operations@yourcompany.com and BCC it to root@yourcompany.com. The mail will appear to be from syslog@project-name.yourcompany.com, whose name will appear as "Syslog from some application" in the email client.
If you want Syslog to send out email in HTML format, use the following configuration:
<Logger name="loggerName" class="com.protomatter.syslog.MailLog"> <Format class="com.protomatter.syslog.SyslogHTMLMailFormatter" > <showChannel>true</showChannel> <showThreadName>true</showThreadName> <showHostName>true</showHostName> </Format> <!-- policy declaration --> <SubjectFormat class="com.protomatter.syslog.SimpleSyslogMailSubjectFormatter" > <showChannel>true</showChannel> <showThreadName>false</showThreadName> <showHostName>true</showHostName> </Format> <workQueue>mailQueue</workQueue> <server>your-smtp-server-name</server> <port>25</port> <html>false</html> <to>jim@yourcompany.com, george@yourcompany.com</to> <cc>operations@yourcompany.com</cc> <bcc>root@yourcompany.com</bcc> <from>syslog@project-name.yourcompany.com</from> <fromName>Syslog from some application</fromName> </Logger> |
This will send out fairly well formatted HTML email to each user.