Save This Page
Home » slf4j-1.5.5 » org.apache » log4j » net » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.log4j.net;
   19   
   20   import java.net.DatagramSocket;
   21   import java.net.InetAddress;
   22   import java.net.DatagramPacket;
   23   import java.net.UnknownHostException;
   24   import java.net.SocketException;
   25   
   26   import org.apache.log4j.helpers.OptionConverter;
   27   import org.apache.log4j.AppenderSkeleton;
   28   import org.apache.log4j.spi.LoggingEvent;
   29   import org.apache.log4j.Category;
   30   import org.apache.log4j.Priority;
   31   import org.apache.log4j.Layout;
   32   
   33   import org.apache.log4j.helpers.SingleLineTracerPrintWriter;
   34   import org.apache.log4j.helpers.LogLog;
   35   import org.apache.log4j.helpers.QuietWriter;
   36   
   37   
   38   /**
   39       Use DatagramStringAppender to send log messages to a remote daemon
   40       which accepts Datagram (UDP) messages.
   41       <p>
   42       The benefits of UDP are that the client is guarunteed not to
   43       slow down if the network or remote log daemon is slow, and that
   44       no permanent TCP connection between client and server exists.
   45       <p>
   46       The disadvantages are that log messages can be lost if the network
   47       or remote daemon are under excessive load.
   48       <p>
   49       This class builts the final message string <b>before</b> sending
   50       the UDP packet, hence the "string" component in the class name. This
   51       means that the receiving application can be written in any language.
   52       The data is transmitted in whatever encoding is specified in the
   53       configuration file; this may be an 8-bit encoding (eg ISO-8859-1, also
   54       known as LATIN-1) or a larger encoding, eg UTF-16.
   55       <p>
   56       An alternative to building the message string within DatagramStringAppender
   57       would be to serialize & send the complete logging event object (perhaps
   58       such a class could be called a DatagramSerialAppender??). The
   59       receiving end could then be configured with appropriate Layout objects
   60       to generate the actual logged messages. This would ensure that the
   61       logging of messages from different sources is done in a consistent
   62       format, and give a central place to configure that format. It would ensure
   63       (by transmitting messages as unicode) that the receiving end could control
   64       the encoding in which the output is generated. It also would possibly allow
   65       he receiving end to use the full log4j flexibility to pass the event to
   66       different appenders at the receiving end, as the category information is
   67       retained, etc. However, this does require that the receiving end is in
   68       java, and that all clients of the logging daemon are java applications.
   69       In contrast, this DatagramStringAppender can send mesages to a log daemon
   70       that accepts messages from a variety of sources.
   71   
   72       @author Simon Kitching
   73    */
   74   public class DatagramStringAppender extends AppenderSkeleton {
   75   
   76      /**
   77        A string constant used in naming the option for setting the destination
   78        server for messages.  Current value of this string constant is
   79        <b>DatagramHost</b>. */
   80     public static final String DATAGRAM_HOST_OPTION = "DatagramHost";
   81   
   82      /**
   83        A string constant used in naming the option for setting the destination
   84        port for messages. Current value of this string constant is
   85        <b>DatagramPort</b>. */
   86     public static final String DATAGRAM_PORT_OPTION = "DatagramPort";
   87   
   88      /**
   89        A string constant used in naming the option for setting the character
   90        encoding used when generating the log message. Current value of this
   91        string constant is <b>DatagramEncoding</b>. */
   92     public static final String DATAGRAM_ENCODING_OPTION = "DatagramEncoding";
   93   
   94      /**
   95        The default value for the "host" attribute, ie the machine to which
   96        messages are sent. Current value of this string constant is
   97        <b>localhost</b>. */
   98     public static final String DEFAULT_HOST = "localhost";
   99   
  100      /**
  101        The default value for the "port" attribute, ie the UDP port to which
  102        messages are sent. Current value of this integer constant is
  103        <b>8200</b>. This value was chosen for no particular reason. */
  104     public static final int DEFAULT_PORT = 8200;
  105   
  106      /**
  107        The default value for the "encoding" attribute, ie the way in which
  108        unicode message strings are converted into a stream of bytes before
  109        their transmission as a UDP packet. The current value of this constant
  110        is <b>null</b>, which means that the default platform encoding will
  111        be used. */
  112     public static final String DEFAULT_ENCODING = null;
  113   
  114     String host = DEFAULT_HOST;
  115     int port = DEFAULT_PORT;
  116     String encoding = DEFAULT_ENCODING;
  117   
  118     SingleLineTracerPrintWriter stp;
  119     QuietWriter qw;
  120   
  121     public
  122     DatagramStringAppender() {
  123       this.setDestination(DEFAULT_HOST, DEFAULT_PORT, DEFAULT_ENCODING);
  124     }
  125   
  126     public
  127     DatagramStringAppender(Layout layout) {
  128       this.setLayout(layout);
  129       this.setDestination(DEFAULT_HOST, DEFAULT_PORT, DEFAULT_ENCODING);
  130     }
  131   
  132     public
  133     DatagramStringAppender(Layout layout, String host, int port) {
  134       this.setLayout(layout);
  135       this.setDestination(host, port, DEFAULT_ENCODING);
  136     }
  137   
  138     public
  139     DatagramStringAppender(Layout layout, String host, int port, String encoding) {
  140       this.setLayout(layout);
  141       this.setDestination(host, port, encoding);
  142     }
  143   
  144     /**
  145        Release any resources held by this Appender
  146      */
  147     public
  148     void close() {
  149       closed = true;
  150       // A DatagramWriter is UDP based and needs no opening. Hence, it
  151       // can't be closed. We just unset the variables here.
  152       qw = null;
  153       stp = null;
  154     }
  155   
  156     public
  157     void append(LoggingEvent event) {
  158       if(!isAsSevereAsThreshold(event.priority))
  159         return;
  160   
  161       // We must not attempt to append if qw is null.
  162       if(qw == null) {
  163         errorHandler.error(
  164           "No host is set for DatagramStringAppender named \""
  165           +	this.name + "\".");
  166         return;
  167       }
  168   
  169       String buffer = layout.format(event);
  170       qw.write(buffer);
  171   
  172       if(event.throwable != null)
  173         event.throwable.printStackTrace(stp);
  174       else if (event.throwableInformation != null) {
  175         // we must be the receiver of a serialized/deserialized LoggingEvent;
  176         // the event's throwable member is transient, ie becomes null when
  177         // deserialized, but that's ok because throwableInformation should
  178         // have the string equivalent of the same info (ie stack trace)
  179         qw.write(event.throwableInformation);
  180       }
  181     }
  182   
  183     /**
  184        Activate the options set via the setOption method.
  185   
  186        @see #setOption
  187     */
  188     public
  189     void activateOptions() {
  190       this.setDestination(this.host, this.port, this.encoding);
  191     }
  192   
  193     /**
  194        Returns the option names for this component, namely the string
  195        array consisting of {{@link #DATAGRAM_HOST_OPTION}, {@link
  196        #DATAGRAM_PORT_OPTION}, {@link #DATAGRAM_ENCODING_OPTION}  */
  197     public
  198     String[] getOptionStrings() {
  199       return OptionConverter.concatanateArrays(super.getOptionStrings(),
  200   		      new String[] {
  201               DATAGRAM_HOST_OPTION,
  202               DATAGRAM_PORT_OPTION,
  203               DATAGRAM_ENCODING_OPTION});
  204     }
  205   
  206     /**
  207        The DatagramStringAppender requires a layout. Hence, this method return
  208        <code>true</code>.
  209   
  210        @since 0.8.4 */
  211     public
  212     boolean requiresLayout() {
  213       return true;
  214     }
  215   
  216     /**
  217       Set DatagramStringAppender specific parameters.
  218       <p>
  219       The recognized options are <b>DatagramHost</b>, <b>DatagramPort</b> and
  220       <b>DatagramEncoding</b>, i.e. the values of the string constants
  221       {@link #DATAGRAM_HOST_OPTION}, {@link #DATAGRAM_PORT_OPTION} and
  222       {@link #DATAGRAM_ENCODING_OPTION} respectively.
  223       <p>
  224       <dl>
  225       <p>
  226       <dt><b>DatagramHost</b>
  227       <dd>
  228       The name (or ip address) of the host machine where log output should go.
  229       If the DatagramHost is not set, then this appender will default to
  230       {@link #DEFAULT_HOST}.
  231       <p>
  232       <dt><b>DatagramPort</b>
  233       <dd>
  234       The UDP port number where log output should go. See {@link #DEFAULT_PORT}
  235       <p>
  236       <dt><b>DatagramEncoding</b>
  237       <dd>
  238       The ISO character encoding to be used when converting the Unicode
  239       message to a sequence of bytes within a UDP packet. If not defined, then
  240       the encoding defaults to the default platform encoding.
  241       </dl>
  242       */
  243     public
  244     void setOption(String option, String value) {
  245       if(value == null) return;
  246   
  247       super.setOption(option, value);
  248   
  249       if(option.equals(DATAGRAM_HOST_OPTION))
  250       {
  251         this.host = value;
  252       }
  253       else if(option.equals(DATAGRAM_PORT_OPTION))
  254       {
  255         this.port = OptionConverter.toInt(value, DEFAULT_PORT);
  256       }
  257       else if(option.equals(DATAGRAM_ENCODING_OPTION))
  258       {
  259         this.encoding = value;
  260       }
  261     }
  262   
  263     public
  264     void setDestination(String host, int port, String encoding) {
  265       if (host==null) {
  266         LogLog.error("setDestination: host is null");
  267         host = DEFAULT_HOST;
  268       }
  269       
  270       this.host = host;
  271       this.port = port;
  272       this.encoding = encoding;
  273   
  274       this.qw = new QuietWriter(
  275           new DatagramStringWriter(host, port, encoding),
  276           errorHandler);
  277       this.stp = new SingleLineTracerPrintWriter(qw);
  278     }
  279   
  280     public
  281     void setLayout(Layout layout) {
  282       this.layout = layout;
  283     }
  284   }

Save This Page
Home » slf4j-1.5.5 » org.apache » log4j » net » [javadoc | source]