log4j2 appender talking to sql server database

Viewed 3887

This URL

https://logging.apache.org/log4j/log4j-2.0/manual/appenders.html

has this example:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
  <Appenders>
    <JDBC name="databaseAppender" tableName="dbo.application_log">
      <DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" />
      <Column name="eventDate" isEventTimestamp="true" />
      <Column name="level" pattern="%level" />
      <Column name="logger" pattern="%logger" />
      <Column name="message" pattern="%message" />
      <Column name="exception" pattern="%ex{full}" />
    </JDBC>
  </Appenders>
  <Loggers>
    <Root level="warn">
      <AppenderRef ref="databaseAppender"/>
    </Root>
  </Loggers>
</Configuration>

When I try to wire up to a sqlserver database......

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
   <Appenders>
      <JDBC name="SQLServerAppender" tableName="dbo.LogEntry">
         <DataSource jndiName="jdbc:sqlserver://MyMachine\\MyInstance:1433;databaseName=LoggingDB;applicationName=myappname;integratedSecurity=true;" />
         <Column name="EntryDateUtc" isEventTimestamp="true" />
         <Column name="LOGGER" pattern="%C" />
         <Column name="Level" pattern="%level" />
         <Column name="Message" pattern="%m" />
         <Column name="UserName" pattern="%x" />
         <Column name="Priority" pattern="%p" />
         <Column name="ElapsedMilliseconds" pattern="%r" />
         <Column name="ThreadName" pattern="%t" />
         <Column name="ThrowableMessage" pattern="%throwable " />
      </JDBC>

I get errors like:

ERROR No ConnectionSource provided: connectionSource
ERROR Could not create plugin of type class org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender for element JDBC org.apache.logging.log4j.core.config.ConfigurationException: Arguments given for element JDBC are invalid: field 'connectionSource' has invalid value 'null'

How do I set up a connection string in the xml-configuration to talk to sqlserver?

Even though it doesn't match the documentation, I tried this:

   <Appenders>
      <JDBC name="SQLServerAppender" tableName="dbo.LogEntry">

         <ConnectionSource jndiName="jdbc:sqlserver

It didn't work of course.

What is the magic syntax sugar?? #help

Thanks.

2 Answers

The value of DataSource jndiName is not a SQL Server connection string. If you want to use a SQL Server connection string then put in Log4J configuration put something like:

<appender name="SQLServer" class="org.apache.log4j.jdbc.JDBCAppender">
   <param name="url" value="jdbc:sqlserver://MyMachine\\MyInstance:1433;databaseName=LoggingDB;applicationName=myappname;"/>
   <param name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
   <param name="user" value="user_id"/>
   <param name="password" value="password"/>
   <param name="sql" value="INSERT INTO LOG4J_TABLE VALUES('%x','%d','%C','%p','%m')"/>
   <layout class="org.apache.log4j.PatternLayout"></layout>
</appender>

<logger name="log4j.rootLogger" additivity="false">
   <level value="DEBUG"/>
   <appender-ref ref="SQLServer"/>
</logger>

Which will write to a table that you must have created previously like:

CREATE TABLE LOG4J_TABLE (
User_Id     VARCHAR(20)    NOT NULL,
Date_Stamp  DATETIME       NOT NULL,
Logger      VARCHAR(100)   NOT NULL,
Level       VARCHAR(10)    NOT NULL,
Message     VARCHAR(8000)  NOT NULL
)

Note that you can´t use integratedSecurity=true straightforward from Java but must specify the user + password.

I think the problem is that JNDI is not enabled.

This is my configuration log4j2.xml:

<bean id="dataSourceProxy" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
    <constructor-arg ref="dataSource"/>
</bean>

<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSourceProxy"/>
</bean>

<bean id="jdbcTemplate" class="xx.com.xxxxx.framework.database.xxxxxJDBCTemplate">
    <constructor-arg ref="dataSourceProxy"/>
</bean>

<bean id="DBSession" class="xx.com.xxxxx.framework.database.DBConnectionManager" lazy-init="true">
    <constructor-arg type="java.lang.String" value="DBSession"/>
    <constructor-arg ref="dataSourceProxy"/>
    <constructor-arg ref="transactionManager"/>
    <property name="template" ref="jdbcTemplate"/>
</bean>

It worked normally before we had upgraded log4j to log4j2. After upgrading, there was an error output from my weblogic console:

ERROR Could not create plugin of type class org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender for element JDBC org.apache.logging.log4j.core.config.ConfigurationException: Arguments given for element JDBC are invalid: field 'connectionSource' has invalid value 'null'
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.injectFields(PluginBuilder.java:210)
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:121)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1120)
        ....
    

According to Apache documentation , a Log4j JDBC Appender configured with a DataSource is disabled by default. You may try to add java option -Dlog4j2.enableJndiJdbc=true to use JNDI's java protocol.

When we added set JAVA_OPTIONS=-Dlog4j2.enableJndiJdbc=true into our weblogic, the error was gone. I hope it is helpful for you.

Related