log4jdbc is a jar package used to record database sql. Need to be used with log class .jar. Our company used log4j before. But log4j is said to have performance issues. Finally, we switched to the now more popular logback logging framework. However, an adapted jar package needs to be used in the middle, so the combination is log4jdbc+log4j-over-slfj+logback.
1. How to configure
The database connection configuration is modified as follows:
#driver needs to be configured as the driver class of the adapted log4jdbc dataSource.driverClass=net.sf.log4jdbc.sql.jdbcapi.DriverSpy #jdbcUrl needs to add the preceding head:jdbc\:log4 dataSource.jdbcUrl=jdbc\:log4jdbc\:jtds\:sybase\://ip\:port/db;charset\=UTF-8;appname\=appname;
log4jdbc specific configuration - log4jdbc.log4j2.properties:
#Configure the real database driver log4jdbc.drivers=net.sourceforge.jtds.jdbc.Driver # log4jdbc.dump.fulldebugstacktrace = false #Configure to match the path of the package or class that needs to be recorded log4jdbc.debug.stack.prefix= #sql maximum line length log4jdbc.dump.sql.maxlinelength=150 #spy log processing class log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator #warn level log, if the time-consuming time exceeds the configuration value, it will be printed out log4jdbc.sqltiming.warn.threshold=100logback configuration:
<appender name="jdbcfile" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${baseHome}/${appname}_jdbc_${ip}_${port}.log</File> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] [%-5thread] %logger{20} - %msg%n</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>warn</level> </filter> <append>true</append> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${baseHome}/${appname}_jdbc_${ip}_${port}.%d{yyyy-MM-dd}(%i).log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>200MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> </appender> <logger name="jdbc.sqltiming" level="warn" additivity="false"> <appender-ref ref="jdbcfile" /> </logger>2. Source tracking
First, let's take a look at the driver class of the agent -- net.sf.log4jdbc.sql.jdbcapi.DriverSpy
1. Why does jdbcUrl need to add the preceding head:jdbc\:log4?
/** * A <code>String</code> representing the prefix of URL * to use log4jdbc. */ static final private String log4jdbcUrlPrefix = "jdbc:log4"; /** * Get the actual URL that the real driver expects * (strip off <code>#log4jdbcUrlPrefix</code> from <code>url</code>). * * @param url A <code>String</code> corresponding to a JDBC url for log4jdbc. * @return A <code>String</code> representing url * with <code>#log4jdbcUrlPrefix</code> stripped off. */ private String getRealUrl(String url) { return url.substring(log4jdbcUrlPrefix.length()); }2. Does log4jdbc.log4j.properties only have these properties?
More than that @~@
// You can know much more than this public final class Properties { private static volatile SpyLogDelegator log; /** * A <code>String</code> representing the name of the class implementing * <code>SpyLogDelegator</code> to use. It is used by {@link SpyLogFactory} * to determine which class to load. * Default is <code>net.sf.log4jdbc.log4j2.Log4j2SpyLogDelegator</code> * * @see SpyLogFactory */ static final String SpyLogDelegatorName; //Here is a list of what you want to see and see the properties /** * Static initializer. */ static { //first we init the logger log = null; //then we need the properties to define which logger to use java.util.Properties props = getProperties(); SpyLogDelegatorName = props.getProperty("log4jdbc.spylogdelegator.name");//。。。。。 } private static java.util.Properties getProperties() { java.util.Properties props = new java.util.Properties(System.getProperties()); //try to get the properties file. //default name is log4jdbc.log4j2.properties //check first if an alternative name has been provided in the System properties String propertyFile = props.getProperty("log4jdbc.log4j2.properties.file", "/log4jdbc.log4j2.properties"); if (log != null) { log.debug("Trying to use properties file " + propertyFile); } InputStream propStream = Properties.class.getResourceAsStream(propertyFile); if (propStream != null) { try { props.load(propStream); } catch (IOException e) { if (log != null) { log.debug("Error when loading log4jdbc.log4j2.properties from classpath: " + e.getMessage()); } } finally { try { propStream.close(); } catch (IOException e) { if (log != null) { log.debug("Error when closing log4jdbc.log4j2.properties file" + e.getMessage()); } } } if (log != null) { log.debug("log4jdbc.logj2.properties loaded from classpath"); } } else { if (log != null) { log.debug("log4jdbc.logj2.properties not found in classpath. Using System properties."); } } return props; } }3. Where is the connect method of log4jdbc called?
getConnection method of java.sql.DriverManager
try { println(" trying " + aDriver.driver.getClass().getName()); Connection con = aDriver.driver.connect(url, info); if (con != null) { // Success! println("getConnection returning " + aDriver.driver.getClass().getName()); return (con); } } catch (SQLException ex) { if (reason == null) { reason = ex; } }4. When was the log recorded?
These are the detected sql_spy classes:
public boolean execute(String sql, String[] columnNames) throws SQLException { String methodCall = "execute(" + sql + ", " + columnNames + ")"; this.sql = sql; reportStatementSql(sql, methodCall); //This place starts to call Slf4jSpyLogDelegator long tstart = System.currentTimeMillis(); try { boolean result = realStatement.execute(sql, columnNames); reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);//2 return reportReturn(methodCall, result);//3 } catch (SQLException s) { reportException(methodCall, s, sql, System.currentTimeMillis() - tstart); throw s; } }The following is the processing class for printing sql, if you want to assign it according to your standard or log level, you can implement the interface SpyLogDelegator:
The above is all my content. I am a young woman in the IT field. Someone asked you how far you want to go in IT? I want to say, as far as others can go, I can too! There is no end!