On Thu, Jun 23, 2011 at 01:59:27PM +0200, Knut Anders Hatlen wrote:
> Jens Elkner <[email protected]> writes:
>
> > On Mon, Jun 20, 2011 at 12:07:09PM +0000, [email protected] wrote:
> >> https://defect.opensolaris.org/bz/show_bug.cgi?id=18585
> >>
> >> Knut Anders Hatlen <[email protected]> changed:
> >>
> >> What |Removed |Added
> >> ----------------------------------------------------------------------------
> >> Status|ACCEPTED |CLOSED
> >> Resolution| |FIXED
> >> Target Milestone|--- |next
> >>
> >> --- Comment #1 from Knut Anders Hatlen <[email protected]> 2011-06-20
> >> 12:07:08 UTC ---
> >> changeset: 1258:b889068b5d93
> >
> > Hmmm, well, actually the intention was to silent logs, i.e. print
> > stacktraces only, when debugging for this class is enabled. So the
> > "correct" way would be:
> >
> > if (null != thrown &&
> > Logger.getLogger(record.getLoggerName()).getLevel().intValue() >
> > Level.CONFIG.intValue())
> > {
> > ...
> > }
> >
> > I call that, from the back through the breast ;-), since the method
> > which calls "format(...)" already knows, what gets accomplished "brute
> > force like" with Logger.getLogger...
>
> You're probably right. I only wanted to fix the obvious bug with the
> wrong operator being used to compare the levels.
>
> > Anyway:
> >
> > To get Logging correct, in general the pattern one should always use is:
> > class Foo ... {
> > static final Logger log = Logger.getLogger(Foo.class.getName());
> >
> > try {
> > ...
> > } catch (*Exception e) {
> > log.warn(e.getLocalizedMessage();
> > if (log.isDebugEnabled()) {
> > log.debug("$hint-e-g-methodName", e);
> > }
> > }
> > }
> >
> > So yes, "Logger logger = OpenGrokLogger.getLogger(); log..." is plain
> > wrong. In addition, OpenGrokLogger hard codes pretty everything, which
> > makes logging almost useless.
>
> Well, "plain wrong" is a bit too strong, isn't it? :)
Always depends on the POV, but here it is the case ;-)
> The API says this about the "name" parameter to Logger.getLogger():
>
> Parameters:
> name - A name for the logger. This should be a dot-separated name
> and should normally be based on the package name or class name of
> the subsystem, such as java.net or javax.swing
>
> OpenGrokLogger calls it with "org.opensolaris.opengrok", which satisfies
> both the requirement that it's dot-separated and the suggestion that
> it's based on the package name.
That's actually the tricky point: At least in java, developers and
troubleshooters and java aware admins ;-) expect to be able to
enable/disable logging in a coarse as well as fine grained manner, i.e.
wrt. to the "state of the art" class based. So in contrast to a
syslog[ger] one has not only 24 facilities but up to $#classes + $#packages
facilities aka Loggers with $#Levels priorities.
Using OpenGrokLogger.getLogger() is reducing it to exactly one facility
with ($#Levels - ord(OpenGrokLogger.get*LogLevel())) priorities - aka all
or nothing approach. And that will make people mad/complain and also
makes problem spotting a pain and _TIME_ consuming: if one enables debug
Level logging, the log gets bloated with tons of stuff one isn't
simply interested in ...
> I'm not so familiar with the logging API. What would switching to using
> class names buy us? The ability for users to do more fine-tuning of what
Yes, the right approach is, to enable the intented log level (e.g.
info/debug) on demand/when it is needed and only at the places, where it
is beneficial. Since java classes imply a namespace and functionalities
are usually grouped into packages, it certainly makes sense to re-use
this namespace for Loggers as well and thus there is no need to write
a whole chapter about logging and maintaining a list of available
logging targets.
> to log? If so, it sounds like a good idea, provided that it doesn't at
> the same time make it more a lot more difficult to set up for those who
> don't need the fine-tuning.
As for normal jul, one can ship a default config file which gets
automatically picked up via the CLASSPATH - no need to touch or
fine-tune it.
Maybe an logback example helps to understand that and the use of a more
complete logging framework a little bit better: A default logback.xml may
look like this:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<jmxConfigurator /> <!-- enable logging config via JMX (e.g. VisualVM)
-->
<appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %level
[%thread, %file:%line] - %message%n</pattern>
</encoder>
<target>System.err</target>
</appender>
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/opengrok.log</file>
<append>true</append>
<!-- as currently used in opengrok -->
<rollingPolicy
class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>opengrok-%i.log.gz</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>30</maxIndex>
</rollingPolicy>
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>1MB</maxFileSize>
</triggeringPolicy>
<!-- or simply daiily
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/opengrok-%d.log.gz</fileNamePattern>
</rollingPolicy>
-->
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %level
[%thread, %file:%line] - %message%n</pattern>
</encoder>
</appender>
<!- default for everything, which does not belong to the opengrok pkg
-->
<root level="WARN" />
<appender-ref ref="STDERR" />
<appender-ref ref="FILE" />
</root>
<!-- default log level for opengrok.** classes; logs to STDERR+FILE -->
<logger name="org.opensolaris.opengrok" level="INFO"/>
<!-- e.g. if JarAnalyzer is suspected to behave mad enable debug, but
log to FILE, only -->
<!--
<logger
name="org.opensolaris.opengrok.analysis.executables.JarAnalyzer" level="DEBUG"
additivity="false">
<appender-ref ref="FILE" />
</logger>
-->
</configuration>
So we have all the functionallity we have right now plus a lot more
flexibility wrt. what, how and where to log. There is really no need to
struggle with its own LF and to artificially limit its capabilities by
e.g. hardcoding logformats etc. (where are the line numbers gone ;-)).
For more info just skim over:
http://logback.qos.ch/manual/appenders.html
http://logback.qos.ch/manual/configuration.html
> > IMHO, we should switch over to use slf4j (see slf4j.org) and than
> > everybody can use the logging framework he like and make use of its
> > features. Also this way, OpenGrokLogger and *Formatter can be phased out
> > (i.e. removed) completely and actually _should be_.
>
> I tend to be reluctant to add third-party dependencies, especially when
> similar functionality is provided by the Java platform. Couldn't those
Well, I also don't like to pull in everything, what is available. However,
wrt. logging it is IMHO expected: Sun decided to just provide a basic
Logging Framework (also having the long term API stability in mind)
and expected, that industry will adapt to it and provide propper
extensions, which enrich it by providing needed configuration/management
UIs/mechanisms. However to get the ball rolling, they just provided a very
basic config mechanism via -Djava.util.logging.config.file=... (default:
$JRE/lib/logging.properties) and supplement it later [because the lack
of adaption?] with JMX capabilities.
So under the bottom line: The intention with jul was certainly not, that
everybody/application has to code and ship its own Logging extensions to
make use of it. 3rd party products were actually expected to fill the gap.
Anyway, IMHO because of the lack of the required config/management
UIs/mechs the adaption of jul is still very limited. In general some
webapps use it, since tomcat aka catalina and thus GF? actually
provide the required extensions (*.apache.juli.*), and maybe some
standalone apps, which do not care much about logging, but that's usually
it. All others are still using Apache commons logging (oh my godness),
log4j and the like, but there is a clear tendency to switching over to
slf4ji (and not to jul): one just has to put his favorit LF jars/adapters
(which are already available) into the CLASSPATH, optionally configure
the LF and that's it.
> who need to plug OpenGrok into another logging framework do that with a
> bridge instead of us using a third-party API? For example this one:
> http://www.slf4j.org/legacy.html#jul-to-slf4j
Possible, but again from the back through the breast and much more
important: a really bad idea wrt. performance/resource usage and may
cause unwanted problems as well:
http://simplericity.com/2009/01/02/1230894176938.html.
> > Would that be a problem: Nope. Tomcats already use slf4j, glassfish comes
> > with an adapter and for standalone usage, slf4j comes with adapters
> > (i.e. implementation wrappers) for jul, apach.commons.logging, log4j etc.
>
> The indexer also uses logging, and runs outside of Tomcat and GlassFish,
> so we would need to bundle slf4j with OpenGrok, wouldn't we?
IMHO the propper way is, to use slf4j API everywhere and bundle at least
slf4j-api.jar (to make the comipler happy). For runtime it actually
depends, how the container (if any) is configured. If it is using jul,
one needs to add slf4j-jdk14.jar, if it is using log4j one needs to
add slf4j-log4j12.jar etc. but that's really the choice of the admin and
at least for recent ones I GUESS, these adapter are already configured
at the global level - so no need to bundle any slf4j*.jar into *.war.
For standalone use, yes, slf4j-api.jar (~ 12K) and the LF. My suggestion
for the latter is logback and thus logback-core.jar + logback-classic.jar;
~ 260K - highest flexibility and easy to use/adjust even by normal human
beeings ;-)).
However, if the latter gets considered to be too much bloat, one may
provide the basic logback.xml config file for convinience, but go with
the jul implementation (slf4j-jdk14.jar ~ 6K).
In any case, I would remove org.opensolaris.opengrok.*Formatter as well as
org.opensolaris.opengrok.*Logger
> > Finally, I would ship opengrok with a native implementation named logback
> > (see http://logback.qos.ch/): here one is able to get all the functionallity
> > OpenGrokLogger is trying to deliver, but in a much more flexible way
> > just by supplying an appropriate logback.xml file ...
> >
> > What do you think?
>
> I think it would make sense to change the Logger.getLogger() calls as
> you suggested. I would prefer to stick to java.util.logging for now and
> not switch to a third-party library.
Well, actually these are basically 2 different things:
1) get logging right and making it flexible as much as possible
2) LF to use
However, 2) has an influence on 1) and thus, if one needs to touch a lot
of files anyway, it is smart to find an agreement for 2) first. E.g:
JUL usage:
private static final Logger log = Logger.getLogger(Foo.class.getName());
...
log.log(Level.WARNING, "message bla {} bla {}", a, b);
...
log.isLoggable(Level.FINE);
SLF4J usage:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
...
log.warn("message bla {} bla {}", a, b);
...
log.isDebugEnabled();
Anyway, for me it is important, that (1) gets fixed. Everything else is
secondary. So SLF4J is just for convinience (a real API, less bloat,
"state of the art" ;-) and wrt. logback much better performance, easy-
to-use experience, [G]UI support).
Regards,
jel.
--
Otto-von-Guericke University http://www.cs.uni-magdeburg.de/
Department of Computer Science Geb. 29 R 027, Universitaetsplatz 2
39106 Magdeburg, Germany Tel: +49 391 67 12768
_______________________________________________
opengrok-dev mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/opengrok-dev