You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Andrew McConnell <mc...@socketware.com> on 2003/02/20 12:40:55 UTC

[Logging] Internationalization enhancement proposal

I would like to propose that a number of methods be added to the Log
interface to meet the suggestion outlined in the commons-logging user
guide: "Perhaps more direct support for internationalizing log messages
can be introduced in a future or alternate version of the Log interface"

It seems to me that the JDK1.4 logging support for i18n is an excellent
model.

To implement, a single overloaded getInstance() method needs to be added
to LogFactory so that a resource bundle can be associated with a Log.
Several methods would need to be added to the Log interface to provide a
way to pass parameters to the resource bundle for rendering. For
example, for trace-level messages, add:

trace(Object message, Object param);
trace(Object message, Object[] params);
trace(Object message, Throwable t, Object param);
trace(Object message, Throwable t, Object[] params);

All levels would need analogous methods.

The implementation of these and existing methods should change slightly,
to first attempt to retrieve the log messages from a resource bundle (if
a bundle exists). If the key cannot be found, return Object.toString(),
otherwise use ResourceBundle.getString() to create the displayed
message.

While this adds numerous (24!) methods to the Log interface, the
development effort required to implement is limited due to the
intelligent structure of the Log impls already written, and having this
full set of methods may be the easiest for commons-logging users.

There is a slight performance penalty, due to having to add a check to
see if a resource bundle is set. Perhaps there is an alternate
implementation that can avoid this penalty altogether such as having the
LogFactory return a different implementation of the Log depending on if
a resource bundle is needed?


-- 
Andrew McConnell <mc...@socketware.com>
Socketware, Inc.

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Logging] Internationalization enhancement proposal

Posted by Costin Manolache <cm...@yahoo.com>.
Andrew McConnell wrote:

> I miss your point about different styles of ResourceBundles. Can you
> elaborate?

If you pass in the key - the logger is expected to locate the bundle
and do the substitution. How do you specify where is the key stored ( which
resource bundle ) ? And AFAIK not everyone uses the same layout and style
for the ResourceBundle.

You could pass in the RB as a param, but with the signatures you posted
I just don't see how it could work without additional config or complexity.


> I disagree with the notion that i18n has no place in logging
> infrastructures for the following reason:

I didn't say that. 

I said that logging and i18n shouldn't be mixed up in the same API.


> Despite the well-documented limitations of the JDK 1.4 API, Sun did
> something very useful by exposing the raw log message ("before
> localization and formatting") within the LogRecord, as well as all of
> the parameters that are ultimately handed to the ResourceBundle. In my

That's exactly my sugestion - instead of adding 24 new methods, just
define a LogRecord class ( that can be added to c-l without _any_ backward
compat problems ). The LogRecord method will have a toString() method doing
the normal formatting - but loggers that are I18N-aware could use the 
information directly.

All log() methods take Object as param - it can be a String, and most
current loggers are just converting it to String. But it can be a LogRecord
or something else.

If a LogRecord would be used - performance-critical code could benefit from
not having to do the concatentation of strings and conversions, and a smart
logger could store the fields directly ( I'm thinking about access.log as
example, or general "logs" that are generated by apps, not only for debug). 

Costin


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Logging] Internationalization enhancement proposal

Posted by Andrew McConnell <mc...@socketware.com>.
On Fri, 2003-02-21 at 11:05, Costin Manolache wrote:
> Adding 24 methods and the requirement that the logger deals with
> internationalization doesn't seem right. The second part is worse - 
> each app uses different styles of ResourceBundles - and you mix 
> very different domains.
> 

Well, I agree with you about all of the new methods being difficult.
Probably just adding 2 methods (a la Log4J's Logger.log7dl() methods)
would be sufficient.

I miss your point about different styles of ResourceBundles. Can you
elaborate?

I disagree with the notion that i18n has no place in logging
infrastructures for the following reason:

Despite the well-documented limitations of the JDK 1.4 API, Sun did
something very useful by exposing the raw log message ("before
localization and formatting") within the LogRecord, as well as all of
the parameters that are ultimately handed to the ResourceBundle. In my
particular case, I have system logs written in multiple languages (a
requirement from one of our strategic partners), but a support team that
only speaks one of them. So, in order to be able to review log files to
help diagnose problems, it seems reasonable for them to rely on the key
values, rather than German, French, or other transactions. This becomes
even more important for our automated systems, that may want to escalate
issues because some value in a log file exceeds a threshold. The
position of the value is probably not going to be in the same place in
different languages, but it can rely on the fact that it is in
LogRecord.getParameter()[0].

I'm not saying that there aren't workarounds, but the java.util.logging
methodology suits my needs perfectly for this requirement - and then
promptly fails in others, and since jdk1.4 isn't open source.... ;-)

Also, since Log4J doesn't at this point expose the raw messages and
parameters either, this modification to commons-logging wouldn't totally
meet my overall needs anyhow, but I figured I'd start at the top and
work down.


> A much simpler solution - with no API change in Log - is to 
> use the fact that the message is an Object, and define conventions
> for what it should be for "internationalized" messages.
> For example, add a "I18NMessage" class that holds message and params - 
> and has a toString() method that returns something printable.
> 

> Then add a second class that deals with I18N - I don't think the right
> place is logging ( again - this is a complex issue ), but some helper
> could be included in logging as long as it doesn't impose too many 
> restrictions on how the ResourceBundles are organized. 
> 
> I know some people preffer to use message IDs (ints), some use XML files,
> and so on.
> 
> Another alternative: create a separate interface ( in a i18n component )
> that uses Log for the actual display of the message. 
> 
> Implementing 24 methods ( even if it is cut&paste ) doesn't seem like fun.
> 
> Costin
> 
> 
> 
> Andrew McConnell wrote:
> 
> > I would like to propose that a number of methods be added to the Log
> > interface to meet the suggestion outlined in the commons-logging user
> > guide: "Perhaps more direct support for internationalizing log messages
> > can be introduced in a future or alternate version of the Log interface"
> > 
> > It seems to me that the JDK1.4 logging support for i18n is an excellent
> > model.
> > 
> > To implement, a single overloaded getInstance() method needs to be added
> > to LogFactory so that a resource bundle can be associated with a Log.
> > Several methods would need to be added to the Log interface to provide a
> > way to pass parameters to the resource bundle for rendering. For
> > example, for trace-level messages, add:
> > 
> > trace(Object message, Object param);
> > trace(Object message, Object[] params);
> > trace(Object message, Throwable t, Object param);
> > trace(Object message, Throwable t, Object[] params);
> > 
> > All levels would need analogous methods.
> > 
> > The implementation of these and existing methods should change slightly,
> > to first attempt to retrieve the log messages from a resource bundle (if
> > a bundle exists). If the key cannot be found, return Object.toString(),
> > otherwise use ResourceBundle.getString() to create the displayed
> > message.
> > 
> > While this adds numerous (24!) methods to the Log interface, the
> > development effort required to implement is limited due to the
> > intelligent structure of the Log impls already written, and having this
> > full set of methods may be the easiest for commons-logging users.
> > 
> > There is a slight performance penalty, due to having to add a check to
> > see if a resource bundle is set. Perhaps there is an alternate
> > implementation that can avoid this penalty altogether such as having the
> > LogFactory return a different implementation of the Log depending on if
> > a resource bundle is needed?
> > 
> > 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
-- 
Andrew McConnell <mc...@socketware.com>
Socketware, Inc.

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Logging] Internationalization enhancement proposal

Posted by Costin Manolache <cm...@yahoo.com>.
Adding 24 methods and the requirement that the logger deals with
internationalization doesn't seem right. The second part is worse - 
each app uses different styles of ResourceBundles - and you mix 
very different domains.

A much simpler solution - with no API change in Log - is to 
use the fact that the message is an Object, and define conventions
for what it should be for "internationalized" messages.
For example, add a "I18NMessage" class that holds message and params - 
and has a toString() method that returns something printable.

Then add a second class that deals with I18N - I don't think the right
place is logging ( again - this is a complex issue ), but some helper
could be included in logging as long as it doesn't impose too many 
restrictions on how the ResourceBundles are organized. 

I know some people preffer to use message IDs (ints), some use XML files,
and so on.

Another alternative: create a separate interface ( in a i18n component )
that uses Log for the actual display of the message. 

Implementing 24 methods ( even if it is cut&paste ) doesn't seem like fun.

Costin



Andrew McConnell wrote:

> I would like to propose that a number of methods be added to the Log
> interface to meet the suggestion outlined in the commons-logging user
> guide: "Perhaps more direct support for internationalizing log messages
> can be introduced in a future or alternate version of the Log interface"
> 
> It seems to me that the JDK1.4 logging support for i18n is an excellent
> model.
> 
> To implement, a single overloaded getInstance() method needs to be added
> to LogFactory so that a resource bundle can be associated with a Log.
> Several methods would need to be added to the Log interface to provide a
> way to pass parameters to the resource bundle for rendering. For
> example, for trace-level messages, add:
> 
> trace(Object message, Object param);
> trace(Object message, Object[] params);
> trace(Object message, Throwable t, Object param);
> trace(Object message, Throwable t, Object[] params);
> 
> All levels would need analogous methods.
> 
> The implementation of these and existing methods should change slightly,
> to first attempt to retrieve the log messages from a resource bundle (if
> a bundle exists). If the key cannot be found, return Object.toString(),
> otherwise use ResourceBundle.getString() to create the displayed
> message.
> 
> While this adds numerous (24!) methods to the Log interface, the
> development effort required to implement is limited due to the
> intelligent structure of the Log impls already written, and having this
> full set of methods may be the easiest for commons-logging users.
> 
> There is a slight performance penalty, due to having to add a check to
> see if a resource bundle is set. Perhaps there is an alternate
> implementation that can avoid this penalty altogether such as having the
> LogFactory return a different implementation of the Log depending on if
> a resource bundle is needed?
> 
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org