Java >> Java tutorial >  >> Tag >> Log4j

Log4j Database Appenders Eksempel

I dette eksempel skal vi lære at logge beskeder fra vores applikation ind i databasen med log4j.

1. Introduktion

Log4J er en af ​​de mange logningsrammer, der er tilgængelige til brug med Java, måske den mest populære af dem alle. Med Log4J kan du logge det generelle flow af applikationen samt registrere undtagelser.

Et par punkter at bemærke om eksemplet:

  1. Jeg ønskede at gøre eksemplet selvstændigt; har således brugt JUnit til at lave databaseopsætningen til vores eksempels brug. Logningsmekanismen fungerer fra enhver Java-applikationskilde – testcases, webapplikationer, klientapplikationer osv.
  2. Der er ingen kode, der skal udføres eksplicit for at logge meddelelser og fejl/undtagelser i DB. Log4J håndterer alt dette (eller bedre kalde det JDBCAppender).
  3. Dette er et selvstændigt eksempel, der bruger en indlejret database HSQLDB i hukommelsen (du kan bare downloade kildekoden og køre den uden yderligere trin). Men i virkelige scenarier vil du allerede have en DB-opsætning til din applikation. For en lille vejledning om, hvordan du kommer i gang med HSQLDB, gå her.
  4. Dette eksempel handler om JDBCAppender leveret af log4j. For en hurtig opfriskning af bilag, gå her. Der er mange flere bilag til din rådighed; klik her for alle detaljer.

2. Anvendte teknologier

Til dette eksempel bruger vi følgende værktøjer på en Windows 10-platform:

  • Eclipse IDE
  • Apache Maven
  • JDK 1.8
  • Log4J 1.2.17
  • JUnit 4.12
  • HSQLDB 2.3.4

3. Eksempel på Log4j Database Appenders

3.1 Opret et Maven-projekt

Vi vil skabe et absolut minimum Maven-projekt. Når du har installeret Maven og kører på din maskine, skal du udsende følgende kommando fra kommandolinjen.

mvn archetype:generate -DgroupId=com.javacodegeeks -DartifactId=log4j-database-example -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

I dette eksempel vil Maven administrere afhængigheder for os, og vi behøver ikke at downloade nogen jars eksplicit.

3.2 Tilføj Maven-afhængigheder

Tilføj de nødvendige afhængigheder for log4j, HSQLDB, JUnit og log4j ekstramateriale. log4j ekstramateriale giver os org.apache.log4j.EnhancedPatternLayout klasse til formatering af logmeddelelser. Standard er org.apache.log4j.PatternLayout . Vi vil senere se, det er fordelene.

Din pom.xml skulle se sådan ud.
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.javacodegeeks</groupId>
	<artifactId>log4j-database-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>log4j-database-example</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>apache-log4j-extras</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<version>2.3.4</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
	</dependencies>
</project>

3.3 Log4J-egenskaber

Opret log4j.properties til log4j-konfigurationen.

log4j.properties

# Define the root logger with file appender
log4j.rootLogger = DEBUG, DB

# Define the file appender
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.URL=jdbc:hsqldb:mem:exampleDatabase
# Set Database Driver
log4j.appender.DB.driver=org.hsqldb.jdbc.JDBCDriver
# Set database user name and password
log4j.appender.DB.user=root
log4j.appender.DB.password=password
# Set the SQL statement to be executed.
log4j.appender.DB.layout.ConversionPattern=INSERT INTO APP_LOGS VALUES ('%t', now() ,'%C','%L','%p','%m', '%throwable{200}')
# Define the layout for SQL appender
log4j.appender.DB.layout=org.apache.log4j.EnhancedPatternLayout

Her er en forklaring på, hvad der er i denne fil:
Linje 2: Laveste logningsniveau. For detaljer om forskellige logniveauer, tjek dette.
Linje 5: Vi bruger org.apache.log4j.jdbc.JDBCAppender til at logge meddelelser og undtagelser ind i databasen.
BEMÆRK:

JDBCAppender giver mulighed for at sende loghændelser til en database.

Hvert tilføj opkald tilføjer en ArrayList buffer. Når bufferen er fyldt, placeres hver loghændelse i en sql-sætning (konfigurerbar) og udføres. Bufferstørrelse , db URL , Bruger , &Adgangskode er konfigurerbare muligheder på standard log4j måder.
Linje 6-11: Databaseforbindelsesegenskaber
Linje 13: ConversionPattern – Specificerer den SQL-sætning, der skal udføres, hver gang en logningshændelse opstår. Dette kunne være INSERT, UPDATE eller DELETE.
Linje 15: PatternLayout – Målet med denne klasse er at formatere en LoggingEvent og returnere resultaterne som en String. Resultaterne afhænger af konverteringsmønsteret.

BEMÆRK:

1. Med org.apache.log4j.PatternLayout er det ikke muligt at logge undtagelser ind i databasen. Dette opnås med org.apache.log4j.EnhancedPatternLayout.
2. %throwable{short} eller %throwable{1} vil udsende den første linje af staksporing. throwable{none} eller throwable{0} vil undertrykke stak-sporingen. %throwable{n} vil udsende n linjer med stacksporing hvis et positivt heltal eller udelade de sidste -n linjer hvis et negativt heltal.

3.4 Testklasse

Lad os skrive noget kode for bevidst at logge sporingsopkald ind i databasen. Vi vil senere udskrive disse meddelelser for at se outputtet. Vi vil også med vilje forårsage en undtagelse for at se, om den bliver logget ind i databasen.

HelloLog4J.java

package com.javacodegeeks.log4j.database.example;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.log4j.Logger;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * HelloLog4J!
 *
 */
public class HelloLog4J
{
	private static final Logger LOG = Logger.getLogger(HelloLog4J.class);

	@Test
	public void run() {
		LOG.info("This is an example of JDBCAppender of log4j!");

		LOG.debug("Start of run()");

		try {
			// Intentionally we trigger divide by zero exception
			if(23/0 > 23) {
//				some code...
			}
		} catch(Exception e) {
			LOG.error("Execution error", e);
		}

		LOG.debug("End of run()");
	}

	@BeforeClass
	public static void setup() {
		try (Connection connection = getConnection(); Statement statement = connection.createStatement();) {
			Class.forName("org.hsqldb.jdbc.JDBCDriver");

			statement.execute("CREATE TABLE APP_LOGS(THREAD VARCHAR(20), DATE_OF_OCCURENCE DATETIME, CLASS VARCHAR(100),"
					+ "LINE_NUMBER INTEGER, LEVEL VARCHAR(10), MESSAGE VARCHAR(1000), STACKTRACE CLOB)");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@AfterClass
	public static void destroy() {
		try (Connection connection = getConnection(); Statement statement = connection.createStatement();) {
			ResultSet rs = statement.executeQuery("select * from APP_LOGS");
			System.out.println("Thread | Date | Class | Line Number | Level | Message | Stacktrace");
			while(rs.next()) {
				String userId = rs.getString("THREAD");
				Date date = rs.getDate("DATE_OF_OCCURENCE");
				String logger = rs.getString("CLASS");
				int line = rs.getInt("LINE_NUMBER");
				String level = rs.getString("LEVEL");
				String message = rs.getString("MESSAGE");
				String stackTrace = rs.getString("STACKTRACE");
				System.out.println(userId + " | " + date + " | " + logger + " | " + line + " | " + level + " | " 
				+ message + " | " + stackTrace);
			}
			rs.close();
			statement.executeUpdate("DROP TABLE APP_LOGS");
			connection.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public static Connection getConnection() throws SQLException {
		return DriverManager.getConnection("jdbc:hsqldb:mem:exampleDatabase", "root", "password");
	}
}

Output

Thread | Date | Class | Line Number | Level | Message | Stacktrace
main | 2017-04-12 | com.javacodegeeks.log4j.database.example.HelloLog4J | 33 | INFO | This is an example of JDBCAppender of log4j! | 
main | 2017-04-12 | com.javacodegeeks.log4j.database.example.HelloLog4J | 35 | DEBUG | Start of run() | 
main | 2017-04-12 | com.javacodegeeks.log4j.database.example.HelloLog4J | 42 | ERROR | Execution error | java.lang.ArithmeticException: / by zero
	at com.javacodegeeks.log4j.database.example.HelloLog4J.run(HelloLog4J.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

main | 2017-04-12 | com.javacodegeeks.log4j.database.example.HelloLog4J | 45 | DEBUG | End of run() | 

4. Resumé

Med JDBCAppender leveret af Log4J er det muligt at logge både sporingskald og undtagelser ind i databasen. Databasetabellen kan tilpasses med et hvilket som helst antal kolonner efter eget valg, som leveres af mønstrene i org.apache.log4j.EnhancedPatternLayout-klassen.

5. Referencer

  1. https://examples.javacodegeeks.com/enterprise-java/log4j/log4j-appender-example/
  2. https://logging.apache.org/log4j/2.x/manual/appenders.html
  3. https://logging.apache.org/log4j/2.x/manual/index.html

6. Download kildekoden

Du kan downloade den fulde kildekode for dette eksempel her:log4j-database-example JDBCAppender
Java tag