When I said "Node", I meant this class:
http://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/config/Node.html

Not the DOM version. If you wanted to manipulate the DOM, you'd probably
have to extend the XML configuration factory classes.


On 24 July 2014 01:33, Nayden Gochev <[email protected]> wrote:

> Hello there,
> I didnt send the source of the appender since I didnt think it is
> important.
> The thing is the appender works correctly everything is fine. The problem
> is that other ROOT appenders also receive messages for this logger.. even
> if this logger has only one appender which is with additivity=false. The
> same thing done with XML configuration works as expected.
> I will paste all the source.. the custom appender is using Atmosphere
> framework to send websocket messages,thats why I didnt send the source
> before since it is not so important, you can ignore it if you like.
>
> Appender :
>
> package org.gochev.core.log.appender;
>
> import org.gochev.core.log.data.LogEntryData;
> import org.apache.logging.log4j.LogManager;
> import org.apache.logging.log4j.Logger;
> import org.apache.logging.log4j.core.Filter;
> import org.apache.logging.log4j.core.Layout;
> import org.apache.logging.log4j.core.LogEvent;
> import org.apache.logging.log4j.core.appender.AbstractAppender;
> import org.apache.logging.log4j.core.config.plugins.Plugin;
> import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
> import org.apache.logging.log4j.core.config.plugins.PluginElement;
> import org.apache.logging.log4j.core.config.plugins.PluginFactory;
> import org.apache.logging.log4j.core.layout.PatternLayout;
> import org.apache.logging.log4j.core.util.Booleans;
> import org.atmosphere.cpr.BroadcasterFactory;
> import org.fusesource.jansi.HtmlAnsiOutputStream;
>
> import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.io.Serializable;
> import java.nio.charset.Charset;
> import java.util.concurrent.locks.Lock;
> import java.util.concurrent.locks.ReadWriteLock;
> import java.util.concurrent.locks.ReentrantReadWriteLock;
>
> @Plugin(name = LogStreamAppender.NAME, category = "Core", elementType =
> "appender")
> public class LogStreamAppender extends AbstractAppender {
>
>     public final static String NAME = "LogStream";
>
>     private static final String BROADCASTER_ID_LOG =
> "admin-queue-agent-logviewer";
>
>      protected final Logger LOG = LogManager.getLogger(getClass());
>
>     private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
>     private final Lock readLock = rwLock.readLock();
>
>     public LogStreamAppender(String name, Filter filter, Layout<? extends
> Serializable> layout, boolean ignoreExceptions) {
>         super(name, filter, layout, ignoreExceptions);
>      }
>
>     @Override
>     public void append(LogEvent event) {
>         if (BroadcasterFactory.getDefault() != null) {
>             try {
>                 readLock.lock();
>                 String message = new
> String(getLayout().toByteArray(event));
>
>
> BroadcasterFactory.getDefault().lookup(LogStreamAppender.BROADCASTER_ID_LOG,
> true).broadcast(new LogEntryData(message + "<br/>"));
>             } finally {
>                 readLock.unlock();
>             }
>         }
>     }
>
>     @PluginFactory
>     public static LogStreamAppender createAppender(
>             @PluginAttribute("name") String name,
>             @PluginAttribute("pattern") String pattern,
>             @PluginAttribute("ignoreExceptions") String ignore,
>             @PluginElement("filters") Filter filter) {
>         return new LogStreamAppender(name, filter,
>                 PatternLayout.createLayout(pattern, null, null,
> Charset.forName("UTF-8"), true, true, null, null),
>                 Booleans.parseBoolean(ignore, false));
>     }
> }
>
>
> Using XML Configuration where everything works as expected (after matt
> told me what additivity is doing ): (only my appender is recieving messages
> for this package.. and the root appender(s) doesnt)
>
> <Configuration status="INFO" packages="org.gochev.core.log">
> <Appenders>
> <Console name="CONSOLE" target="SYSTEM_OUT">
>  <PatternLayout pattern="%highlight{%d [%t] %-5level: %msg%n%throwable}"
> />
> </Console>
>                 <LogStream name="ADMINSTREAM" pattern="%highlight{%d [%t]
> %-5level: %msg%n%throwable}">
>              </LogStream>
> <!-- I have even more appenders here.. but this is a bit smaller config -->
>        </Appenders>
> <Loggers>
> <Root level="info">
> <AppenderRef ref="CONSOLE"/>
> <!-- I have even more appenders here.. but this is a bit smaller config -->
> </Root>
>                 <Logger name="org.gochev.core.service" level="DEBUG"
> additivity="false">
>                   <AppenderRef ref="ADMINSTREAM"/>
> </Logger>
>
> *This works *.. only my ADMINSTREAM is recieving messages from
> services... the CONSOLE log is not receiving them
>
> Using code... where it *doesn't work* and the additivity flag basically
> makes no difference. This code is in service.. invoked from a Spring
> Controller on demand(when user wants).
>
>         String loggerName = "org.gochev.core.service";
>         if (enable) {
>             final LoggerContext ctx = (LoggerContext)
> LogManager.getContext(false);
>             Configuration cfg = ctx.getConfiguration();
>             if (cfg instanceof XmlConfiguration) {
>                 //add appender if not added
>                 Appender appender =
> cfg.getAppender(LogStreamAppender.NAME);
>                 if (appender == null) {
>                     appender =
> LogStreamAppender.createAppender(LogStreamAppender.NAME, "%highlight{%d
> [%t] %-5level: %msg%n%throwable}", "false", null);
>                     appender.start();
>                     cfg.addAppender(appender);
>                 }
>                 //add logger if not added
>                 LoggerConfig logger = ((XmlConfiguration)
> cfg).getLogger(loggerName);
>                 if (logger == null) {
>                     logger = new LoggerConfig(loggerName, Level.DEBUG,
> false);
>                     cfg.addLogger(loggerName, logger);
>                 } else {
>                     logger.setLevel(Level.DEBUG);
>                 }
>                 logger.addAppender(appender, Level.DEBUG, null);
>                 ctx.updateLoggers(cfg);
>             }
>         } else {
>             this.deleteLogger(loggerName);
>         }
>
> About your question if the logger is already loaded .. why I am not
> changing the additivity .. yes .. this is how I want it .. if some user
>  specify manually in XML configuration that he wants additivity .. I dont
> want to replace it ... also if he specify it with false.. he should not
> have issues.. the problem is that in 99% of cases.. the user will use the
> XML configuration only for his packages from his part and not for the core
> stuff so I want to give him an ability in admin backend to be able to
> start/stop this logging.
>
> I will try with ThresholdFilter but this sounds more like a workaround ..
> then a fix.
>
> If I have to use Node and to create this configuration.. can someone tell
> me .. after I create this Document ... can I merge it with the XML one ? or
> can I somehow take the XML ones ... add a new node.. and then pass this to
> the logger context ? somehow is there any doc or example about this ?
>
> Thanks
>
>
>
> On Wed, Jul 23, 2014 at 8:01 PM, Matt Sicker <[email protected]> wrote:
>
>> Ah, good point.
>>
>>
>> On 23 July 2014 11:51, Ralph Goers <[email protected]> wrote:
>>
>>> Well, you can say that about everything in core.  Clearly there is some
>>> stuff in core that we are going to carefully consider the impact to users
>>> before we allow it to change. And saying “not supported” is much different
>>> that saying “we may not maintain binary compatibility”.
>>>
>>> Ralph
>>>
>>> On Jul 23, 2014, at 8:56 AM, Matt Sicker <[email protected]> wrote:
>>>
>>> I say not supported because that API is subject to change in 2.x
>>> releases since it's not log4j-api.
>>>
>>>
>>> On 23 July 2014 10:46, Ralph Goers <[email protected]> wrote:
>>>
>>>> Matt,
>>>>
>>>> That isn’t quite true.  What he is trying to do should work.  We just
>>>> want to find a better way to do it.
>>>>
>>>> As for the code below, I don’t see the source for LogStreamAppender,
>>>> but it is never being started which will ultimately cause problems.
>>>>
>>>> Note also that if the LoggerConfig existed and had additivity = true
>>>> the code below will not be changing that to false.
>>>>
>>>> Can you create a Jira issue and attach a sample project that
>>>> demonstrates the problem?
>>>>
>>>> Ralph
>>>>
>>>> On Jul 23, 2014, at 8:30 AM, Matt Sicker <[email protected]> wrote:
>>>>
>>>> Programmatic configuration is not yet supported which is the biggest
>>>> issue here. The only "supported" way of doing it would be through creating
>>>> a hierarchy of Node objects that directly correspond to a parsed tree of an
>>>> XML or JSON config file.
>>>>
>>>>
>>>> On 23 July 2014 06:40, Remko Popma <[email protected]> wrote:
>>>>
>>>>> One thing you can try is in your log4j2.xml, add a threshold filter
>>>>> that accepts INFO to the console appender. For an example, see
>>>>> http://logging.apache.org/log4j/2.x/manual/filters.html#ThresholdFilter
>>>>>
>>>>> Sent from my iPhone
>>>>>
>>>>> On 2014/07/23, at 16:27, Nayden Gochev <[email protected]> wrote:
>>>>>
>>>>> Matt,
>>>>> so you are right.. if I do a XML configuration and make additivity=
>>>>> false and register my logger with appenderRef there.. everything works as
>>>>> expected.. the ROOT appenders are not used.
>>>>>  However.. when I do it via code ( the one I send in the previous mail
>>>>> ) the root appenders are working...
>>>>> Do I do something wrong abotu creation ?
>>>>> or is there some difference in how updateLoggers(cfg) works compared
>>>>> to after parsing the log4j2.xml and again updating loggers ?
>>>>>
>>>>> Thanks,
>>>>> Nayden
>>>>>
>>>>>
>>>>> On Wed, Jul 23, 2014 at 9:55 AM, Nayden Gochev <[email protected]>
>>>>> wrote:
>>>>>
>>>>>> Hello Matt,
>>>>>> the problem is that I want to create the appender and the logger
>>>>>> together via code.
>>>>>> So the appender or the logger are not mentioned in the log4j2.xml
>>>>>> file
>>>>>>
>>>>>> I am creating the appender via the createAppender factory method but
>>>>>> in the code.
>>>>>> Full code for enable the logger + appender I use is this :
>>>>>> if (enable) {
>>>>>>             final LoggerContext ctx = (LoggerContext)
>>>>>> LogManager.getContext(false);
>>>>>>             Configuration cfg = ctx.getConfiguration();
>>>>>>             if (cfg instanceof XmlConfiguration) {
>>>>>>                 //add appender if not added
>>>>>>                 Appender appender =
>>>>>> cfg.getAppender(LogStreamAppender.NAME);
>>>>>>                 if (appender == null) {
>>>>>>                     appender
>>>>>> = LogStreamAppender.createAppender(LogStreamAppender.NAME, "%highlight{%d
>>>>>> [%t] %-5level: %msg%n%throwable}", "false", null);
>>>>>>                     cfg.addAppender(appender);
>>>>>>                 }
>>>>>>                 //add logger if not added
>>>>>>                 LoggerConfig logger = ((XmlConfiguration)
>>>>>> cfg).getLogger(loggerName);
>>>>>>                 if (logger == null) {
>>>>>>                     logger = new LoggerConfig(loggerName,
>>>>>> Level.DEBUG, false);
>>>>>>                     cfg.addLogger(loggerName, logger);
>>>>>>                 } else {
>>>>>>                     logger.setLevel(Level.DEBUG);
>>>>>>                 }
>>>>>>                 logger.addAppender(appender, Level.DEBUG, null);
>>>>>>                 ctx.updateLoggers(cfg);
>>>>>>             }
>>>>>>         }
>>>>>>
>>>>>> The problem is that indeed this LogStreamAppender is receiving
>>>>>> everything correctly. However in the log4j2.xml I have several other
>>>>>> appenders added at the ROOT log.
>>>>>> <Appenders>
>>>>>> <Console name="CONSOLE" target="SYSTEM_OUT">
>>>>>> <PatternLayout pattern="%highlight{%d [%t] %-5level:
>>>>>> %msg%n%throwable}" />
>>>>>>  </Console>
>>>>>> .....
>>>>>> </Appenders>
>>>>>> <Root level="info">
>>>>>> <AppenderRef ref="CONSOLE"/>
>>>>>>
>>>>>>  ....
>>>>>> </Root>
>>>>>>
>>>>>> All of which .. start automatically receive my Stream log ... which
>>>>>> is what I don't want to happen :(
>>>>>> So even if I pass additivity to false... the root appenders (which
>>>>>> were info but are now as it looks are debug for this package 
>>>>>> (loggerName))
>>>>>> are still receiving the messages
>>>>>>
>>>>>> Regards,
>>>>>> Nayden
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Tue, Jul 22, 2014 at 10:35 PM, Matt Sicker <[email protected]>
>>>>>> wrote:
>>>>>>
>>>>>>> How are you creating the appender? It might work better using a
>>>>>>> config file.
>>>>>>>
>>>>>>>
>>>>>>> On 22 July 2014 02:47, Nayden Gochev <[email protected]> wrote:
>>>>>>>
>>>>>>>> Hello Matt,
>>>>>>>>
>>>>>>>> this sounds great however it doesn't work.
>>>>>>>>
>>>>>>>> Maybe it is a bug ?
>>>>>>>>
>>>>>>>> what I do is :
>>>>>>>>
>>>>>>>>  final LoggerContext ctx = (LoggerContext)
>>>>>>>> LogManager.getContext(false);
>>>>>>>>
>>>>>>>>             Configuration cfg = ctx.getConfiguration();
>>>>>>>>
>>>>>>>>             if (cfg instanceof XmlConfiguration) {
>>>>>>>>
>>>>>>>>                 //add logger if not added
>>>>>>>>
>>>>>>>>                 LoggerConfig logger = ((XmlConfiguration)
>>>>>>>> cfg).getLogger(loggerName);
>>>>>>>>
>>>>>>>>                 if (logger == null) {
>>>>>>>>
>>>>>>>>                     logger = new LoggerConfig(loggerName,
>>>>>>>> Level.DEBUG, false); //here this false is for the additive
>>>>>>>>
>>>>>>>>                     cfg.addLogger(loggerName, logger);
>>>>>>>>
>>>>>>>>                 } else { //change the level leave it as it is
>>>>>>>>
>>>>>>>>                     logger.setLevel(Level.DEBUG);
>>>>>>>>
>>>>>>>>                 }
>>>>>>>>
>>>>>>>>                 logger.addAppender(newAppender, Level.DEBUG, null);
>>>>>>>>
>>>>>>>>                 ctx.updateLoggers(cfg);
>>>>>>>>
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>> Still .. all root loggers also receive the log message(s) together
>>>>>>>> with this new appender that is passed here.
>>>>>>>>
>>>>>>>> I am using 2.0 final
>>>>>>>>
>>>>>>>>
>>>>>>>> On Jul 21, 2014 5:32 PM, "Matt Sicker" <[email protected]> wrote:
>>>>>>>>
>>>>>>>>> You should specify false for additivity to prevent the automatic
>>>>>>>>> inheritance.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 21 July 2014 09:20, Nayden Gochev <[email protected]> wrote:
>>>>>>>>>
>>>>>>>>>> In short:
>>>>>>>>>> I am trying to add a custom appender + logger for some package
>>>>>>>>>> for example "org.test"
>>>>>>>>>> However the root appenders (appender refs) are always added as
>>>>>>>>>> well automatically.. so even if I have a root appender(s) with level 
>>>>>>>>>> INFO
>>>>>>>>>> defined in the log4j2.xml,
>>>>>>>>>> ones I add a logger with level DEBUG.. with a new appender (only
>>>>>>>>>> 1) .. the 2 root appenders that I have defined in the XML 
>>>>>>>>>> automatically
>>>>>>>>>> starts receiving this DEBUG messages as well.
>>>>>>>>>>
>>>>>>>>>> Is it possible somehow to REMOVE this ROOT appends.. from my
>>>>>>>>>> newly created logger ?
>>>>>>>>>> newLoggerConfig.getAppenderRefs().clear(); doesn't work of course
>>>>>>>>>> :)
>>>>>>>>>>
>>>>>>>>>> Thanks for the help,
>>>>>>>>>> much appreciated.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Matt Sicker <[email protected]>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Matt Sicker <[email protected]>
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Matt Sicker <[email protected]>
>>>>
>>>>
>>>>
>>>
>>>
>>> --
>>> Matt Sicker <[email protected]>
>>>
>>>
>>>
>>
>>
>> --
>> Matt Sicker <[email protected]>
>>
>
>


-- 
Matt Sicker <[email protected]>

Reply via email to