logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bart S. (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (LOG4J2-952) FAQ: How do I configure log4j2 programmatically in code without a configuration file?
Date Thu, 13 Aug 2015 15:17:46 GMT

    [ https://issues.apache.org/jira/browse/LOG4J2-952?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14695342#comment-14695342

Bart S. commented on LOG4J2-952:

A typical builder paradigm is that there is a fixed _Context_ and the context doesn't change
from one method invocation to the next.

Normally any Builder returns the same Builder from any of its methods, as what you called
the methods on.

So the relationship holds that:

Builder b = builder.doSomething() ---->  b == builder

In fluent API speak this is called the context.

If half of your methods return actual objects and the other half inserts those objects into
the planned configuration (thus honouring the builder thing) then I guess technically there
might not be an amazing issue (as long as the configuration object already exists and you
can pass it into the new created objects) (which is in itself an issue) (you can't have flee
floating objects, they have to be attached to a configuration right from the get go the way
it currently is, I believe)....

But the only advantage is a bit of type checking. You won't be creating a new Log4J configuration
every day I hope. Unless you have a 1000 line configuration, even considering it would be
possible with the builder, the amount of "debugging" you MIGHT need to do AFTER the runtime
engine tells you there has been a mistake is just very minimal.

There are just not any practical advantages to having the real objects in your hands.

At WORST your program might display some errors because you have made a typing mistake, the
exact same thing as when you'd use an XML or other file!!!!!.

Now if some method returned a specific builder instance FOR one of those objects and you were
allowed to manipulate it own your own before sending it back into function (or being registered
at the start) that might not be so bad:

*In that case you'd have the Configuration.Builder store a collection of Builder objects for
the various classes. It would than transform those builder objects into actual objects before
implanting them into the Configuration it is making.*

However I think the two stage approach we have here is much prettier even if I don't agree
with all the Maps, (seems too easy) and more powerful. Also I believe Maps are expensive objects,
but that might be beside the point.

The problem with the current situation is precisely that you need a large number of imports
to do anything:

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.LoggerConfig;

If you created an abstraction interface that would still require all those imports (because
you'd have to store the references yourself) that would perfectly devoid the whole sense of
creating a fluid API (fluent API) to do things.

So I think then the main advantage of having a Builder would be gone. A Builder should not
give back weird objects, it should stay a Builder. Now, how important that is is up to debate.

But I would at this point stick to the simple interface I have / we have described. Just use
string literals, why not. The only alternative is to create something fluent that ensures
you don't have to _keep the references around_ as you pass one object to the next. Then you'd
probably want to use sub-builder classes (such as SyslogOptions.Builder) that either did "Register-in-Front"
as the prettiest solution, or "Finalize-with-Build" and pass the object to the system, as
the ugliest. Like I have indicated.

Personally I don't see why you'd be interested in having a ConfigurationBuilder if the amount
of work required to use it would still be 70% of what you had before?.

> FAQ: How do I configure log4j2 programmatically in code without a configuration file?
> -------------------------------------------------------------------------------------
>                 Key: LOG4J2-952
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-952
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: API, Configurators, Documentation
>    Affects Versions: 2.1
>            Reporter: Joe Merten
> I found [this link|http://logging.apache.org/log4j/2.x/faq.html#config_from_code] which
> {quote}
> You could use the static method #initialize(String contextName, ClassLoader loader, String
configLocation) in org.apache.logging.log4j.core.config.Configurator. (You can pass null for
the class loader.) Be aware that this class is not part of the public API so your code may
break with any minor release.
> {quote}
> This documentation is unclear because it points to a member function which needs a filename
{{configLocation}} where as the topic is ┬╗without a configuration file┬ź.
> It shoud rather point to the member function {{org.apache.logging.log4j.core.config.Configurator.initialize(ClassLoader
loader, ConfigurationSource source)}}.
> Example:
> {code:java}
> import org.apache.logging.log4j.core.config.ConfigurationSource;
> import org.apache.logging.log4j.core.config.Configurator;
> final String hardCodedXmlConfig =
>         "<?xml version='1.0' encoding='UTF-8'?>\n" +
>         "<Configuration status='INFO'>\n" +
>         "  <Appenders>\n" +
>         "    <Console name='Console' target='SYSTEM_OUT'>\n" +
>         "      <PatternLayout pattern='%d{HH:mm:ss.SSS} [%t] %-5level %logger{36}
- %msg%n'/>\n" +
>         "    </Console>\n" +
>         "  </Appenders>\n" +
>         "  <Loggers>\n" +
>         "    <Root level='debug'>\n" +
>         "      <AppenderRef ref='Console'/>\n" +
>         "    </Root>\n" +
>         "  </Loggers>\n" +
>         "</Configuration>\n";
> try {
>     Configurator.initialize(null, new ConfigurationSource(new ByteArrayInputStream(hardCodedXmlConfig.getBytes())));
> } catch (IOException e) {
>     e.printStackTrace();
> }
> {code}

This message was sent by Atlassian JIRA

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

View raw message