Karaf leverages Pax Logging for the logging layer. Pax Logging provides an abstraction service for most popular logging frameworks, like SLF4J, Log4j, commons-logging, etc.
Karaf provides a default logging configuration in etc/org.ops4j.pax.logging.cfg file.
By default, all INFO log messages (rootLogger) are send into a file appender (in data/log/karaf.log). The file appender “maintains” one file of 1MB, and store up to 10 backup files.
Adding a new appender configuration, example with Syslog appender
We can add new appender configuration in the Karaf logging module.
For instance, we can add a syslog appender in etc/org.ops4j.pax.logging.cfg:
log4j.rootLogger = INFO, out, syslog, osgi:*
...
# Syslog appender
log4j.appender.syslog=org.apache.log4j.net.SyslogAppender
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern=[%p] %c:%L - %m%n
log4j.appender.syslog.syslogHost=localhost
log4J.appender.syslog.facility=KARAF
log4j.appender.syslog.facilityPrinting=false
...
We create the syslog appender configuration, and we use this appender for the rootLogger.
Pax Logging provides all default Log4j appenders.
Creating a custom appender
It’s also possible to create your own appender.
For instance, you want to create MyJDBCAppender, extending the standard Log4J JDBCAppender. MyJDBCAppender has a better management of the quote in the SQL query for a DB2 backend for instance:
package org.apache.karaf.blog.logging.appender;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.jdbc.JDBCAppender;
/**
* Override apache log4j JDBCAppender for DB2 use (escaping of ' char in data)
* Need proper substitution of the ' char by {@link SQL_APOS} in the writing of the log4j sql property
*/
public class MyJDBCAppender extends JDBCAppender {
private static final String SQL_APOS = "{sql_apos}";
private static final String XML_APOS = "'";
/** {@inheritDoc} */
@Override
protected String getLogStatement(LoggingEvent event) {
String sqlLayout = getLayout().format(event);
// escape ' as standard sequence (') in the sql statement after layout
sqlLayout = sqlLayout.replace("'", XML_APOS);
// revert specific sequence as ' to have final executable sql statement
sqlLayout = sqlLayout.replace(SQL_APOS, "'");
return sqlLayout;
}
}
We put the MyJDBCAppender java file in a src/main/java/org/apache/karaf/blog/logging folder.
We package this appender as an OSGi bundle. This bundle is a fragment to the Pax Logging service bundle:
<?xml version="1.0" encoding="UTF-8"?>
<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>org.apache.karaf.blog.logging.appender</groupId>
<artifactId>org.apache.karaf.blog.logging.appender.jdbc</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.ops4j.pax.logging</groupId>
<artifactId>pax-logging-service</artifactId>
<version>1.6.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>org.apache.karaf.blog.logging.appender.jdbc</Bundle-SymbolicName>
<Export-Package>org.apache.karaf.blog.logging.appender</Export-Package>
<Import-Package/>
<Private-Package>org.apache.log4j.jdbc</Private-Package>
<Fragment-Host>org.ops4j.pax.logging.pax-logging-service</Fragment-Host>
<_failok>true</_failok>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
We can use our appender in etc/org.ops4j.pax.logging.cfg file, for instance:
log4j.rootLogger = INFO, out, myappender, osgi:*
...
log4j.appender.myappender=org.apache.karaf.blog.logging.appender.MyJDBCAppender
log4j.appender.myappender.url=jdbc:db2:....
log4j.appender.myappender.driver=com.ibm.db2.jcc.DB2Driver
log4j.appender.myappender.user=username
log4j.appender.myappender.password=password
log4j.appender.myappender.sql=insert into logs values({{sql_apos}%x{sql_apos}, {sql_apos}%d{sql_apos}, {sql_apos}%C{sql_apos}, {sql_apos}%p{sql_apos}, {sql_apos}%m{sql_apos})
log4j.appender.myappender.layout=org.apache.log4j.PatternLayout
In order to be loading very early in the Karaf bootstrap, our appender bundle should be present in the system folder and defined in etc/startup.properties.
The system folder has a “Maven repo like” structure. So you have to copy with:
system/groupId/artifactId/version/artifactId-version.jar
In our example, it means:
mkdir -p $KARAF_HOME/system/org/apache/karaf/blog/logging/appender
cp target/org.apache.karaf.blog.logging.appender.jdbc-1.0-SNAPSHOT.jar $KARAF_HOME/system/org/apache/karaf/blog/logging/appender/org.apache.karaf.blog.logging.appender.jdbc/1.0-SNAPSHOT/org.apache.karaf.blog.logging.appender.jdbc-1.0-SNAPSHOT.jar
and in etc/startup.properties, we define the appender bundle just after the pax-logging-service bundle:
...
org/ops4j/pax/logging/pax-logging-api/1.6.9/pax-logging-api-1.6.9.jar=8
org/ops4j/pax/logging/pax-logging-service/1.6.9/pax-logging-service-1.6.9.jar=8
org/apache/karaf/blog/logging/appender/org.apache.karaf.blog.logging.appender.jdbc/1.0-SNAPSHOT/org.apache.karaf.blog.logging.appender.jdbc-1.0-SNAPSHOT.jar=8
...
You can now start Karaf, it will use our new custom appender.