I have a log table in my database that keeps track of login, logout, timeout, and what the user does while they are logged on. My Java is set up so that every time I do LOGGER.info(message), the message goes into the MESSAGE column of my table.
Here is the log4j.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<appender name="db" class="org.apache.log4j.jdbcplus.JDBCAppender">
<param name="connector" value="com.blahblahblah.jdbcplus.MySqlConnectionHandler" />
<param name="sql"
value="INSERT INTO LOG(LEVEL, MESSAGE, TIMESTAMP, HOST) VALUES ('#PRIO#', '#MSG#', '#TIMESTAMP#', 'Test')" />
<layout class="org.apache.log4j.PatternLayout"></layout>
</appender>
<!-- Application Loggers -->
<logger name="com.blahblahblah.service.ZebraService">
<level value="info" />
<appender-ref ref="db" />
</logger>
<logger name="com.blahblahblah.service.ZplTemplateService">
<level value="info" />
<appender-ref ref="db" />
</logger>
<logger name="com.blahblahblah.service.MyService">
<level value="info" />
<appender-ref ref="db" />
</logger>
<logger name="com.blahblahblah.web.controller.ViewController">
<level value="info" />
<appender-ref ref="db" />
</logger>
<logger name="com.blahblahblah.security">
<level value="info" />
<appender-ref ref="db" />
</logger>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="error" />
</logger>
<logger name="org.springframework.beans">
<level value="error" />
</logger>
<logger name="org.springframework.context">
<level value="error" />
</logger>
<logger name="org.springframework.web">
<level value="error" />
</logger>
<logger name="org.springframework.web.servlet.DispatcherServlet">
<level value="error" />
</logger>
<logger name="org.springframework.security">
<level value="error" />
</logger>
<logger name="org.springframework.aop">
<level value="error" />
</logger>
<logger name="org.springframework.ui">
<level value="error" />
</logger>
<!-- Root Logger -->
<root >
<priority value="error" />
<appender-ref ref="console" />
</root>
This prints "INFO" in the LEVEL column, my information about login/logout in the MESSAGE column, the timestamp in the TIMESTAMP column, and "Test" in the HOST column.
I want to have the HOST column be the local machine name. For example, my computer's name is PC-1050, so every time I do something on that computer, I want HOST to say "PC-1050".
I have no idea how to do the #MSG#, #TIMESTAMP#, etc. I was just following what I was told to do. Can anyone offer some assistance? Thanks.
I did some research on log4j configuration for JDBCAppender and unfortunately did not see any easy way to do it (i.e. nothing along the lines of a simple change to the log4j.xml file) for Hostname.
I did not find anything for Hostname along the lines of
Priority #PRIO#
Message #MSG#
Timestamp #TIMESTAMP#
for your SQL of
INSERT INTO LOG(LEVEL, MESSAGE, TIMESTAMP, HOST) VALUES
('#PRIO#', '#MSG#', '#TIMESTAMP#', 'Test')
Also, I did not see anything in log4j documentation on PatternLayout for Hostname. I woudl think that if there was a macro for it in log4j JDBCAppender, it would correspond to a conversion character in PatternLayout.
You could look at putting the Hostname into the MDC. Here is an example of someone else who uses log4j JDBCAppender and put the user into the MDC.
Good luck, hope this helps!
Related
I am using Logback for logging. Now all logs are writing into one file, and it becomes very large. How to organize logging in such a way that a new file is created at the beginning of a new day?
I use such logback.xml
<configuration>
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %p %m%n" />
<property name="APP_LOG_ROOT" value="admin-logs"/>
<timestamp key="year" datePattern="yyyy" />
<timestamp key="month" datePattern="MM" />
<timestamp key="date" datePattern="dd" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5relative %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<logger level="INFO" name="my.name">
<appender-ref ref="STDOUT" />
</logger>
<root level="ERROR">
<appender-ref ref="STDOUT" />
</root>
</configuration>
all logs are writing into one file
The shown config is going to the STDOUT, not a file.
If you want to write to a daily file, use logrotate/cron process, or have logback do this itself.
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_DIR}/bim.%d{yyyy-MM-dd}.log</fileNamePattern>
...
</appender>
...
<logger level="INFO" name="my.name">
<appender-ref ref="file" />
</logger>
<root level="ERROR">
<appender-ref ref="file" />
</root>
This is my Log4j config file:
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="error" />
</logger>
<logger name="org.springframework.beans">
<level value="error" />
</logger>
<logger name="org.springframework.context">
<level value="error" />
</logger>
<logger name="org.springframework.web">
<level value="error" />
</logger>
<logger name="org.hibernate">
<level value="error" />
</logger>
<logger name="org.springframework.security">
<level value="error" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
.
And I use a logge into a service for example, like this:
private static final Logger LOG = LoggerFactory.getLogger(CommessaServiceImpl.class);
and then:
LOG.info("Start method");
But I can see nothing about it into my console...
Why??
Because you are logging info(LOG.info) and logging level is set to error and warn.
Change it to
<root>
<priority value="info" />
<appender-ref ref="console" />
</root>
There are a couple of reasons you will not see logs.
You have not defined any appenders. You need something like:
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<!-- Pattern to output the caller's file name and line number -->
<param name="ConversionPattern" value="%d{dd-MM-yy HH:mm:ss,SS} %5p [%t] (%F:%L) - %m%n" />
</layout>
</appender>
Your log levels are all set to "error" and you are trying to log at the "info" level.
Looked at quite a few examples on this and have seen some confusing stuff. Here is the log4j.xml file
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<appender name="file" class="org.apache.log4j.RollingFileAppender">
<param name="append" value="false" />
<param name="maxFileSize" value="1000KB" />
<param name="maxBackupIndex" value="5" />
<!-- For Tomcat -->
<param name="file" value="${catalina.home}/logs/demandManage.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<logger name="com.xxx.demand.domain.data" additivity="true">
<level value="debug" />
<appender-ref ref="file"/>
</logger>
<logger name="com.xxx.rita.serviceserver.controller.AbstractRestController" additivity="true">
<level value="debug" />
<appender-ref ref="file"/>
<appender-ref ref="console" />
</logger>
<logger name="com.xxx.dao.AbstractDAOImpl" additivity="true">
<level value="debug" />
<appender-ref ref="file"/>
<appender-ref ref="console" />
</logger>
<logger name="org.hibernate" >
<level value="warn" />
<appender-ref ref="file"/>
</logger>
<root>
<priority value ="warn" />
<appender-ref ref="console" />
<appender-ref ref="file"/>
</root>
</log4j:configuration>
In my java class:
package com.xxx.dao;
public abstract class AbstractDAOImpl<T, ID extends Serializable> implements AbstractDAO<T,ID>{
private Logger logger = LoggerFactory.getLogger(com.xxx.dao.AbstractDAOImpl.class);
#SuppressWarnings("unchecked")
public T read(ID id){
T response = (T) getCurrentSession().get(clazz, id);
if(response==null){
logger.error(RiskTaker.name.get()+ " tried to load " + clazz + " of " +id);
throw new RuntimeException("hibernate object did not exist");
}
return response;
}
}
So when I am hitting the logger.error message with this configuration, nothing is going to the demandManage.log file or the console. I don't see what's wrong. When I had root set to debug, hibernate of course practically fills up that log file so it does work.
Is there a difference between using level vs priority? Like a slfj4 vs appache logger? The root sets priority but the child loggers are using level.
I am starting tomcat in debug mode and know I am hitting those logger.error statements but the file remains empty. May be I need to flush to it right away?
I previously had the logger in the xml file as fully qualified and in the java class as just class name only but fixing that did nothing. I am wondering what I am missing. Thank you in advance.
Logs are not written properly
slf version slf4j-api-1.7.5.jar, slf4j-log4j12-1.7.5.jar, log4j-1.2.16.jar
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!-- log4j generic catchall for adapters. -->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Example DailyRollingFile appender, this is the preferred logging appender -->
<appender name="CommonAdapterAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="/opt/adapter.log" />
<param name="encoding" value="UTF-8" />
<param name="append" value="true" />
<!-- Rollover at the top of every hour -->
<param name="DatePattern" value="'.'yyyy-MM-dd-HH" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS-zzz} %5p [%t] %c{1} - %m%n" />
</layout>
</appender>
<!-- Categories -->
<category name="com.other" additivity="false">
<priority value="warn" />
</category>
<logger name="com.adapter" additivity="false">
<level value="debug" />
<appender-ref ref="CommonAdapterAppender"/>
</logger>
<logger name="com.adaptations" additivity="false">
<level value="debug" />
<appender-ref ref="CommonAdapterAppender"/>
</logger>
<root>
<priority value="error" />
<appender-ref ref="CommonAdapterAppender" />
<!-- <appender-ref ref="SyslogAppender"/> -->
</root>
</log4j:configuration>
The above log4j file is used by multiple adapters. First time it is writing to adapter.log and after that only some component logs are written. Also I have noticed that after the second time it is writing few logs to adapter.log..
I cannot understand what is going wrong here. Can someone please help me out?
I believe you should be using a single shared log 4J configuration and instance for all your adapters if you want to use the the same log file.
As is, Log 4j instances are probably competing for the control of the file.
I am using iBatis with spring framework. I want to log the sql that iBatis executes when I say something like
Employee e = (Employee) getSqlMapClientTemplate().queryForObject("emp_sql", emp);
The above line will look for "emp_sql" id in the ibatis sql file that I have. And then run the query corresponding to "emp_sql". I want to log this query.
I have the following log4j xml properties file.
<appender name="sqlLogAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="/disk1/logs/sql.log"/>
<param name="datePattern" value="'-'yyyy-MM-dd'.txt'"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m %n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="DEBUG"/>
</filter>
</appender>
<logger name="log4j.logger.com.ibatis">
<level value="DEBUG"/>
<appender-ref ref="sqlLogAppender"/>
</logger>
<logger name="log4j.logger.java.sql.Connection">
<level value="DEBUG"/>
<appender-ref ref="sqlLogAppender"/>
</logger>
<logger name="log4j.logger.java.sql.PreparedStatement">
<level value="DEBUG"/>
<appender-ref ref="sqlLogAppender"/>
</logger>
I still cannot get the sql that the ibatis executed.
Is there something wrong with the configuration?
Should I just say
<appender name="sqlLogAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="/disk1/logs/sql.log"/>
<param name="datePattern" value="'-'yyyy-MM-dd'.txt'"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m %n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="DEBUG"/>
</filter>
</appender>
<logger name="log4j.logger.java.sql">
<level value="DEBUG"/>
<appender-ref ref="sqlLogAppender"/>
</logger>
Do I have to use p6spy or something else? Or is there something that I can do in the log4j configuration to get the iBatis sql logs?
Add the following to your log4j configuration (uncomment what you want to see).
# SqlMap logging configuration.
#log4j.logger.com.ibatis=DEBUG
#log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
#log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
#log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
#log4j.logger.java.sql=DEBUG
#log4j.logger.java.sql.Connection=DEBUG
#log4j.logger.java.sql.Statement=DEBUG
#log4j.logger.java.sql.PreparedStatement=DEBUG
#log4j.logger.java.sql.ResultSet=DEBUG
Add this in your log4j.xml
<logger name="com.ibatis" additivity="false">
<level value="debug"/>
<appender-ref ref="APPENDER"/>
</logger>
If you are using Log4j as your logging framework you need to set mybatis to use log4j as its default logging tool. You can do this by setting it in the mybatis-config.xml like this,
<setting name="logImpl" value="LOG4J"/>
Or if you are not using mybatis-config.xml and just annotations, then you want to use
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
before invoking any other mybatis methods to set the default logging implementation. Read More...
Use this configuration in your log4j.properties,
# Global logging configuration
log4j.rootLogger=INFO, stdout
# MyBatis mapper interfaces logging configuration...
log4j.logger.com.sample.mappers=DEBUG
# SqlMap logging configuration.
log4j.logger.org.mybatis.spring=DEBUG
log4j.logger.org.apache.ibatis=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%p] %c - %m%n
If you are using log4j.xml configuration try this equivalent of the above,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%p] %c{1} - %m%n"/>
</layout>
</appender>
<logger name="org.mybatis.spring" additivity="false">
<level value="debug"/>
<appender-ref ref="STDOUT"/>
</logger>
<logger name="com.sample.mappers">
<level value="debug"/>
<appender-ref ref="STDOUT"/>
</logger>
<!-- Other custom 3rd party logger configs -->
<root>
<priority value ="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
Either use properties file or xml file to configure log4j as above and place it in your classpath for this to work correctly.
Add this in your log4j
<logger name="java.sql" additivity="false">
<level value="debug" />
<appender-ref ref="console" /> </logger>
This will print out the sql as well as the output results