logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Lance Larsen" <llar...@netopia.com>
Subject Re: Making object rendering more extensible
Date Tue, 12 Feb 2002 19:28:50 GMT
Note, it would be helpful if you could copy me on the response to this. I am
following the dev list, but  am not subscribed to it at the moment, so it is
difficult to respond on the thread unless I get the e-mail directly.

I can't speak for Anders, but it does sound like he is interested in
addressing the same issue I am trying to face currently. Hopefully he will
express more of his thoughts later, but here is my shot at answering your

> Ceki says:
> I still don't see the *practical* use of having the renderer depend on
> the layout or appender. Would it be possible for you to describe a
> practical case where such functionality would be useful.

I wouldn't necessarily say the 'ObjectRenderer(s)' should depend on
'Layout(s)' or 'Appender(s)', but rather that there can exist multiple
'ObjectRenderer' sets (refered to as 'ObjectRendererBundle' from here on
out), and that the log4j configuration include the ability to specify per
'Layout' an 'ObjectRendererBundle' that the 'Layout' will use. The
'ObjectRendererBundle' is independant of the 'Layout' and can be associated
with multiple 'Layout(s)' in the same sense that a 'Layout' is independant
of an 'Appender' and can be associated with multiple 'Appender(s)'.

In the architecture, it appears that 'Layout(s)' are responsible for
formatting log data that is sent to the 'Appender', but 'ObjectRenderer(s)'
are also responsible for part of this formatting process. I am running a few
cases where I have multiple 'Layout(s)' and each of these 'Layout(s)' need
to coordinate with the 'ObjectRenderer(s)' to format text correctly. In
other words, the result each of these 'Layout(s)' need from the
'ObjectRender' is different for the same object, and there does not seem to
be a way to address this in log4j at present.

I will try to give a practical example here. You will have to let me know if
this helps, or if there are things I need to clarify. Lets say we have an
FTP server written in java. We include the capability to log FTP commands
that the FTP server receives. The FTP command info is stored in an instance
of the following class:

public class FTPCommandInfo
   public String m_fromIP; // FTP client IP
   public String m_toIP; // FTP server IP
   public int    m_port; // FTP port

   public String m_username; // User for connection
   public String m_password; // Password for connection

   public String m_command; // The FTP command that was issued
   public String m_filePath; // The file
   public String m_result; // The FTP server result

In some FTP server class we have some code like the following:

Logger log = ...;
FTPCommandInfo ftpInfo = ...;
// The FTP command info gets populated in ftpInfo

The logging occurs for each FTP command that get called. In configuring
log4j, we decide we want a few different 'Appender(s)' to listen to this
'Logger', with the ability to run them all at the same time. We would like
the 'Layout' associated with a first 'Appender' to return result to be in a
comma separated list of all the info stored in the 'FTPCommandInfo' object:
<FTP client IP>,<FTP Server IP>,<FTP port> ... <FTP Password> ...

The 'Layout' for the second 'Appender' should return results in an XML
format such as the following:
<FTPCommand client_ip="<FTP client IP>" server_ip="<FTP server IP>" ...
result="<FTP result>"/>

The 'Layout' for the third 'Appender' should return a comma separated list
similar to the first 'Layout'. But in this case we do not want to include
the 'm_password' value in the log file because the log is made public and we
do not want to expose passwords. So the format might be exactly like the
first case, but without the passwords included.

It is the job of the 'Layout' to format the text. The 'Layout(s)' supposedly
are fairly generic and delegate rendering of object data to the
'ObjectRenderer(s)'. This is very handy since the 'Layout' does not have to
understand each object that comes in. Making an 'ObjectRenderer' to hand bac
k a correct 'String' to the 'Layout' in any one of these cases is fairly
trivial. It is fairly trivial to make an 'ObjectRenderer' that returns ftp
info in a comma separated list, or one that returns the ftp info as a set of
xml attributes, or even one that excludes certian info the loggable object
contains that should not be displayed. However these does not seem to be a
way for these 'ObjectRenderer(s)' to coexist in log4j at the same time and
associated with the respective 'Layout(s)'.

A workaround is to ignore 'ObjectRenderer(s)' and add the
'ObjectRender(ing)' capabilities to the 'Layout' directly but this is not
ideal since it supervents a part of the architecture and does not allow for
an extensible way to render new objects. It would really be much better to
be able to use the 'ObjectRenderer' architecture, but there is only one
unchangable 'ObjectRenderer' set so I have to deal with a workaround.

I think it is justifiable that you may want multiple log files for different
purposes (we run into that fairly often), and it is quite possible that each
of the log files may need to render the object data in different formats.
The example above is just one case. The best way I can think of to address
this is to allow 'ObjectRendererBundle(s)' that allow you to render object
differently in different 'Appender(s)' (or more correctly in different
'Layout(s)'). In the case that you only use a default 'ObjectRendererBundle'
the architecture reduces to the current one. I expect that this change would
have minor impact on the API overall, but would allow more flexibility as

Is this a practical enough example? It is similar to a problem I am
currently trying to address and I hope my explaination did it justice. I am
feeling the limitations of the current 'ObjectRenderer' configuration
options. I need to have a way to render the same object in multiple ways
within the same program. I believe that the changes I have suggested would
help make log4j fundamentally for extensible. It is not a huge leap from
where things are at right now and seems to be a logical extension.

Log4j really is an excellent product. I hope that you will consider the
changes I have suggested because I think it would help make log4j more
extensible to meet a broader set of needs in a clean and clear fashion.
Please let me know if there is anything I can clarify, or that does not seem
entirely sound in the discussion above. Thanks again for an excellent

-Lance Larsen

> This might be another case where Anders is a few steps ahead of me. It
> has happened in the past... so I am all ears.

> TIA, Ceki

> ps: Would it be sufficient if Appender and layouts accepted configuration
> directives for elements unknown at compile time? For example, appenders
> are known to contain a layout element and there is code to handle layout
> directives within an appender. The idea is to support unknown element
> types... such as object renderers.

----- Original Message -----
From: Lance Larsen
To: log4j-dev@jakarta.apache.org
Sent: Thursday, February 07, 2002 11:54 AM
Subject: Making object rendering more extensible

I have looked through the dev list to see if this has come up, but I haven't
seen anything so far. I have been using log4j on a few projects, and like
the configurability and extensibility it provides - very nice - thankyou for
the excellent tool.

However, there seems to be one part of the architecture where I have run
into limitations, and would like to submit a feature request. Log4j provides
a mechanism to register 'ObjectRenderer(s)' in the configuration. This is
very handy since it allows you to log various types of objects that log4j
would not natively understand by simply creating a new 'ObjectRenderer'
class and including this in the log4j configuration (no other changes). This
part is very nice. The problem I have run into is cases where I would like
the set of 'ObjectRenderer(s)' to be different for various 'Layout(s)' used
at the same time. There does not appear to be a way to do this.

The current assumption seems to be that there is one application global
fundamental 'String' mapping for each loggable object type. There seem to be
many cases where you may want to object to be rendered differently in
different contexts. Log4j gives you this flexibility in the relationship of
'Appender(s)' to 'Layout(s)', but for some reason did not extend this to the
relationship between 'Layout(s)' and 'ObjectRenderer(s)'.

One case where having different object renderers is useful is in a case
where there are several things you can pull out of an object. One 'Appender'
(or more correctly 'Formatter') may log part of the info and another
'Appender' may log different info from the same object. In another case, two
'Layout(s)' may need the same info, but the string format may need to be
different for each. I do not see a clean way to currently handle either of
these cases.

My suggestion would be to add a new concept of 'ObjectRendererBundle(s)'
which includes a set of 'ObjectRenderer(s)' that a 'Layout' will use. In the
configuration, the 'Layout' can be assigned an 'ObjectRendererBundle' in a
similar way that an 'Appender' is assigned a 'Layout'. The 'Layout' class
could include a couple of new methods something like
'setObjectRendererBundle' and 'getObjectRendererBundle' to access the set of
object renders for the 'Layout'. There would probably be a default
'ObjectRendererBundle' that was global as in the current case, but the
'ObjectRenderer' model would be more extensible.

Are there any other thoughts or somments on this? Does this seem like a
reasonable approach? Is this something that you are interested in including
into 'log4j'?

-Lance Larsen

To unsubscribe, e-mail:   <mailto:log4j-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:log4j-dev-help@jakarta.apache.org>

View raw message