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]>
