I want to use default SLF4J + Logback configuration except setting org.springframework.data.document.mongodb logging level to DEBUG.
How can I do it with Java code?
I'm not using XML, and this decision made at runtime.
The following works for me but generally this is not a good idea. Your code will depend on Logback (you can't choose another logging framework behind SLF4J).
final org.slf4j.Logger logger =
org.slf4j.LoggerFactory.getLogger("test.package");
if (!(logger instanceof ch.qos.logback.classic.Logger)) {
return;
}
ch.qos.logback.classic.Logger logbackLogger =
(ch.qos.logback.classic.Logger) logger;
logbackLogger.setLevel(ch.qos.logback.classic.Level.TRACE);
logger.trace("some log");
Depending to logback-classic is not a good idea as #palacsint stated. You can achieve what you want using Java's Reflection API. Note that this approach puts some overhead to your program because of use of reflection.
Usage:
LogbackUtils.setLogLevel("com.stackoverflow.sample", "DEBUG")
Code:
public static final String LOGBACK_CLASSIC = "ch.qos.logback.classic";
public static final String LOGBACK_CLASSIC_LOGGER = "ch.qos.logback.classic.Logger";
public static final String LOGBACK_CLASSIC_LEVEL = "ch.qos.logback.classic.Level";
private static final Logger logger = LoggerFactory.getLogger(LogbackUtils.class);
/**
* Dynamically sets the logback log level for the given class to the specified level.
*
* #param loggerName Name of the logger to set its log level. If blank, root logger will be used.
* #param logLevel One of the supported log levels: TRACE, DEBUG, INFO, WARN, ERROR, FATAL,
* OFF. {#code null} value is considered as 'OFF'.
*/
public static boolean setLogLevel(String loggerName, String logLevel)
{
String logLevelUpper = (logLevel == null) ? "OFF" : logLevel.toUpperCase();
try
{
Package logbackPackage = Package.getPackage(LOGBACK_CLASSIC);
if (logbackPackage == null)
{
logger.info("Logback is not in the classpath!");
return false;
}
// Use ROOT logger if given logger name is blank.
if ((loggerName == null) || loggerName.trim().isEmpty())
{
loggerName = (String) getFieldValue(LOGBACK_CLASSIC_LOGGER, "ROOT_LOGGER_NAME");
}
// Obtain logger by the name
Logger loggerObtained = LoggerFactory.getLogger(loggerName);
if (loggerObtained == null)
{
// I don't know if this case occurs
logger.warn("No logger for the name: {}", loggerName);
return false;
}
Object logLevelObj = getFieldValue(LOGBACK_CLASSIC_LEVEL, logLevelUpper);
if (logLevelObj == null)
{
logger.warn("No such log level: {}", logLevelUpper);
return false;
}
Class<?>[] paramTypes = { logLevelObj.getClass() };
Object[] params = { logLevelObj };
Class<?> clz = Class.forName(LOGBACK_CLASSIC_LOGGER);
Method method = clz.getMethod("setLevel", paramTypes);
method.invoke(loggerObtained, params);
logger.debug("Log level set to {} for the logger '{}'", logLevelUpper, loggerName);
return true;
}
catch (Exception e)
{
logger.warn("Couldn't set log level to {} for the logger '{}'", logLevelUpper, loggerName, e);
return false;
}
}
// getFieldValue() method omitted for bravity from here,
// but available at GitHub link below.
Full code including tests: Github Gist.
Related
I'm trying to write a customized java rule to check if the debug/trace log levels are enabled. If the log level check has been forgotten, the rule should report an issue.
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
public class CheckDebugAndTraceLevel {
private static final Log LOG = LogFactory.getLog(CheckDebugAndTraceLevel.class);
void foo()
{
if(LOG.isDebugEnabled())
{
LOG.debug("some debug text..");
}
LOG.debug("some debug text.."); // Noncompliant {{ check LOG.debug with an if statement}}
if(LOG.isTraceEnabled())
{
LOG.trace("some debug text..");
}
LOG.trace("some text.."); // Noncompliant {{ check LOG.trace with an if statement}}
}
}
I tested my rule with loggers and recieved "Log.debug" and "Log.trace" from my example class. Still, I get an assertion error while executing jUnit test.
public class DebugAndTraceRule extends BaseTreeVisitor implements JavaFileScanner {
private JavaFileScannerContext context;
private boolean logFlag = false;
#Override
public void scanFile(JavaFileScannerContext context) {
this.context = context;
scan(context.getTree());
}
#Override
public void visitMethod(MethodTree tree) {
super.visitMethod(tree);
String logOption;
for (StatementTree statement : tree.block().body()) {
if (statement.is(Kind.EXPRESSION_STATEMENT)) {
logOption = statement.firstToken().text() + ".";
//System.out.println(statement);
ExpressionStatementTreeImpl eStatement = (ExpressionStatementTreeImpl) statement;
MethodInvocationTreeImpl methodInvoc = (MethodInvocationTreeImpl) eStatement.expression();
MemberSelectExpressionTreeImpl memberSel = (MemberSelectExpressionTreeImpl) methodInvoc.methodSelect();
logOption += memberSel.identifier();
// check logOption
if (logFlag && (logOption.equals("LOG.debug") || logOption.equals("LOG.trace"))) {
//System.out.println(logOption + " - line:" + statement.firstToken().line());
context.reportIssue(this, tree, "debug/trace levels of your logger must be enabled!");
}
}
}
}
#Override
public void visitVariable(VariableTree tree) {
super.visitVariable(tree);
if (tree.type().symbolType().toString().equals("Log")) {
logFlag = true;
}
}
}
If someone could help me out, I would really appreciate it!
I'm using log4j2.
I want to create a RollingFileAppender which rotates the log file on a daily basis.
The name of the logfile is unknown until the application has started (the logfile name is assembled from the application config).
That is why I need to add a RollingFileAppender at runtime.
I have the following code:
public static final ConfigurationBuilder<BuiltConfiguration> BUILDER = ConfigurationBuilderFactory.newConfigurationBuilder
public void initFileLoggerWithFilePattern(final String pattern) {
final LoggerComponentBuilder logger = BUILDER.newLogger("FileLogger", Level.DEBUG);
final AppenderComponentBuilder appender = createFileAppenderWithFilePattern(pattern);
BUILDER.add(appender);
logger.add(BUILDER.newAppenderRef("RollingFileAppender"));
BUILDER.add(logger);
Configurator.initialize(BUILDER.build());
}
public AppenderComponentBuilder createFileAppenderWithFilePattern(final String pattern) {
final AppenderComponentBuilder acb = BUILDER.newAppender("RollingFileAppender", "RollingFile");
acb.addAttribute("fileName", pattern);
acb.addAttribute("filePattern", pattern);
acb.addComponent(createPatternLayout());
acb.addComponent(createTimeBasedTriggeringPolicy());
return acb;
}
public LayoutComponentBuilder createPatternLayout() {
final LayoutComponentBuilder lcb = BUILDER.newLayout("PatternLayout");
lcb.addAttribute("pattern", "%d{yyyy-MM-dd HH:mm:ss.SSS}{GMT}Z %m");
return lcb;
}
public ComponentBuilder createTimeBasedTriggeringPolicy() {
final ComponentBuilder policies = BUILDER.newComponent("Policies");
final ComponentBuilder policy = BUILDER.newComponent("TimeBasedTriggeringPolicy");
policies.addComponent(policy);
return policies;
}
The problem is that this code changes absolutely nothing. No appender as well as no Logger is being added to the configuration. The "FileLogger" that was created programmatically is not available.
I used this code to print the loggers and Appenders after executing the code above.
private void printLog4jConfig() {
final LoggerContext context = (LoggerContext) LogManager.getContext(false);
final Configuration config = context.getConfiguration();
// Print appenders
for(Appender app : config.getAppenders().values()) {
System.out.println(app.getName());
}
// Print Loggers and their Appenders
for(LoggerConfig lc : config.getLoggers().values()) {
System.out.println(lc);
for(Appender app : lc.getAppenders().values()) {
System.out.println(" " + app);
}
}
}
Output:
Appenders
-------------
STDOUT
Loggers
-------------
root
STDOUT
Console
STDOUT
My Question:
What is wrong with my code? Why is my Appender as well as my Logger not added? Respectively why is the configuration not being refreshed / updated ?
How can I add a RollingFileAppender as well as a logger to the log4j2 configuration during runtime?
I found the solution to my problem.
Instead using
Configurator.initialize(BUILDER.build())
I had to use
Configurator.reconfigure(BUILDER.build());
This reloaded the configuration and i was able to see and use my appender and logger.
I'm trying to configure and set up Log4j2 only through using ConfigurationFactory and this reference. The code I'm using is as follows:
public class LoggingConfiguration {
public static final String PATTERN_LAYOUT = "[%d] [%t] [%-5level] - %msg (%logger{1}:%L) %n%throwable";
public static final String LOG_FILE_NAME = "app.log";
public static final String LOG_FILE_NAME_PATTERN = LOG_FILE_NAME + "-yyyy.MM.dd";
static {
ConfigurationFactory.setConfigurationFactory(new Log4j2ConfigurationFactory());
}
/**
* Just to make JVM visit this class to initialize the static parts.
*/
public static void configure() {
}
#Plugin(category = "ConfigurationFactory", name = "Log4j2ConfigurationFactory")
#Order(0)
public static class Log4j2ConfigurationFactory extends ConfigurationFactory {
#Override
protected String[] getSupportedTypes() {
return null;
}
#Override
public Configuration getConfiguration(ConfigurationSource source) {
return new Log4j2Configuration();
}
#Override
public Configuration getConfiguration(String name, URI configLocation) {
return new Log4j2Configuration();
}
}
private static class Log4j2Configuration extends DefaultConfiguration {
public Log4j2Configuration() {
setName("app-log4j2");
String root = System.getProperty("APP_ROOT", "/tmp");
if (!root.endsWith("/")) {
root += "/";
}
// MARKER
Layout<? extends Serializable> layout = PatternLayout.createLayout(PATTERN_LAYOUT, null, null, null, null);
String oneDay = TimeUnit.DAYS.toMillis(1) + "";
String oneMB = (1024 * 1024) + "";
final TimeBasedTriggeringPolicy timeBasedTriggeringPolicy = TimeBasedTriggeringPolicy.createPolicy(oneDay,
"true");
final SizeBasedTriggeringPolicy sizeBasedTriggeringPolicy = SizeBasedTriggeringPolicy.createPolicy(oneMB);
final CompositeTriggeringPolicy policy = CompositeTriggeringPolicy.createPolicy(timeBasedTriggeringPolicy,
sizeBasedTriggeringPolicy);
final DefaultRolloverStrategy strategy = DefaultRolloverStrategy.createStrategy("7", "1", null,
Deflater.DEFAULT_COMPRESSION + "", this);
Appender appender = RollingFileAppender.createAppender(root + LOG_FILE_NAME, LOG_FILE_NAME_PATTERN, "true",
"app-log-file-appender", "true", "true", policy, strategy, layout, null, null, null, null, null);
addAppender(appender);
getRootLogger().addAppender(appender, Level.INFO, null);
}
}
}
Note that
it extends BaseConfiguration that already configures console by default
it tries to add a rolling file appender to the root logger
I get the following exception:
Exception in thread "main" java.lang.IllegalStateException: Pattern does not contain a date
at org.apache.logging.log4j.core.appender.rolling.PatternProcessor.getNextTime(PatternProcessor.java:91)
at org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy.initialize(TimeBasedTriggeringPolicy.java:49)
at org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy.initialize(CompositeTriggeringPolicy.java:43)
at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.<init>(RollingFileManager.java:58)
at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:297)
at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:267)
at org.apache.logging.log4j.core.appender.AbstractManager.getManager(AbstractManager.java:71)
at org.apache.logging.log4j.core.appender.OutputStreamManager.getManager(OutputStreamManager.java:65)
at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.getFileManager(RollingFileManager.java:78)
at org.apache.logging.log4j.core.appender.RollingFileAppender.createAppender(RollingFileAppender.java:175)
at com.narmnevis.papyrus.LoggingConfiguration$Log4j2Configuration.<init>(LoggingConfiguration.java:79)
at com.narmnevis.papyrus.LoggingConfiguration$Log4j2ConfigurationFactory.getConfiguration(LoggingConfiguration.java:55)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:377)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:149)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:85)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:34)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:200)
at org.slf4j.helpers.Log4jLoggerFactory$PrivateManager.getContext(Log4jLoggerFactory.java:104)
at org.slf4j.helpers.Log4jLoggerFactory.getContext(Log4jLoggerFactory.java:90)
at org.slf4j.helpers.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:46)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:270)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:281)
at com.narmnevis.papyrus.Main.<init>(Main.java:12)
at com.narmnevis.papyrus.Main.main(Main.java:21)
If I comment out the code after MARKER in above code, it works but it seems that I'm missing something to configure a rolling file appender. What should I do to fix this?
In log4j 2.x you have to specify the date format in this way
public static final String LOG_FILE_NAME_PATTERN = LOG_FILE_NAME + "-%d{dd-MM-yyy}";
% marks the beginning of a format
d means that it is a date format (you can also use date)
within the curly braces {} you define the formatter's options. In this case the date format. You can use everything that a SimpleDateFormat would accept.
In addition you can also use:
%d{ABSOLUTE} -> HH:mm:ss,SSS
%d{COMPACT} -> yyyyMMddHHmmssSSS
%d{DATE} -> dd MMM yyyy HH:mm:ss,SSS
%d{ISO8601_BASIC} -> yyyyMMdd HHmmss,SSS
%d{ISO8601} -> yyyy-MM-dd HH:mm:ss,SSS
Note: This information is based on log4j 2.0-beta9 (the current release). Since it is a beta version it might change slightly.
How do I print the entire stack trace using java.util.Logger? (without annoying Netbeans).
The question should've originally specified staying within Java SE. Omitting that requirment was an error on my part.
-do-compile:
[mkdir] Created dir: /home/thufir/NetBeansProjects/rainmaker/build/empty
[mkdir] Created dir: /home/thufir/NetBeansProjects/rainmaker/build/generated-sources/ap-source-output
[javac] Compiling 13 source files to /home/thufir/NetBeansProjects/rainmaker/build/classes
[javac] /home/thufir/NetBeansProjects/rainmaker/src/model/TelnetEventProcessor.java:44: error: 'void' type not allowed here
[javac] log.severe(npe.printStackTrace(System.out));
[javac] ^
[javac] 1 error
BUILD FAILED
code with the error:
package model;
import java.util.Observable;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TelnetEventProcessor extends Observable {
private static Logger log = Logger.getLogger(TelnetEventProcessor.class.getName());
private String string = null;
public TelnetEventProcessor() {
}
private void stripAnsiColors() {
Pattern regex = Pattern.compile("\\e\\[[0-9;]*m");
Matcher regexMatcher = regex.matcher(string);
string = regexMatcher.replaceAll(""); // *3 ??
}
public void parse(String string) {
this.string = string;
ifs();
}
// [\w]+(?=\.)
private void ifs() {
log.fine("checking..");
if (string.contains("confusing the hell out of")) {
Pattern pattern = Pattern.compile("[\\w]+(?=\\.)"); //(\w+)\.
Matcher matcher = pattern.matcher(string);
String enemy = null;
GameData data = null;
while (matcher.find()) {
enemy = matcher.group();
}
try {
data = new GameData.Builder().enemy(enemy).build();
log.fine("new data object\t\t" + data.getEnemy());
setChanged();
notifyObservers(data);
} catch (NullPointerException npe) {
log.severe(npe.printStackTrace(System.out));
}
} else if (string.contains("Enter 3-letter city code:")) {
log.fine("found enter city code");
} else {
}
}
}
see also:
https://stackoverflow.com/a/7100975/262852
The severe method is only used to log severe messages without associated throwable information. If you need to log throwable information then you should use the log method instead:
try {
data = new GameData.Builder().enemy(enemy).build();
log.fine("new data object\t\t" + data.getEnemy());
setChanged();
notifyObservers(data);
} catch (NullPointerException npe) {
log.log(Level.SEVERE, npe.getMessage(), npe);
}
Why don't you put the exception in the logger?
You can use this method :
logger.log(Level level, String msg, Throwable thrown)
Maybe a duplicated question? Java - Need a logging package that will log the stacktrace
Below the explanation from the given url
Using log4j
this is done with:
logger.error("An error occurred", exception);
The first argument is a message to be displayed, the second is the
exception (throwable) whose stacktrace is logged.
Another option is commons-logging,
where it's the same:
log.error("Message", exception);
With java.util.logging
this can be done via:
logger.log(Level.SEVERE, "Message", exception);
You don't explicitly print the stack trace; Throwables have stack traces attached to them, and you can pass a Throwable to the log methods:
log(Level level, String msg, Throwable thrown)
You could use Apache ExceptionUtils. In your case
try {
data = new GameData.Builder().enemy(enemy).build();
log.fine("new data object\t\t" + data.getEnemy());
setChanged();
notifyObservers(data);
} catch (NullPointerException npe) {
logger.info(**ExceptionUtils.getFullStackTrace(npe)**);
}
You should redirect the System.err to the logger, the process is not too simple but you can use this code:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LogOutputStream extends ByteArrayOutputStream {//java.io.OutputStream {
private String lineSeparator;
private Logger logger;
private Level level;
public LogOutputStream(Logger logger, Level level) {
super();
this.logger = logger;
this.level = level;
this.lineSeparator = System.getProperty("line.separator");
}
#Override
public void flush() throws IOException {
String record;
synchronized (this) {
super.flush();
record = this.toString();
super.reset();
if ((record.length() == 0) || record.equals(this.lineSeparator)) {
// avoid empty records
return;
}
this.logger.logp(this.level, "", "", record);
}
}
}
And The code to set this (that should called the when you first create the logger
Logger logger = Logger.getLogger("Exception");
LogOutputStream los = new LogOutputStream(logger, Level.SEVERE);
System.setErr(new PrintStream(los, true));
This will redirect the System.err stream to the logger.
You can also try to use ExceptionUtils from apache commons
The exception is due to the printstacktrace method being void, meaning it doesn't return anything. You are trying to do:
log.severe(npe.printStackTrace(System.out));
My guess is that the severe method needs a String and not void.
I have developed a spring application, I want to configure it with apache log4j, have downloaded it and put the jar in project's class path. Below is my log4j.Properties file.
# Root logger option
log4j.rootLogger=INFO, file
# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=C\:\\loging.log
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
And below is my main spring application class.
import org.apache.log4j.Logger;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class DrawingClass {
public static void main(String args[])
{
//without dependency injection
/*Triangle t1 = new Triangle();
t1.draw();*/
//with dependency injection
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("Spring.xml"));
Triangle t1 =(Triangle) factory.getBean("triangle");
t1.draw();
}
}
Please advise if I want to put the log.info in my above main class what modifications I need to do in my main class and also please advise what modifications I need to done to call log4j in my main class?
come up with this solution and it works ..the edited log4j.properties file is
### direct messages to file or.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=C:/logs/s.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1} - %m%n
log4j.appender.file.append=true
### set log levels - for more verbose logging change 'info' to 'debug' ##
log4j.rootCategory=ALL, file
log4j.logger.Demo=\=debug
log4j.logger.org.eclipse=debug
and the way to callit from main class is
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class DrawingClass {
/* Get actual class name to be printed on */
static final Logger log = Logger.getLogger(DrawingClass.class);
public static void main(String args[])
{PropertyConfigurator.configure("log4j.properties");
//without dependency injection
/*Triangle t1 = new Triangle();
t1.draw();*/
log.info("Before execution");
//with dependency injection
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("Spring.xml"));
Triangle t1 =(Triangle) factory.getBean("triangle");
log.info("Hello this is an info message");
t1.draw();
log.info("after object execution");
}
}
If there is any other better way then please advise .
Can you try adding this line to your class -
public class DrawingClass {
static final Logger log = Logger.getLogger(DrawingClass.class);
public static void main(String args[])
{
//without dependency injection
/*Triangle t1 = new Triangle();
t1.draw();*/
log.info("Before execution");
//with dependency injection
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("Spring.xml"));
Triangle t1 =(Triangle) factory.getBean("triangle");
t1.draw();
}
}
Now let me know if anything gets added to the log.
This link might help you - http://www.dzone.com/tutorials/java/log4j/sample-log4j-properties-file-configuration-1.html
For using logging in my project I made such things:
1) Defined special annotation that should mark fields where logger should be injected:
#Retention(RUNTIME)
#Target(FIELD)
#Documented
public #interface InjectLogger {
}
2) Then created special BeanPostProcessor for injected logger into annotated field:
#Component(value="loggerInjector")
public class LoggerInjector implements BeanPostProcessor {
#Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
#Override
public Object postProcessBeforeInitialization(final Object bean, String beanName)
throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException,
IllegalAccessException {
// make the field accessible if defined private
ReflectionUtils.makeAccessible(field);
if (field.getAnnotation(InjectLogger.class) != null) {
Logger log = LoggerFactory.getLogger(bean.getClass());
field.set(bean, log);
}
}
});
return bean;
}
}
3) After this in necessary bean mark property where logger should be injected by #InjectLogger annotation and use this logger in your code.
#InjectLogger
private Logger logger;
public void doSomething(...) {
try{
...
} catch (Exception e) {
logger.error("bla bla bla", e);
}
}
In my project I use slf4j with log4j as concrete implementation. But with log4j it will be similar.
Also you need to know that by default all Spring libs using common-logging. And if you want that Spring libs write their log to your file you should use special additionla lib. You can get them, as I remember, from appache site. For slf4j such lib is named jcl-over-slf4j-1.6.4.jar.
EDIT 2:
Also in spring the good practise is to use AOP for logging. Here is an example of simplified Aspect:
#Component
#Aspect
#Order(value=2)
public class LoggingAspect {
#Around("execution(* com.blablabla.server..*.*(..))")
public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable{
final Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass().getName());
Object retVal = null;
try {
StringBuffer startMessageStringBuffer = new StringBuffer();
startMessageStringBuffer.append("Start method ");
startMessageStringBuffer.append(joinPoint.getSignature().getName());
startMessageStringBuffer.append("(");
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
startMessageStringBuffer.append(args[i]).append(",");
}
if (args.length > 0) {
startMessageStringBuffer.deleteCharAt(startMessageStringBuffer.length() - 1);
}
startMessageStringBuffer.append(")");
logger.trace(startMessageStringBuffer.toString());
StopWatch stopWatch = new StopWatch();
stopWatch.start();
retVal = joinPoint.proceed();
stopWatch.stop();
StringBuffer endMessageStringBuffer = new StringBuffer();
endMessageStringBuffer.append("Finish method ");
endMessageStringBuffer.append(joinPoint.getSignature().getName());
endMessageStringBuffer.append("(..); execution time: ");
endMessageStringBuffer.append(stopWatch.getTotalTimeMillis());
endMessageStringBuffer.append(" ms;");
logger.trace(endMessageStringBuffer.toString());
} catch (Throwable ex) {
StringBuffer errorMessageStringBuffer = new StringBuffer();
// Create error message
logger.error(errorMessageStringBuffer.toString(), e)
throw ex;
}
return retVal;
}
}
# LOG4J configuration
log4j.rootLogger= DEBUG, INFO, Appender1, Appender2
log4j.appender.Appender1=org.apache.log4j.ConsoleAppender
log4j.appender.Appender1.layout=org.apache.log4j.PatternLayout
log4j.appender.Appender1.layout.ConversionPattern=%-7p %d [%t] %c %x - %m%n
log4j.appender.Appender2=org.apache.log4j.FileAppender
log4j.appender.Appender2.File=D:/Project Log/Demo/demo.log
log4j.appender.Appender2.layout=org.apache.log4j.PatternLayout
log4j.appender.Appender2.layout.ConversionPattern=%-7p %d [%t] %c %x - %m%n
Write this code in log4j.properties which is in Resources folder of src folder.
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Write this above code in porm.xml file or download jar for this dependency.
<context:property-placeholder location="classpath:log4j.properties" />
write this above code between and in your spring-config.xml
package com.apmc.controller;
import org.apache.log4j.Logger;
import java.text.DateFormat;
import java.util.Date;
import com.apmc.Generic.RandomGenerator;//This my own made class So You need to create //RandomGenerator for use it
#Controller
public class StateController {
private static Logger logger = Logger.getLogger(StateController.class);
DateFormat df = new SimpleDateFormat("ddMMyyHHmmss");
Date dateobj = new Date();
int randNum = RandomGenerator.randInt(1000, 9999);
String successMsg = "", errorMsg = "";
#Autowired
StateService stateService;
List<State> newList = new ArrayList();
#RequestMapping(value = "/Admin/admin/NewState_form")
public ModelAndView stateForm(#ModelAttribute State state) {
try {
logger.info("\n stateForm Started \n errorcode : "+errorcode);
newList = stateService.loadAll();
logger.info("\n stateForm Completed");
errorMsg = "";
} catch (Exception e) {
errorcode = ""+df.format(dateobj)+randNum;
errorMsg = " New State Form Error \n Please contact Admin and errorcode:" +errorcode;
successMsg = "";
logger.error("error code for stateForm in StateController" +df.format(dateobj)+" errorcode: "+errorcode);
}
return new ModelAndView("state").addObject("editState", new State())
.addObject("errorMsg", errorMsg) .addObject("showStateList",newList)
.addObject("successMsg", successMsg);
}
}
Above example for how to use log in Controller or any Java Class
Here I made for error Tracking create error code show for commmunicate with error using RandomGenerator.java write as below given
package com.apmc.Generic;
import java.util.Random;
public class RandomGenerator {
/**
* Returns a pseudo-random number between min and max, inclusive.
* The difference between min and max can be at most
* <code>Integer.MAX_VALUE - 1</code>.
*
* #param min Minimum value
* #param max Maximum value. Must be greater than min.
* #return Integer between min and max, inclusive.
* #see java.util.Random#nextInt(int)
*/
public static int randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}