Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
4af6fc12
Commit
4af6fc12
authored
Jul 15, 2014
by
Tomek Mrugalski
🛰
Browse files
[3427] Logging configuration implemented.
parent
0a00f963
Changes
11
Hide whitespace changes
Inline
Side-by-side
src/bin/d2/d_controller.cc
View file @
4af6fc12
...
...
@@ -18,6 +18,7 @@
#include
<d2/d_controller.h>
#include
<exceptions/exceptions.h>
#include
<log/logger_support.h>
#include
<dhcpsrv/configuration.h>
#include
<sstream>
...
...
@@ -217,6 +218,28 @@ DControllerBase::configFromFile() {
isc
::
data
::
ConstElementPtr
whole_config
=
isc
::
data
::
Element
::
fromJSONFile
(
config_file
,
true
);
// Let's configure logging before applying the configuration,
// so we can log things during configuration process.
// Temporary storage for logging configuration
isc
::
dhcp
::
ConfigurationPtr
storage
(
new
isc
::
dhcp
::
Configuration
());
// Get 'Logging' element from the config
isc
::
data
::
ConstElementPtr
logger
=
whole_config
->
get
(
"Logging"
);
if
(
logger
)
{
// Configure logger first, so it can be applied to DHCPv6
// configuration. If we don't have a logger, just pass
// empty configuration.
Daemon
::
configureLogger
(
logger
,
storage
);
}
else
{
// There was no Logging element defined in the config file.
// Let's pass an empty pointer that will remove any current
// configuration.
Daemon
::
configureLogger
(
isc
::
data
::
ConstElementPtr
(),
storage
);
}
// Extract derivation-specific portion of the configuration.
module_config
=
whole_config
->
get
(
getAppName
());
if
(
!
module_config
)
{
...
...
src/bin/dhcp4/kea_controller.cc
View file @
4af6fc12
...
...
@@ -17,6 +17,7 @@
#include
<dhcp4/json_config_parser.h>
#include
<dhcp4/ctrl_dhcp4_srv.h>
#include
<dhcp4/dhcp4_log.h>
#include
<dhcpsrv/cfgmgr.h>
#include
<exceptions/exceptions.h>
#include
<string>
...
...
@@ -42,6 +43,7 @@ void configure(const std::string& file_name) {
isc
::
data
::
ConstElementPtr
json
;
isc
::
data
::
ConstElementPtr
dhcp4
;
isc
::
data
::
ConstElementPtr
logger
;
isc
::
data
::
ConstElementPtr
result
;
// Basic sanity check: file name must not be empty.
...
...
@@ -62,6 +64,23 @@ void configure(const std::string& file_name) {
" file: "
<<
file_name
);
}
// Let's configure logging before applying the configuration,
// so we can log things during configuration process.
logger
=
json
->
get
(
"Logging"
);
if
(
logger
)
{
// Configure logger first, so it can be applied to DHCPv6
// configuration. If we don't have a logger, just pass
// empty configuration.
Daemon
::
configureLogger
(
logger
,
CfgMgr
::
instance
().
getConfiguration
());
}
else
{
// There was no Logging element defined in the config file.
// Let's pass an empty pointer that will remove any current
// configuration.
Daemon
::
configureLogger
(
isc
::
data
::
ConstElementPtr
(),
CfgMgr
::
instance
().
getConfiguration
());
}
// Get Dhcp4 component from the config
dhcp4
=
json
->
get
(
"Dhcp4"
);
...
...
src/bin/dhcp6/kea_controller.cc
View file @
4af6fc12
...
...
@@ -47,6 +47,7 @@ void configure(const std::string& file_name) {
isc
::
data
::
ConstElementPtr
json
;
isc
::
data
::
ConstElementPtr
dhcp6
;
isc
::
data
::
ConstElementPtr
logger
;
isc
::
data
::
ConstElementPtr
result
;
// Basic sanity check: file name must not be empty.
...
...
@@ -67,6 +68,22 @@ void configure(const std::string& file_name) {
+
file_name
);
}
// Let's configure logging before applying the configuration,
// so we can log things during configuration process.
logger
=
json
->
get
(
"Logging"
);
if
(
logger
)
{
// Configure logger first, so it can be applied to DHCPv6
// configuration. If we don't have a logger, just pass
// empty configuration.
Daemon
::
configureLogger
(
logger
,
CfgMgr
::
instance
().
getConfiguration
());
}
else
{
// There was no Logging element defined in the config file.
// Let's pass an empty pointer that will remove any current
// configuration.
Daemon
::
configureLogger
(
isc
::
data
::
ConstElementPtr
(),
CfgMgr
::
instance
().
getConfiguration
());
}
// Get Dhcp6 component from the config
dhcp6
=
json
->
get
(
"Dhcp6"
);
...
...
src/lib/dhcpsrv/Makefile.am
View file @
4af6fc12
...
...
@@ -59,6 +59,8 @@ libkea_dhcpsrv_la_SOURCES += key_from_key.h
libkea_dhcpsrv_la_SOURCES
+=
lease.cc lease.h
libkea_dhcpsrv_la_SOURCES
+=
lease_mgr.cc lease_mgr.h
libkea_dhcpsrv_la_SOURCES
+=
lease_mgr_factory.cc lease_mgr_factory.h
libkea_dhcpsrv_la_SOURCES
+=
logging.cc logging.h
libkea_dhcpsrv_la_SOURCES
+=
configuration.h
libkea_dhcpsrv_la_SOURCES
+=
memfile_lease_mgr.cc memfile_lease_mgr.h
if
HAVE_MYSQL
...
...
src/lib/dhcpsrv/cfgmgr.cc
View file @
4af6fc12
...
...
@@ -437,10 +437,15 @@ CfgMgr::getD2ClientMgr() {
return
(
d2_client_mgr_
);
}
ConfigurationPtr
CfgMgr
::
getConfiguration
()
{
return
(
configuration_
);
}
CfgMgr
::
CfgMgr
()
:
datadir_
(
DHCP_DATA_DIR
),
all_ifaces_active_
(
false
),
echo_v4_client_id_
(
true
),
d2_client_mgr_
()
{
d2_client_mgr_
()
,
configuration_
(
new
Configuration
())
{
// DHCP_DATA_DIR must be set set with -DDHCP_DATA_DIR="..." in Makefile.am
// Note: the definition of DHCP_DATA_DIR needs to include quotation marks
// See AM_CPPFLAGS definition in Makefile.am
...
...
src/lib/dhcpsrv/cfgmgr.h
View file @
4af6fc12
...
...
@@ -24,6 +24,7 @@
#include
<dhcpsrv/option_space_container.h>
#include
<dhcpsrv/pool.h>
#include
<dhcpsrv/subnet.h>
#include
<dhcpsrv/configuration.h>
#include
<util/buffer.h>
#include
<boost/shared_ptr.hpp>
...
...
@@ -420,6 +421,12 @@ public:
/// @return a reference to the DHCP-DDNS manager.
D2ClientMgr
&
getD2ClientMgr
();
/// @brief Returns the current configuration.
///
/// @return a pointer to the current configuration.
ConfigurationPtr
getConfiguration
();
protected:
/// @brief Protected constructor.
...
...
@@ -516,6 +523,14 @@ private:
/// @brief Manages the DHCP-DDNS client and its configuration.
D2ClientMgr
d2_client_mgr_
;
/// @brief Configuration
///
/// This is a structure that will hold all configuration.
/// @todo: migrate all other parameters to that structure.
/// @todo: maybe this should be a vector<Configuration>, so we could keep
/// previous configurations and do a rollback if needed?
ConfigurationPtr
configuration_
;
};
}
// namespace isc::dhcp
...
...
src/lib/dhcpsrv/configuration.h
0 → 100644
View file @
4af6fc12
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef DHCPSRV_CONFIG_H
#define DHCPSRV_CONFIG_H
#include
<log/logger_level.h>
#include
<boost/shared_ptr.hpp>
namespace
isc
{
namespace
dhcp
{
/// @brief Defines single logging destination
///
/// This structure is used to keep log4cplus configuration parameters.
struct
LoggingDestination
{
/// @brief defines logging destination output
///
/// Values accepted are: stdout, stderr, syslog, syslog:name.
/// Any other destination will be considered a file name.
std
::
string
output_
;
/// @brief Maximum number of log files in rotation
int
maxver_
;
/// @brief Maximum log file size
uint64_t
maxsize_
;
};
/// @brief structure that describes one logging entry
///
/// This is a structure that conveys one logger entry configuration.
/// The structure in JSON form has the following syntax:
/// {
/// "name": "*",
/// "output_options": [
/// {
/// "output": "/path/to/the/logfile.log",
/// "maxver": 8,
/// "maxsize": 204800
/// }
/// ],
/// "severity": "WARN",
/// "debuglevel": 99
/// },
struct
LoggingInfo
{
/// @brief logging name
std
::
string
name_
;
/// @brief describes logging severity
isc
::
log
::
Severity
severity_
;
/// @brief debuglevel (used when severity_ == DEBUG)
///
/// We use range 0(least verbose)..99(most verbose)
int
debuglevel_
;
/// @brief specific logging destinations
std
::
vector
<
LoggingDestination
>
destinations_
;
};
/// @brief storage for logging information in log4cplus format
typedef
std
::
vector
<
isc
::
dhcp
::
LoggingInfo
>
LoggingInfoStorage
;
/// @brief Specifies current DHCP configuration
///
/// @todo Migrate all other configuration parameters from cfgmgr.h here
struct
Configuration
{
/// @brief logging specific information
LoggingInfoStorage
logging_info_
;
};
/// @brief pointer to the configuration
typedef
boost
::
shared_ptr
<
Configuration
>
ConfigurationPtr
;
}
// namespace isc::dhcp
}
// namespace isc
#endif
src/lib/dhcpsrv/daemon.cc
View file @
4af6fc12
...
...
@@ -15,11 +15,13 @@
#include
<config.h>
#include
<dhcpsrv/daemon.h>
#include
<exceptions/exceptions.h>
#include
<cc/data.h>
#include
<boost/bind.hpp>
#include
<logging.h>
#include
<errno.h>
/// @brief provides default implementation for basic daemon operations
///
///
/// This file provides stub implementations that are expected to be redefined
/// in derived classes (e.g. ControlledDhcpv6Srv)
namespace
isc
{
...
...
@@ -53,6 +55,41 @@ void Daemon::handleSignal() {
}
}
void
Daemon
::
configureLogger
(
isc
::
data
::
ConstElementPtr
log_config
,
const
ConfigurationPtr
&
storage
)
{
// This is utility class that translates JSON structures into formats
// understandable by log4cplus.
LogConfigParser
parser
(
storage
);
if
(
!
log_config
)
{
// There was no logger configuration. Let's clear any config
// and revert to the default.
parser
.
defaultLogging
();
// Set up default logging
return
;
}
isc
::
data
::
ConstElementPtr
loggers
;
loggers
=
log_config
->
get
(
"loggers"
);
if
(
!
loggers
)
{
// There is Logging structure, but it doesn't have loggers
// array in it. Let's clear any old logging configuration
// we may have and revert to the default.
parser
.
defaultLogging
();
// Set up default logging
return
;
}
// Translate JSON structures into log4cplus formats
parser
.
parseConfiguration
(
loggers
);
// Apply the configuration
/// @todo: Once configuration unrolling is implemented,
/// this call will be moved to a separate method.
parser
.
applyConfiguration
();
}
};
};
src/lib/dhcpsrv/daemon.h
View file @
4af6fc12
...
...
@@ -12,12 +12,16 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef DAEMON_H
#define DAEMON_H
#include
<config.h>
#include
<cc/data.h>
#include
<dhcpsrv/configuration.h>
#include
<util/signal_set.h>
#include
<boost/noncopyable.hpp>
#include
<string>
namespace
isc
{
namespace
dhcp
{
...
...
@@ -105,7 +109,7 @@ public:
return
(
config_file_
);
}
/// Initializes logger
///
@brief
Initializes logger
///
/// This method initializes logger. Currently its implementation is specific
/// to each configuration backend.
...
...
@@ -114,6 +118,19 @@ public:
/// @param verbose verbose mode (true usually enables DEBUG messages)
static
void
loggerInit
(
const
char
*
log_name
,
bool
verbose
);
/// @brief Configures logger
///
/// Applies configuration stored in "Logging" structure in the
/// configuration file. This structure has a "loggers" array that
/// contains 0 or more entries, each configuring one logging source
/// (name, severity, debuglevel), each with zero or more outputs (file,
/// maxsize, maximum number of files).
///
/// @param log_config JSON structures that describe logging
/// @param storage configuration will be stored here
static
void
configureLogger
(
isc
::
data
::
ConstElementPtr
log_config
,
const
isc
::
dhcp
::
ConfigurationPtr
&
storage
);
protected:
/// @brief Invokes handler for the next received signal.
...
...
@@ -150,3 +167,5 @@ private:
};
// end of isc::dhcp namespace
};
// end of isc namespace
#endif
src/lib/dhcpsrv/logging.cc
0 → 100644
View file @
4af6fc12
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include
<cc/data.h>
#include
<dhcpsrv/logging.h>
#include
<boost/foreach.hpp>
#include
<boost/lexical_cast.hpp>
#include
<log/logger_specification.h>
#include
<log/logger_manager.h>
using
namespace
isc
::
data
;
using
namespace
isc
::
log
;
namespace
isc
{
namespace
dhcp
{
static
const
char
*
DEFAULT_SYSLOG_NAME
=
"kea"
;
LogConfigParser
::
LogConfigParser
(
const
ConfigurationPtr
&
storage
)
:
config_
(
storage
)
{
if
(
!
storage
)
{
isc_throw
(
InvalidOperation
,
"LogConfigParser needs a pointer to the "
"configuration, so parsed data can be stored there"
);
}
}
void
LogConfigParser
::
parseConfiguration
(
isc
::
data
::
ConstElementPtr
loggers
)
{
// Iterate over all entries in "Logging/loggers" list
BOOST_FOREACH
(
ConstElementPtr
logger
,
loggers
->
listValue
())
{
parseConfigEntry
(
logger
);
}
}
void
LogConfigParser
::
parseConfigEntry
(
isc
::
data
::
ConstElementPtr
entry
)
{
if
(
!
entry
)
{
// This should not happen, but let's be on the safe side and check
return
;
}
if
(
!
config_
)
{
isc_throw
(
BadValue
,
"configuration storage not set, can't parse logger config."
);
}
LoggingInfo
info
;
// Get a name
isc
::
data
::
ConstElementPtr
name_ptr
=
entry
->
get
(
"name"
);
if
(
!
name_ptr
)
{
isc_throw
(
BadValue
,
"loggers entry does not have a mandatory 'name' "
"element ("
<<
entry
->
getPosition
()
<<
")"
);
}
info
.
name_
=
name_ptr
->
stringValue
();
// Get severity
isc
::
data
::
ConstElementPtr
severity_ptr
=
entry
->
get
(
"severity"
);
if
(
!
name_ptr
)
{
isc_throw
(
BadValue
,
"loggers entry does not have a mandatory "
"'severity' element ("
<<
entry
->
getPosition
()
<<
")"
);
}
try
{
info
.
severity_
=
isc
::
log
::
getSeverity
(
severity_ptr
->
stringValue
().
c_str
());
}
catch
(
const
std
::
exception
&
ex
)
{
isc_throw
(
BadValue
,
"Unable to convert '"
<<
severity_ptr
->
stringValue
()
<<
"' into allowed severity ("
<<
severity_ptr
->
getPosition
()
<<
")"
);
}
// Get debug logging level
info
.
debuglevel_
=
0
;
isc
::
data
::
ConstElementPtr
debuglevel_ptr
=
entry
->
get
(
"debuglevel"
);
// It's ok to not have debuglevel, we'll just assume its least verbose
// (0) level.
if
(
debuglevel_ptr
)
{
try
{
info
.
debuglevel_
=
boost
::
lexical_cast
<
int
>
(
debuglevel_ptr
->
str
());
if
(
(
info
.
debuglevel_
<
0
)
||
(
info
.
debuglevel_
>
99
)
)
{
// Comment doesn't matter, it is caught several lines below
isc_throw
(
BadValue
,
""
);
}
}
catch
(...)
{
isc_throw
(
BadValue
,
"Unable to convert '"
<<
debuglevel_ptr
->
stringValue
()
<<
"' into allowed debuglevel range (0-99) ("
<<
debuglevel_ptr
->
getPosition
()
<<
")"
);
}
}
isc
::
data
::
ConstElementPtr
output_options
=
entry
->
get
(
"output_options"
);
if
(
output_options
)
{
parseOutputOptions
(
info
.
destinations_
,
output_options
);
}
config_
->
logging_info_
.
push_back
(
info
);
}
void
LogConfigParser
::
parseOutputOptions
(
std
::
vector
<
LoggingDestination
>&
destination
,
isc
::
data
::
ConstElementPtr
output_options
)
{
if
(
!
output_options
)
{
isc_throw
(
BadValue
,
"Missing 'output_options' structure in 'loggers'"
);
}
BOOST_FOREACH
(
ConstElementPtr
output_option
,
output_options
->
listValue
())
{
LoggingDestination
dest
;
isc
::
data
::
ConstElementPtr
output
=
output_option
->
get
(
"output"
);
if
(
!
output
)
{
isc_throw
(
BadValue
,
"output_options entry does not have a mandatory 'output' "
"element ("
<<
output_option
->
getPosition
()
<<
")"
);
}
dest
.
output_
=
output
->
stringValue
();
isc
::
data
::
ConstElementPtr
maxver_ptr
=
output_option
->
get
(
"maxver"
);
if
(
maxver_ptr
)
{
dest
.
maxver_
=
boost
::
lexical_cast
<
int
>
(
maxver_ptr
->
str
());
}
isc
::
data
::
ConstElementPtr
maxsize_ptr
=
output_option
->
get
(
"maxsize"
);
if
(
maxsize_ptr
)
{
dest
.
maxsize_
=
boost
::
lexical_cast
<
uint64_t
>
(
maxsize_ptr
->
str
());
}
destination
.
push_back
(
dest
);
}
}
void
LogConfigParser
::
applyConfiguration
()
{
// Constants: not declared static as this is function is expected to be
// called once only
static
const
std
::
string
STDOUT
=
"stdout"
;
static
const
std
::
string
STDERR
=
"stderr"
;
static
const
std
::
string
SYSLOG
=
"syslog"
;
static
const
std
::
string
SYSLOG_COLON
=
"syslog:"
;
// Set locking directory to /tmp
setenv
(
"B10_LOCKFILE_DIR_FROM_BUILD"
,
"/tmp"
,
1
);
// Now iterate through all specified loggers
for
(
LoggingInfoStorage
::
const_iterator
it
=
config_
->
logging_info_
.
begin
();
it
!=
config_
->
logging_info_
.
end
();
++
it
)
{
// Prepare the objects to define the logging specification
LoggerSpecification
spec
(
it
->
name_
,
it
->
severity_
,
it
->
debuglevel_
);
OutputOption
option
;
for
(
std
::
vector
<
LoggingDestination
>::
const_iterator
dest
=
it
->
destinations_
.
begin
();
dest
!=
it
->
destinations_
.
end
();
++
dest
)
{
// Set up output option according to destination specification
if
(
dest
->
output_
==
STDOUT
)
{
option
.
destination
=
OutputOption
::
DEST_CONSOLE
;
option
.
stream
=
OutputOption
::
STR_STDOUT
;
}
else
if
(
dest
->
output_
==
STDERR
)
{
option
.
destination
=
OutputOption
::
DEST_CONSOLE
;
option
.
stream
=
OutputOption
::
STR_STDERR
;
}
else
if
(
dest
->
output_
==
SYSLOG
)
{
option
.
destination
=
OutputOption
::
DEST_SYSLOG
;
// Use default specified in OutputOption constructor for the
// syslog destination
}
else
if
(
dest
->
output_
.
find
(
SYSLOG_COLON
)
==
0
)
{
option
.
destination
=
OutputOption
::
DEST_SYSLOG
;
// Must take account of the string actually being "syslog:"
if
(
dest
->
output_
==
SYSLOG_COLON
)
{
// The expected syntax is syslog:facility. User skipped
// the logging name, so we'll just use DEFAULT_SYSLOG_NAME.
option
.
facility
=
DEFAULT_SYSLOG_NAME
;
}
else
{
// Everything else in the string is the facility name
option
.
facility
=
dest
->
output_
.
substr
(
SYSLOG_COLON
.
size
());
}
}
else
{
// Not a recognised destination, assume a file.
option
.
destination
=
OutputOption
::
DEST_FILE
;
option
.
filename
=
dest
->
output_
;
}
// ... and set the destination
spec
.
addOutputOption
(
option
);
}
LoggerManager
manager
;
manager
.
process
(
spec
);
}
}
void
LogConfigParser
::
defaultLogging
()
{
LoggerSpecification
spec
(
"kea"
,
isc
::
log
::
INFO
,
0
);
OutputOption
option
;
option
.
destination
=
OutputOption
::
DEST_CONSOLE
;
option
.
stream
=
OutputOption
::
STR_STDOUT
;
spec
.
addOutputOption
(
option
);
LoggerManager
manager
;
manager
.
process
(
spec
);
}
}
// namespace isc::dhcp
}
// namespace isc
src/lib/dhcpsrv/logging.h
0 → 100644
View file @
4af6fc12
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef DHCPSRV_LOGGING_H
#define DHCPSRV_LOGGING_H
#include
<cc/data.h>
#include
<dhcpsrv/configuration.h>
#include
<dhcpsrv/cfgmgr.h>
#include
<stdint.h>
#include
<vector>
namespace
isc
{
namespace
dhcp
{
/// @brief Interprets JSON structures and translates them to log4cplus
///
/// This parser iterates over provided JSON structures and translates them
/// into values applicable to log4cplus.