java - Log4j2: Ability to log data with different log levels in multi user environment -


i'm using log4j2 in oracle adf 12c application.

one of requirements of our customer have different log levels different logged-in users , change log levels dynamically user.also administrator should have control stop logging.

i.e lets 'user a' needs trace log level , 'user b' needs error log level. if both users logged in simultaneously, application should log in trace level 'user a' , in error level 'user b'. , if 'user b' wants log in fatal level should able change configuration dynamically.

following log4j2 config file.

    <?xml version="1.0" encoding="utf-8"?> <configuration status="trace">     <mapfilter onmatch="accept" operator="or">         <keyvaluepair key="$${ctx:loglevelyn}" value="y"/>     </mapfilter>     <appenders>         <file name="file" filename="./adfappcustomlogs/testlog4j2.log">             <patternlayout>                 <pattern>%d{yyyy-mm-dd hh:mm:ss.sss} %-5level %class %l %m - %msg%xex%n</pattern>             </patternlayout>         </file>         <console name="stdout" target="system_out">             <patternlayout pattern="%m%n"/>         </console>         <routing name="approuting">             <routes pattern="$${ctx:loggedsessionid}">                 <!-- route chosen if threadcontext has no value key routingkey. -->                 <route key="$${ctx:loggedsessionid}">                     <rollingfile name="rolling-all" filename="./adfappcustomlogs/defaultall.log"                                  filepattern="./adfappcustomlogs/archive/${date:yyyy-mm}/defaultall-%d{mm-dd-yyyy}-%i.txt.gz">                         <patternlayout>                             <pattern>%d{yyyy-mm-dd hh:mm:ss.sss} %-5level %t %msg%xex%n</pattern>                         </patternlayout>                         <policies>                             <timebasedtriggeringpolicy interval="6" modulate="true"/>                             <sizebasedtriggeringpolicy size="10 mb"/>                         </policies>                     </rollingfile>                 </route>                 <!-- route chosen if threadcontext has value 'user' key routingkey. -->                 <route>                     <rollingfile name="rolling-other-${ctx:loggedsessionid}"                                  filename="./adfappcustomlogs/${ctx:loginid}-${ctx:loggedsessionid}.log"                                  filepattern="./adfappcustomlogs/archive/${date:yyyy-mm}/${ctx:loginid}-%d{mm-dd-yyyy}-%i.txt.gz">                         <patternlayout>                             <pattern>%d{yyyy-mm-dd hh:mm:ss.sss} %-5level %t %msg%xex%n</pattern>                         </patternlayout>                         <policies>                             <timebasedtriggeringpolicy interval="6" modulate="true"/>                             <sizebasedtriggeringpolicy size="10 mb"/>                         </policies>                         <!-- <defaultrolloverstrategy max="100"/> -->                     </rollingfile>                 </route>             </routes>         </routing>         <async name="async" buffersize="1000" includelocation="true">             <appenderref ref="approuting"/>         </async>     </appenders>     <loggers>         <root level="trace">             <!--<appenderref ref="file" level="debug"/> -->             <appenderref ref="async"/>             <!-- uncomment following if want log printed in weblogic console -->              <appenderref ref="stdout"/>          </root>     </loggers> </configuration> 

i'm trying create multiple loggers different loglevel each 1 nothing worked.

it great if can give me pointers or hints.

one of requirements of our customer have different log levels different logged-in users , change log levels dynamically user. administrator should have control stop logging.

this require having separate logger each user assume means each thread. can't possibly configure of these loggers in advance since don't know how many users have @ runtime. therefore need dynamically create loggers @ runtime calls log4j2 apis. can refer log4j2 manual full details.

furthermore need create administrative controls allow access log4j2 configuration , provide ability modify configuration @ runtime.

here small example of how can achieve goal of having 1 logger per thread , how change log level during runtime:

here log4j2.xml configuration file:

<?xml version="1.0" encoding="utf-8"?> <configuration status="warn">     <appenders>         <console name="stdout" target="system_out">             <patternlayout pattern="%m%n" />         </console>     </appenders>     <loggers>         <logger name="example" level="trace">             <appenderref ref="stdout" />         </logger>         <root level="warn">             <appenderref ref="stdout" />         </root>     </loggers> </configuration> 

here java code:

package example; import org.apache.logging.log4j.level; import org.apache.logging.log4j.logmanager; import org.apache.logging.log4j.logger; import org.apache.logging.log4j.core.loggercontext; import org.apache.logging.log4j.core.config.appenderref; import org.apache.logging.log4j.core.config.configuration; import org.apache.logging.log4j.core.config.loggerconfig;  public class loglvlbythreadmain {      public static void main(string[] args) {         thread t1 = new thread(new runnable(){              public void run() {                 addlogger(thread.currentthread().getname());                  logger log = logmanager.getlogger(thread.currentthread().getname());                 log.info("here's first thread");                 try {                     thread.sleep(5000);                 } catch (interruptedexception e) {                     e.printstacktrace();                 }                 log.debug("some debug in first thread");                 log.info("finishing first thread");             }}, "thread1");          thread t2 = new thread(new runnable(){              public void run() {                 addlogger(thread.currentthread().getname());                  logger log = logmanager.getlogger(thread.currentthread().getname());                 log.info("here's second thread");                  changeloglevel(thread.currentthread().getname(), level.debug);                  log.debug("some debug in second thread");             }}, "thread2");          t1.start();         t2.start();     }      public static synchronized void addlogger(string name){         appenderref ref = appenderref.createappenderref("stdout", null, null);         appenderref[] refs = new appenderref[] {ref};          loggercontext ctx = (loggercontext) logmanager.getcontext(false);         configuration config = ctx.getconfiguration();         loggerconfig loggerconfig = loggerconfig.createlogger("false", level.info, name,                 "true", refs, null, config, null );          loggerconfig.addappender(config.getappender("stdout"), null, null);         config.addlogger(name, loggerconfig);         ctx.updateloggers();     }      public static synchronized void changeloglevel(string loggername, level lvl){         loggercontext ctx = (loggercontext) logmanager.getcontext(false);         configuration config = ctx.getconfiguration();         loggerconfig loggercfg = config.getloggerconfig(loggername);         loggercfg.setlevel(lvl);         ctx.updateloggers();     }  } 

note have think synchronization problems multiple threads changing logging configuration on fly - notice how 2 methods above alter configuration synchronized.

output above code:

here's second thread here's first thread debug in second thread finishing first thread 

this proves 2 threads have different log levels because if had changed both of them have seen 2 "debug" logs not 1 second thread.


Comments

Popular posts from this blog

How has firefox/gecko HTML+CSS rendering changed in version 38? -

javascript - Complex json ng-repeat -

jquery - Cloning of rows and columns from the old table into the new with colSpan and rowSpan -