Author: mcconnell Date: Sun May 30 18:29:30 2004 New Revision: 20671 Added: avalon/trunk/central/site/src/xdocs/products/runtime/system/logging/logkit/index.xml Modified: avalon/trunk/central/site/src/xdocs/products/runtime/reference/kernel/repository/hosts.xml avalon/trunk/runtime/versioning/avalon-util.ent Log:
Modified: avalon/trunk/central/site/src/xdocs/products/runtime/reference/kernel/repository/hosts.xml ============================================================================== --- avalon/trunk/central/site/src/xdocs/products/runtime/reference/kernel/repository/hosts.xml (original) +++ avalon/trunk/central/site/src/xdocs/products/runtime/reference/kernel/repository/hosts.xml Sun May 30 18:29:30 2004 @@ -33,7 +33,7 @@ <table> <tr><th>Element</th><th>Occurance</th><th>Description</th></tr> <tr> - <td>host</td><td>0..1</td> + <td>host</td><td>0..n</td> <td> <p>Declaration of a remote host. The value of the element is an http address of a server the implements the Maven Added: avalon/trunk/central/site/src/xdocs/products/runtime/system/logging/logkit/index.xml ============================================================================== --- (empty file) +++ avalon/trunk/central/site/src/xdocs/products/runtime/system/logging/logkit/index.xml Sun May 30 18:29:30 2004 @@ -0,0 +1,410 @@ +<!-- + Copyright 2004 The Apache Software Foundation + Licensed 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. +--> +<document> + <properties> + <author email="dev@avalon.apache.org">Avalon Development Team</author> + <title>Logkit - Whitepaper</title> + </properties> + <body> + <section name="Abstract"> + <p> + Logging is an integral component to any software development project. + During the development stages it offers a valuable source of debugging + information for the developer. During deployment it can provide + valuable operational data that allows administrators to diagnose + problems as they arise. This whitepaper describes the design and + implementation of LogKit. + </p> + </section> + <section name="Introduction"> + <p> + LogKit, began life as a facade for a more complex logging toolkit. + During development it was found that existing toolkits were complex and + difficult to use. A malformed logger configuration file could cause the + whole system to fail or the logging information to go into the void. + </p> + <p> + Over time it was discovered that the facade, while simple to use, + inherited many of the faults of the underlying logging toolkit. The + logging was slow and was impossible to dynamically reconfigure. + </p> + <p> + At this time the whole system was overhauled. Existing logging toolkits + were surveyed and user feedback was gathered from both developers and + administrators. The new toolkit focused on speed, reliability and + dynamic reconfiguration. It then added, at that time unique features, + for filtering log events, multiple listeners (aka LogTargets) per + category and delayed serialization of events. + </p> + </section> + <section name="Structure and Elements"> + <p> + The most basic components of LogKit are the Logger, the LogEvent and the + LogTarget. The Logger represents the client interface to the logging + system. The developer interacts with Logger to generate LogEvents. The + LogEvents are routed to a LogTarget. The LogTarget decides what to do + with the LogEvent, usually it is recorded to a file, a database or + transmitted over the network. + </p> + </section> + <section name="Priorities"> + <p> + One of the advantages of a logging toolkit is fine grain control over + which statements get printed. At some times during development you may + wish to enable all logging statements and at other times they may wish + to disable debug messages. It was from this need that the notion of of + Priorities were born. A Priority describes the urgency of a LogEvent. + Below is a list of priorities that are usable within the LogKit system + (extracted from the constants of class org.apache.log.Priority). + </p> + <ul> + <li> + <strong>DEBUG:</strong> + <br/> + Developer oriented messages, usually used during development of the + product. + </li> + <li> + <strong>INFO:</strong> + <br/> + Useful information messages such as state changes, client connection, + user login etc. + </li> + <li> + <strong>WARN:</strong> + <br/> + A problem or conflict has occurred but it may be recoverable, then + again it could be the start of the system failing. + </li> + <li> + <strong>ERROR:</strong> + <br/> + A problem has occurred but it is not fatal. The system will still + function. + </li> + <li> + <strong>FATAL_ERROR:</strong> + <br/> + Something caused whole system to fail. This indicates that an + administrator should restart the system and try to fix the problem + that caused the failure. + </li> + </ul> + <p> + The range of priorities is limited by design as past experience has + indicated more levels do not offer any significant advantage to the + user. + </p> + <p> + Each logger instance is associated with a Priority. This allows you to + limit each logger so that it only displays messages greater than a + certain priority. So if a DEBUG message occurred and the logger's + priority was WARN, the LogEvent would be suppressed. + </p> + <p> + A user can log at a certain priority by calling a method with matching + name and the message as a string. For instance to log at debug level + you would call logger.debug("My Message"). Similar methods exist for + info(), warn() and error(). There is also a set of similarly named + methods that take both a message string and an exception. + </p> + <p> + Where performance is critical it is often useful to check if a priority + is enabled before constructing the message. In many cases the + construction of the message is an expensive string operation and + conversion operation. In this case it is useful to know before you + create the message whether it will be logged. The pattern of the method + to check if a priority is enabled is "is<Priority>Enabled()". An + example use case is displayed below. + </p> + <source> +if( logger.isDebugEnabled() ) +{ + //Construct a message (expensive operation) + final String message = "Var1 value: " + var1 + "\tVar2 value: " + var2 + + "\tVar3 value: " + var3 + "."; + logger.debug( message ); +} + </source> + </section> + <section name="Categories"> + <p> + In a complex system it is often not enough to suppress logging based on + priority. For instance you may wish to log the network subsystem with + DEBUG priority while the simulator subsystem with WARN priority. To + accomplish this LogKit uses a concept termed Categories. Categories, + often called Channels, Subjects or Facilities, are a subdivision of the + logging namespace. + </p> + <p> + Each category is a name, made up of name components separated by a ".". + So a category named "network.interceptor.connected" is made up of three + name components "network", "interceptor" and "connected", ordered from + left to right. Every logger is associated with a category at creation. + </p> + <p> + LogKit takes it one step further and assumes that the namespace is + hierarchical. The left-most name component is the most generic category + while the right-most name component is the most specific. So + "network.interceptor.connected" is a child category of + "network.interceptor", which is in turn a child category of "network". + There is also a root category "" that is hidden inside the + org.apache.log.Hierarchy class. + </p> + <p> + The main reason for structuring logging namespace in a hierarchical + manner is to allow inheritance. A logger will inherit it's parent + priority if it has not been explicitly set. This allows you to set the + "network" logger to have INFO priority and unless the + "network.interceptor" has had it's priority set it will inherit the + INFO priority. + </p> + <p> + Unlike other logging toolkits, there is no performance penalty for + having deep hierarchies. Each logger caches a Priority to check against. + When a logger has it's logger set or unset, it updates the cached + version of it's child loggers. + </p> + </section> + <section name="Log Targets"> + <p> + In LogKit, LogTargets are the destination of LogEvents. Decoupling + LogEvent generation from handling allows developers to change + destinations of LogEvents dynamically or via configuration files. + Possible destinations include writing to a database, a file, an IRC + channel, a syslog server, an instant messaging client etc. + </p> + <p> + Like Priorities, it is often useful to allow LogTargets to be inherited + between loggers. Like Priority inheritance, LogTarget inheritance does + not suffer any runtime performance penalty. + </p> + <section name="Filters"> + <p> + Filters are a special kind of LogTarget. Instead of writing to an + output destination they are used to filter out LogEvents or modify + the LogEvents details and pass it on to another LogTarget. + </p> + <p> + This can be a useful feature when you assign multiple LogTargets to a + logger. For instance you may add two LogTargets to a logger, one which + writes LogEvents to a database and one which writes a message to the + administrators pager. However you may want to record all messages to + the database but only transmit FATAL_ERROR messages to pager. In this + case you would use a PriorityFilter to filter out non-FATAL_ERROR + messages for pager log target. + </p> + </section> + <section name="AsyncLogTarget"> + <p> + AsyncLogTarget is another kind of special LogTarget. It takes a log + event and copies it into a queue so that another thread can actually + write the LogEvent to another LogTarget. This is useful if logging to + a particular LogTarget is a slow operation (such as a MailLogTarget). + </p> + <p> + Below is a snippet of code that creates an AsyncLogTarget to write + messages in another thread. + </p> + <source> +LogTarget mySlowTarget = ...; +AsyncLogTarget asyncTarget = new AsyncLogTarget( mySlowTarget ); +Thread thread = new Thread( asyncTarget ); +thread.setPriority( Thread.MIN_PRIORITY ); +thread.start(); +logger.setLogTargets( new LogTarget[] { asyncTarget } ); + </source> + </section> + </section> + <section name="Formatters"> + <p> + LogTargets that write to a serial or unstructured store (ie filesystem + or network based LogTargets) need some method to serialize the LogEvent + before writing to the store. The most common way to serialize the + LogEvent is to use a Formatter. + </p> + <p> + The Formatter interface takes a LogEvent and returns a String object. + The most commonly use LogEvent is the PatternFormatter. The pattern + formatter takes a format specifier that has a similar format to c's + printf function. + </p> + <p> + The format specifier consists of a string containing raw text combined + with pattern elements. Each pattern element has the generalized form + "%[+|-]#.#{field:subformat}". The +|- indicates whether the pattern + element should be left or right justified (defaults to left justified if + unspecified). The #.# indicates the minimum and maximum size of output, + if unspecified the output is neither padded nor truncated. 'field' + indicates the field to be written and must be one of "category", + "context", "message", "time", "rtime" (time relative to start of + application), "throwable" or "priority". This parameter must be supplied + and correlates to fields of LogEvent. 'subformat' is currently unused + except in the case of "context" field. This is further discussed below. + </p> + <p> + Following is a number of examples for PatternFormatter's format + specifier and actual output. + </p> + <source> +format: "%7.7{priority} %5.5{rtime} [%8.8{category}]: %{message}\n%{throwable}" +output: DEBUG 123 [network.]: This is a debug message +format: "%7.7{priority} %5.5{rtime} [%{category}]: %{message}\n" +output: DEBUG 123 [network.interceptor.connected]: This is a debug message +output: DEBUG 123 [network]: This is another debug message +format: "%7.7{priority} %5.5{rtime} [%10.{category}]: %{message}\n" +output: DEBUG 123 [network.interceptor.connected]: This is a debug message +output: DEBUG 123 [network ]: This is another debug message + </source> + <p> + There is also ExtendedPatternFormatter that allows two extra fields, + namely "method" and "thread". The "method" field attempts to determine + the method that called the Logger method to generate the LogEvent. The + "thread" field displays the name of the current thread. + </p> + </section> + <section name="Context"> + <p> + In many systems you need to include extra information depending in logs + that depends on information not included in the LogEvent. For instance + the Formatters section described an ExtendedPatternFormatter that + included information such as calling method and calling thread. Other + contextual information that you may need to include in log files include + user executing log statement, the network interface that the client + component is listening to (ie 127.0.0.1 vs 192.168.1.1), hostname + (especially important on multihomed boxs) or source of LogEvent (useful + when writing a centralized log server). + </p> + <p> + There are a number of strategies to deal with application specific + contextual information. Some logging toolkits encourage extending the + Logger, LogEvent and LogTargets while others encourage using application + specific LogTargets. The way that LogKit solves this problem is by using + a generic ContexMap object. + </p> + <p> + The ContextMap allows the user to store arbitrary objects using a string + key. These objects can then be extracted by the LogTargets and used as + appropriate. If you were using the PatternFormatter you could extract a + value from ContextMap by specify the "context" field with it's subformat + set to the appropriate key. Some examples are illustrated below. + </p> + <source> +format: "%7.7{priority} [%{context:hostname}]: %{message}\n" +output: DEBUG [helm.realityforge.org]: This is a debug message +format: "%7.7{priority} [%{context:interface}]: %{message}\n" +output: DEBUG [127.0.0.1]: This is logging about loopback interface +output: DEBUG [192.168.1.1]: This is logging about internal network interface +output: DEBUG [203.121.1.2]: This is logging about external network interface +format: "%7.7{priority} [%{context:user}]: %{message}\n" +output: DEBUG [Barney Rubble]: This is a debug message + </source> + <p> + <em>Warning:</em> + Older versions of LogKit also incorporated a ContextStack that offered + hierarchical management of context. It was discovered that this design + encouraged bad practices and thus use of this feature has been + deprecated in favour of using ContextMap. The ContextStack is still + accessible if users do not specify a subformat or specify the subformat + "stack". However it is strongly advised that users do not use this + feature as it will be removed in a future iteration. + </p> + <p> + When using a ContextMap you create the object and populate it using the + set(key,value) method. After populating the ContextMap you call the + method makeReadOnly(). This makes it impossible for hostile code to + modify context in which logging occurs. + </p> + <p> + Then you need to associate the ContextMap with a thread by using + ContextMap.bind( myContextMap ). The ContextMap is bound to a thread + using java.lang.InheritableThreadLocal and thus maps are inherited + between threads as specified by InheritableThreadLocal. + </p> + <p>Below is an example of how a user can create and bind a ContextMap.</p> + <source> +final ContextMap context = new ContextMap(); +context.set( "user", "Fred Flinstone" ); +context.set( "interface", myInterface ); +context.set( "hostname", "helm.realityforge.org" ); +context.set( "jvmid", myJvmId ); +context.makeReadOnly(); +//bind new ContextMap to current thread and subthreads +ContextMap.bind( context ); + </source> + </section> + <section name="Examples" > + <p> + One of the best ways to learn how to use a toolkit is to see an + example in action. With that heres some example uses of LogKit. The + first example is in a simple application while the next example is in a + servlet. The servlet example demonstrates the usage of filters. + </p> + <source> +Logger logger = Hierarchy.getDefaultHierarchy().getLoggerFor("myCategory"); +logger.setPriority( Priority.DEBUG ); +logger.debug( "This is a debug message" ); + </source> + <source> +//Create a Log filter that writes to servlet Containers log +//If priority greater than ERROR +PriorityFilter filter = new PriorityFilter(Priority.ERROR); +filter.addTarget( new ServletOutputLogTarget(context) ); + +String logName = getInitParameter("log-name"); +if( null == logName ) + logName = "myservlet.log"; + +final String path = context.getRealPath("/") + "/WEB-INF/logs/" + logName ; + +//Create a logger to write to a file as specified +//with servlet init parameters +final String pattern = "%7.7{priority} %5.5{time} [%8.8{category}] " + + "(%{context}): %{message}\\n%{throwable}"; + +final PatternFormatter formatter = new PatternFormatter( pattern ); +final File file = new File( path ); + +//open file target in append mode +FileTarget target = new FileTarget( file, true, formatter ); + +//Create logger +myLogger = Hierarchy.getDefaultHierarchy().getLoggerFor("myServlet"); + +//Set log targets of logger +myLogger.setLogTargets( new LogTarget[] { target, filter } ); +String logLevel = getInitParameter("log-priority"); + +if( null == logLevel ) + logLevel = "DEBUG"; + +//Set log targets parameter based on init parameters +Priority priority = Priority.getPriorityForName( logLevel ); +myLogger.setPriority( priority ); + </source> + </section> + <section name="Conclusion"> + <p> + LogKit is a friendly, easy to use logging toolkit. It is high + performing and easily integrated into existing products. By design it + does not specify any configuration format but instead encourages users + to integrate it into their existing products. It also is designed to run + in a secure environment by limiting client access to hierarchies. + </p> + </section> + </body> +</document> Modified: avalon/trunk/runtime/versioning/avalon-util.ent ============================================================================== --- avalon/trunk/runtime/versioning/avalon-util.ent (original) +++ avalon/trunk/runtime/versioning/avalon-util.ent Sun May 30 18:29:30 2004 @@ -9,7 +9,7 @@ <!ENTITY avalon-util-defaults-version "1.2.1"> <!ENTITY avalon-util-env-id "avalon-util-env"> -<!ENTITY avalon-util-env-version "1.1.1"> +<!ENTITY avalon-util-env-version "1.1.2-dev"> <!ENTITY avalon-util-exception-id "avalon-util-exception"> <!ENTITY avalon-util-exception-version "1.0.0"> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]