blob: e905f9ff10912fa59ba3ca026027a41fc9ff6d4d [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<?oxygen RNGSchema="http://www.oasis-open.org/docbook/xml/5.0/rng/docbook.rng" type="xml"?>
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0">
<info>
<title>Operational Logging</title>
<author>
<orgname>Apache Software Foundation</orgname>
</author>
</info>
<chapter>
<title>Status Log Messages</title>
<para>This file was derivied from LogMessages used within the Java Broker and originally defined on:
<tag xlink:href="http://cwiki.apache.org/confluence/display/qpid/Status+Update+Design#StatusUpdateDesign-InitialStatusMessages">Apache Wiki</tag></para>
<sect1>
<title>Technical Notes:</title>
<para>The status log messages file is a standard Java Properties file so white space is respected at the end of
the lines. This file could be processed in a number of ways:</para>
<para>
<orderedlist>
<listitem>
<para>ResourceBundle</para>
<para>This file is loaded as a ResourceBundle. The en_US addition to the
file is the localisation. Additional localisations can be provided and
will automatically be selected based on the &lt;locale> value in the
config.xml. The default locale is en_US.</para>
</listitem>
<listitem>
<para>MessageFormat</para>
<para> Each entry is prepared with the Java Core MessageFormat methods.
Therefore most functionality you can do via MessageFormat can be done
here: </para>
<para><tag xlink:href="http://java.sun.com/javase/6/docs/api/java/text/MessageFormat.html">Java API for MessageFormat</tag></para>
<para>The caveat here is that only default String and number FormatTypes can
be used. This is due to the processing described in 3 below. If support
for date, time or choice is required then the GenerateLogMessages class
should be updated to provide support.</para>
</listitem>
<listitem>
<para>GenerateLogMessage/Velocity Macro</para>
<para>This is the only processing that this file goes through</para>
<orderedlist>
<listitem>
<para>Class Generation:</para>
<para>The GenerateLogMessage processes this file and uses the
velocity Macro to create classes with static methods to perform
the logging and give us compile time validation. </para>
</listitem>
<listitem>
<para>Property Processing</para>
<para>During the class generation the message properties ({x}) are
identified and used to create the method signature.</para>
</listitem>
<listitem>
<para>Option Processing</para>
<para>The Classes perform final formatting of the messages at
runtime based on optional parameters that are defined within the
message. Optional parameters are enclosed in square brackets
e.g. [optional].</para>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
</para>
<para><emphasis role="bold">Format Note:</emphasis></para>
<para> As mentioned earlier white space in this file is very important. One thing in
particular to note is the way MessageFormat performs its replacements. The
replacement text will totally replace the {xxx} section so there will be no addition
of white space or removal e.g. </para>
<programlisting><![CDATA[MSG = Text----{0}----]]>
</programlisting>
<para> When given parameter 'Hello' result in text: </para>
<programlisting><![CDATA[Text----Hello----]]>
</programlisting>
<para>For simple arguments this is expected however when using Style formats then it can
be a little unexpected. In particular a common pattern is used for number
replacements : {0,number,}. This is used in the Broker to display an Integer simply
as the Integer with no formatting. e.g new Integer(1234567) becomes the String
"1234567" which is can be contrasted with the pattern without a style format field :
{0,number} which becomes string "1,234,567".</para>
<para>What you may not expect is that {0,number, } would produce the String " 1234567"
note that the space after the ',' here has resulted in a space in front of the
number in the output.</para>
<para>More details on the SubformatPattern can be found on the API link above. To
provide fixed log messages as required by the Technical Specification:</para>
<para><tag xlink:href="http://cwiki.apache.org/confluence/display/qpid/Operational+Logging+-+Status+Update+-+Technical+SpecificationOperationalLogging-StatusUpdate-TechnicalSpecification-Howtoprovidefixedlogmessages">Operational Logging Tech Specification</tag></para>
<para>This file is processed by Velocity to create a number of classes that contain
static methods that provide LogMessages in the code to provide compile time
validation.</para>
<para>For details of what processing is done see GenerateLogMessages. </para>
<para>What a localiser or developer need know is the following: </para>
<para>The Property structure is important as it defines how the class and methods will
be built.</para>
</sect1>
<sect1>
<title>Class Generation</title>
<para> Each class of messages will be split in to their own &lt;Class>Messages.java.
Each logmessage file contains only one class of messages the &lt;Class> name is
derived from the name of the logmessages file e.g. &lt;Class&gt;_logmessages.properties.
</para>
</sect1>
<sect1>
<title>Property Format</title>
<para>The property format MUST adhere to the follow format to make it easier to use the
logging API as a developer but also so that operations staff can easily locate log
messages in the output.</para>
<para>The property file should contain entries in the following format:</para>
<programlisting><![CDATA[<Log Identifier,developer focused>=<Log Identifier,Operate focus>:<Log Message>]]>
</programlisting>
<para>eg:</para>
<programlisting><![CDATA[SHUTTING_DOWN = BRK-1003 : Shutting down : {0} port {1,number,}]]>
</programlisting>
<para>Note: the developer focused identifier will become a method name so only a valid
method name should be used. Currently only '-' are converted to '_'.</para>
<para>That said properties generate the logging code at build time so any error can be
easily identified.</para>
<para>The three character identifier show above in BRK-1003 should ideally be unique.
This is the only requirement, limiting to 3 characters is not required.</para>
<para>The current broker contains the following mappings:</para>
<para>
<table>
<title>Status Messages Mapping</title>
<tgroup cols="2">
<colspec colname="c1" colnum="1" colwidth="118.29pt"/>
<colspec colname="c2" colnum="2" colwidth="135.18pt"/>
<thead>
<row>
<entry>Class</entry>
<entry> Type</entry>
</row>
</thead>
<tbody>
<row>
<entry>Broker</entry>
<entry>BRK</entry>
</row>
<row>
<entry>Management Console</entry>
<entry>MNG</entry>
</row>
<row>
<entry>VirtualHost</entry>
<entry>VHT</entry>
</row>
<row>
<entry>MessageStore</entry>
<entry>MST</entry>
</row>
<row>
<entry>ConfigStore</entry>
<entry>CFG</entry>
</row>
<row>
<entry>TransactionLog</entry>
<entry>TXN</entry>
</row>
<row>
<entry>Connection</entry>
<entry>CON</entry>
</row>
<row>
<entry>Channel</entry>
<entry>CHN</entry>
</row>
<row>
<entry>Queue</entry>
<entry>QUE</entry>
</row>
<row>
<entry>Exchange</entry>
<entry>EXH</entry>
</row>
<row>
<entry>Binding</entry>
<entry>BND</entry>
</row>
<row>
<entry>Subscription</entry>
<entry>SUB</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</sect1>
<sect1>
<title>Property Processing</title>
<para>
Each property is then processed by the GenerateLogMessages class to identify
the number and type of parameters, {x} entries. Parameters are defaulted to
String types but the use of FormatType number (e.g.{0,number}) will result
in a Number type being used. These parameters are then used to build the
method parameter list. e.g:
</para>
<para>Property:</para>
<programlisting><![CDATA[SHUTTING_DOWN = BRK-1003 : Shuting down : {0} port {1,number,}]]></programlisting>
<para>becomes Method:</para>
<programlisting><![CDATA[public static LogMessage SHUTTING_DOWN(String param1, Number param2)]]>
</programlisting>
<para>
This improves our compile time validation of log message content and
ensures that change in the message format does not accidentally cause
erroneous messages.</para>
</sect1>
<sect1>
<title>Option Processing</title>
<para>
Options are identified in the log message as being surrounded by square
brackets ([ ]). These optional values can themselves contain parameters
however nesting of options is not permitted. Identification is performed on
first matching so given the message:
</para>
<programlisting><![CDATA[Msg = Log Message [option1] [option2] ]]></programlisting>
<para>
Two options will be identified and enabled to select text 'option1' and
'option2'.
</para>
<para>
The nesting of a options is not supported and will provide
unexpected results. e.g. Using Message:
</para>
<programlisting><![CDATA[Msg = Log Message [option1 [sub-option2]] ]]></programlisting>
<para>
The options will be 'option1 [sub-option2' and 'sub-option2'. The first
option includes the second option as the nesting is not detected.
</para>
<para>
The detected options are presented in the method signature as boolean options
numerically identified by their position in the message. e.g.
Property:
</para>
<programlisting><![CDATA[ CON-1001 = Open : Client ID {0} [: Protocol Version : {1}] ]]></programlisting>
<para>becomes Method:</para>
<programlisting><![CDATA[ public static LogMessage CON_1001(String param1, String param2, boolean opt1) ]]></programlisting>
<para>
The value of 'opt1' will show/hide the option in the message. Note that
'param2' is still required however a null value can be used if the optional
section is not desired.
</para>
<para>
Again here the importance of white space needs to be highlighted.
Looking at the QUE-1001 message as an example. The first thought on how this
would look would be as follows:
</para>
<programlisting><![CDATA[ QUE-1001 = Create : Owner: {0} [AutoDelete] [Durable] [Transient] [Priority: {1,number,}] ]]></programlisting>
<para>
Each option is correctly defined so the text that is defined will appear when
selected. e.g. 'AutoDelete'. However, what may not be immediately apparent is
the white space. Using the above definition of QUE-1001 if we were to print
the message with only the Priority option displayed it would appear as this:
</para>
<programlisting><![CDATA[ "Create : Owner: guest Priority: 1" ]]></programlisting>
<para>
Note the spaces here in between gues and Priority are present because only the text between the brackets
has been removed.
</para>
<para>
Each option needs to include white space to correctly format the message. So
the correct definition of QUE-1001 is as follows:
</para>
<programlisting><![CDATA[ QUE-1001 = Create : Owner: {0}[ AutoDelete][ Durable][ Transient][ Priority: {1,number,}] ]]></programlisting>
<para>
Note that white space is included with each option and there is no extra
white space between the options. As a result the output with just Priority
enabled is as follows:
</para>
<programlisting><![CDATA[ "Create : Owner: guest Priority: 1" ]]></programlisting>
</sect1>
</chapter>
</book>