blob: cb6be492eb3c575fdc2c76e217d3ef7b72b0b30f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LOG4CXX_DB_DB_APPENDER_H
#define LOG4CXX_DB_DB_APPENDER_H
#include <log4cxx/log4cxx.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/appenderskeleton.h>
#include <log4cxx/spi/loggingevent.h>
#include <list>
#include <memory>
namespace LOG4CXX_NS
{
namespace db
{
/**
* The DBAppender lets you log messages to a database. This utilizes the APR's database support in order
* to provide a single way of logging to multiple databases, not just ODBC as the ODBCAppender does.
*
* The following SQL script is an example of how you may make a table that stores log messages:
*
* ~~~{.sql}
* CREATE TABLE logs (
* logger VARCHAR(200),
* time DATETIME,
* level CHAR(5),
* file VARCHAR(200),
* line_number INT,
* message VARCHAR(1000)
* );
* ~~~
*
* Once you have defined the table, you must define the order in which the columns are formatted when they are inserted
* along with the insert statement.
*
* Using APR, the following insert statement can be used to insert log statements: <code>INSERT INTO logs (logger, time, level, file, line_number, message) VALUES (%s, %pDa, %s, %s, %d, %s)</code>
* The values to insert must be formatted appropriately and in the correct order. In order to do this, the parameter <code>ColumnMapping</code> must be specified as many times
* as there are columns to insert.
*
* The following table shows the conversion specifiers. These are effectively the same as the conversion patterns provided by PatternLayout but with more descriptive names:
* |Conversion Specifier|Effect|
* |---|---|
* |logger|The name of the logger(e.g. com.foo.bar)|
* |class|The class that the log message was in|
* |time|The time of the log message|
* |shortfilename|The short filename where the log message is from|
* |fullfilename|The full filename where the log mesasge is from|
* |location|The location of the log message|
* |line|The line where the log message appears|
* |message|The log message|
* |method|The method where the message was logged|
* |level|The level of the log message|
* |thread|The thread where this message was logged|
* |threadname|The name of the thread that logged the message|
* |ndc|The NDC(nested diagnostic context) of the log|
*
* Other parameters that are important:
* |Parameter name|Usage|
* |---|---|
* |DriverName|The name of the database driver to load(ex: odbc, sqlite3)|
* |DriverParams|A string of parameters to pass to the driver. This is database-specific|
* |DatabaseName|The name of the database to use when connecting to the server|
*
* The following code shows how you might connect to an ODBC data source and insert the log messages:
* ~~~{.xml}
* <appender name="SqlDBAppender" class="DBAppender">
* <param name="drivername" value="odbc"/>
* <param name="DriverParams" value="DATASOURCE=MariaDB-server"/>
* <param name="DatabaseName" value="example_database"/>
* <param name="sql" value="INSERT INTO logs (logger, time, level, file, line_number, message) VALUES (%s, %pDa, %s, %s, %d, %s)" />
* <param name="ColumnMapping" value="logger"/>
* <param name="ColumnMapping" value="time"/>
* <param name="ColumnMapping" value="level"/>
* <param name="ColumnMapping" value="shortfilename"/>
* <param name="ColumnMapping" value="line"/>
* <param name="ColumnMapping" value="message"/>
* </appender>
* ~~~
*
* A similar configuration can be used for SQLite:
* ~~~{.xml}
* <appender name="SqlDBAppender" class="DBAppender">
* <param name="drivername" value="sqlite3"/>
* <param name="DriverParams" value="/path/to/database.db"/>
* <param name="sql" value="INSERT INTO logs (logger, time, level, file, line_number, message) VALUES (%s, %pDa, %s, %s, %d, %s)" />
* <param name="ColumnMapping" value="logger"/>
* <param name="ColumnMapping" value="time"/>
* <param name="ColumnMapping" value="level"/>
* <param name="ColumnMapping" value="shortfilename"/>
* <param name="ColumnMapping" value="line"/>
* <param name="ColumnMapping" value="message"/>
* </appender>
* ~~~
*/
class LOG4CXX_EXPORT DBAppender : public AppenderSkeleton
{
public:
DECLARE_LOG4CXX_OBJECT(DBAppender)
BEGIN_LOG4CXX_CAST_MAP()
LOG4CXX_CAST_ENTRY(DBAppender)
LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
END_LOG4CXX_CAST_MAP()
DBAppender();
virtual ~DBAppender();
/**
\copybrief AppenderSkeleton::setOption()
Supported options | Supported values | Default value
:-------------- | :----------------: | :---------------:
DriverName | {any} | -
DriverParams | {any} | -
DatabaseName | {any} | -
SQL | {any} | -
ColumnMapping | (\ref rep "^") | -
\anchor rep (^) One value for each '%%' character in the SQL value.
\sa AppenderSkeleton::setOption()
*/
void setOption(const LogString& option, const LogString& value) override;
/**
Activate the specified options.
*/
void activateOptions(helpers::Pool& p) override;
/**
* Adds the event to the buffer. When full the buffer is flushed.
*/
void append(const spi::LoggingEventPtr& event, helpers::Pool&) override;
void close() override;
/**
* DBAppender does not require a layout.
* */
bool requiresLayout() const override
{
return false;
}
/**
* Set pre-formated statement eg: insert into LogTable (msg) values (?)
*/
void setSql(const LogString& s);
/**
* Returns pre-formated statement eg: insert into LogTable (msg) values (?)
*/
const LogString& getSql() const;
private:
DBAppender(const DBAppender&);
DBAppender& operator=(const DBAppender&);
protected:
struct DBAppenderPriv;
}; // class DBAppender
LOG4CXX_PTR_DEF(DBAppender);
} // namespace db
} // namespace log4cxx
#endif // LOG4CXX_DB_DB_APPENDER_H