MXS-421 Add maxscale::event concept
MaxScale now defines events for which the syslog facility and level can explicitly be defined by the administrator. Currently there is only one such event, namelt AUTHENTICATION_FAILURE. In a subsequent commit, config.cc will be modified so that event-related configuration parameters are passed to event::configure() and in another subsequent commit the authenticators will be modifed to use this mechanism. In practice a line like: MXS_WARNING("%s: login attempt for user '%s'@[%s]:%s, " "authentication failed.", dcb->service->name, client_data->user, dcb->remote, dcb->path); will be changed to MXS_LOG_EVENT(event::AUTHENTICATION_FAILURE, "%s: login attempt for user '%s'@[%s]:%s, " "authentication failed.", dcb->service->name, client_data->user, dcb->remote, dcb->path);
This commit is contained in:
parent
2f987d0b10
commit
4c1b7f761c
174
include/maxscale/event.hh
Normal file
174
include/maxscale/event.hh
Normal file
@ -0,0 +1,174 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2020-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
#include <syslog.h>
|
||||
#include <string>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Convert a syslog level into a string
|
||||
*
|
||||
* @param level One of LOG_WARNING, LOG_ERR, ...
|
||||
*
|
||||
* @return The corresponding string; "LOG_WARNING", "LOG_ERR", ...
|
||||
*/
|
||||
const char* log_level_to_string(int32_t level);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a syslog level
|
||||
*
|
||||
* @param pLevel [out] A syslog level.
|
||||
* @param zValue A syslog value as string; "LOG_WARNING", "LOG_ERR", ...
|
||||
*
|
||||
* @return True, if the string corresponds to a syslog level, false otherwise.
|
||||
*/
|
||||
bool log_level_from_string(int32_t* pLevel, const char* zValue);
|
||||
|
||||
/**
|
||||
* @brief Convert a syslog facility into a string
|
||||
*
|
||||
* @param level One of LOG_USER, LOG_LOCAL0, ...
|
||||
*
|
||||
* @return The corresponding string; "LOG_USER", "LOG_LOCAL0", ...
|
||||
*/
|
||||
const char* log_facility_to_string(int32_t facility);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a syslog facility
|
||||
*
|
||||
* @param pFacility [out] A syslog facility.
|
||||
* @param zValue A syslog facility as string; "LOG_USER", "LOG_LOCAL0", ...
|
||||
*
|
||||
* @return True, if the string corresponds to a syslog facility, false otherwise.
|
||||
*/
|
||||
bool log_facility_from_string(int32_t* pFacility, const char* zValue);
|
||||
|
||||
namespace event
|
||||
{
|
||||
|
||||
enum id_t
|
||||
{
|
||||
AUTHENTICATION_FAILURE /**< Authentication failure */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_FACILITY = LOG_USER,
|
||||
DEFAULT_LEVEL = LOG_WARNING
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Convert an event id to a string.
|
||||
*
|
||||
* The string corresponding to an event id is the symbolic constant
|
||||
* converted to all lower-case.
|
||||
*
|
||||
* @param id An event id.
|
||||
*
|
||||
* @return The corresponding string.
|
||||
*/
|
||||
const char* to_string(id_t id);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to an event id
|
||||
*
|
||||
* @param pId [out] An event id.
|
||||
* @param zValue An event id a string; "authentication_failure", ...
|
||||
*
|
||||
* @return True, if the string could be converted, false otherwise.
|
||||
*/
|
||||
bool from_string(id_t* pId, const char* zValue);
|
||||
bool from_string(id_t* pId, const std::string& value)
|
||||
{
|
||||
return from_string(pId, value.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the syslog facility of an event.
|
||||
*
|
||||
* @param id The id of the event.
|
||||
* @param facility One of LOG_USER, LOG_LOCAL0, ...
|
||||
*
|
||||
* @note If @c facility contains other bits than facility bits, they
|
||||
* will silently be ignored.
|
||||
*/
|
||||
void set_log_facility(id_t id, int32_t facility);
|
||||
|
||||
/**
|
||||
* @brief Get the syslog facility of an event.
|
||||
*
|
||||
* @param id An event id.
|
||||
*
|
||||
* @return The facility of the event.
|
||||
*/
|
||||
int32_t get_log_facility(id_t id);
|
||||
|
||||
/**
|
||||
* @brief Set the syslog level of an event.
|
||||
*
|
||||
* @param id The id of the event.
|
||||
* @param level One of LOG_WARNING, LOG_ERR, ...
|
||||
*
|
||||
* @note If @c level contains other bits than level bits, they
|
||||
* will silently be ignored.
|
||||
*/
|
||||
void set_log_level(id_t id, int32_t level);
|
||||
|
||||
/**
|
||||
* @brief Get the syslog level of an event.
|
||||
*
|
||||
* @param id An event id.
|
||||
*
|
||||
* @return The level of the event.
|
||||
*/
|
||||
int32_t get_log_level(id_t id);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Log an event.
|
||||
*
|
||||
* Usually this function should not be used, but the macro
|
||||
* @c MXS_LOG_EVENT should be used in its stead.
|
||||
*
|
||||
* @param event_id The id of the event.
|
||||
* @param modname The module where the event is logged.
|
||||
* @param file The file where the event is logged.
|
||||
* @param line The line where the event is logged.
|
||||
* @param function The function where the event is logged.
|
||||
* @param format Printf formatting string.
|
||||
* @param ... Formatting string specific additional arguments.
|
||||
*
|
||||
*/
|
||||
void log(id_t event_id,
|
||||
const char* modname,
|
||||
const char* file, int line, const char* function,
|
||||
const char* format, ...) mxs_attribute((format(printf, 6, 7)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log an event.
|
||||
*
|
||||
* @param event_id The id of the event.
|
||||
* @param format Printf formatting string.
|
||||
* @param ... Formatting string specific additional arguments.
|
||||
*
|
||||
*/
|
||||
#define MXS_LOG_EVENT(event_id, format, ...)\
|
||||
maxscale::event::log(event_id, MXS_MODULE_NAME, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
|
@ -10,6 +10,7 @@ add_library(maxscale-common SHARED
|
||||
config_runtime.cc
|
||||
dcb.cc
|
||||
encryption.cc
|
||||
event.cc
|
||||
externcmd.cc
|
||||
filter.cc
|
||||
hashtable.cc
|
||||
|
479
server/core/event.cc
Normal file
479
server/core/event.cc
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2020-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include "internal/event.hh"
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <maxscale/atomic.h>
|
||||
#include <maxscale/debug.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace maxscale;
|
||||
|
||||
const char CN_UNKNOWN[] = "Unknown";
|
||||
|
||||
const char CN_FACILITY[] = "facility";
|
||||
const char CN_LEVEL[] = "level";
|
||||
|
||||
const char CN_AUTHENTICATION_FAILURE[] = "authentication_failure";
|
||||
|
||||
const char EVENT_PREFIX[] = "event.";
|
||||
|
||||
|
||||
struct NAME_AND_VALUE
|
||||
{
|
||||
const char* zName;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
int name_and_value_compare(const void* pLeft, const void* pRight)
|
||||
{
|
||||
const NAME_AND_VALUE* pL = static_cast<const NAME_AND_VALUE*>(pLeft);
|
||||
const NAME_AND_VALUE* pR = static_cast<const NAME_AND_VALUE*>(pRight);
|
||||
|
||||
return strcmp(pL->zName, pR->zName);
|
||||
}
|
||||
|
||||
|
||||
// Keep these in alphabetical order.
|
||||
const NAME_AND_VALUE levels[] =
|
||||
{
|
||||
{
|
||||
"LOG_ALERT",
|
||||
LOG_ALERT,
|
||||
},
|
||||
{
|
||||
"LOG_CRIT",
|
||||
LOG_CRIT,
|
||||
},
|
||||
{
|
||||
"LOG_DEBUG",
|
||||
LOG_DEBUG,
|
||||
},
|
||||
{
|
||||
"LOG_EMER",
|
||||
LOG_EMERG,
|
||||
},
|
||||
{
|
||||
"LOG_ERR",
|
||||
LOG_ERR,
|
||||
},
|
||||
{
|
||||
"LOG_INFO",
|
||||
LOG_INFO,
|
||||
},
|
||||
{
|
||||
"LOG_NOTICE",
|
||||
LOG_NOTICE,
|
||||
},
|
||||
{
|
||||
"LOG_WARNING",
|
||||
LOG_WARNING,
|
||||
},
|
||||
};
|
||||
|
||||
const int N_LEVELS = sizeof(levels) / sizeof(levels[0]);
|
||||
|
||||
|
||||
// Keep these in alphabetical order.
|
||||
const NAME_AND_VALUE facilities[] =
|
||||
{
|
||||
{
|
||||
"LOG_AUTH",
|
||||
LOG_AUTH
|
||||
},
|
||||
{
|
||||
"LOG_AUTHPRIV",
|
||||
LOG_AUTHPRIV
|
||||
},
|
||||
{
|
||||
"LOG_CRON",
|
||||
LOG_CRON
|
||||
},
|
||||
{
|
||||
"LOG_DAEMON",
|
||||
LOG_DAEMON
|
||||
},
|
||||
{
|
||||
"LOG_FTP",
|
||||
LOG_FTP
|
||||
},
|
||||
{
|
||||
"LOG_KERN",
|
||||
LOG_KERN
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL0",
|
||||
LOG_LOCAL0
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL1",
|
||||
LOG_LOCAL1
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL2",
|
||||
LOG_LOCAL2
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL3",
|
||||
LOG_LOCAL3
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL4",
|
||||
LOG_LOCAL4
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL5",
|
||||
LOG_LOCAL5
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL6",
|
||||
LOG_LOCAL6
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL7",
|
||||
LOG_LOCAL0
|
||||
},
|
||||
{
|
||||
"LOG_LPR",
|
||||
LOG_LPR
|
||||
},
|
||||
{
|
||||
"LOG_MAIL",
|
||||
LOG_MAIL
|
||||
},
|
||||
{
|
||||
"LOG_NEWS",
|
||||
LOG_NEWS
|
||||
},
|
||||
{
|
||||
"LOG_SYSLOG",
|
||||
LOG_SYSLOG
|
||||
},
|
||||
{
|
||||
"LOG_USER",
|
||||
LOG_USER
|
||||
},
|
||||
{
|
||||
"LOG_UUCP",
|
||||
LOG_UUCP
|
||||
},
|
||||
};
|
||||
|
||||
const int N_FACILITIES = sizeof(facilities) / sizeof(facilities[0]);
|
||||
|
||||
|
||||
struct EVENT
|
||||
{
|
||||
const char* zName;
|
||||
event::id_t id;
|
||||
int32_t facility;
|
||||
int32_t level;
|
||||
};
|
||||
|
||||
// Keep these in alphabetical order.
|
||||
EVENT events[] =
|
||||
{
|
||||
{
|
||||
CN_AUTHENTICATION_FAILURE,
|
||||
event::AUTHENTICATION_FAILURE,
|
||||
event::DEFAULT_FACILITY,
|
||||
event::DEFAULT_LEVEL
|
||||
}
|
||||
};
|
||||
|
||||
const int N_EVENTS = sizeof(events) / sizeof(events[0]);
|
||||
|
||||
int event_compare(const void* pLeft, const void* pRight)
|
||||
{
|
||||
const EVENT* pL = static_cast<const EVENT*>(pLeft);
|
||||
const EVENT* pR = static_cast<const EVENT*>(pRight);
|
||||
|
||||
return strcmp(pL->zName, pR->zName);
|
||||
}
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
EVENT* events;
|
||||
const NAME_AND_VALUE* levels;
|
||||
const NAME_AND_VALUE* facilities;
|
||||
} this_unit =
|
||||
{
|
||||
events,
|
||||
levels,
|
||||
facilities
|
||||
};
|
||||
|
||||
event::result_t configure_facility(event::id_t id, const char* zValue)
|
||||
{
|
||||
event::result_t rv = event::INVALID;
|
||||
|
||||
int32_t facility;
|
||||
if (log_facility_from_string(&facility, zValue))
|
||||
{
|
||||
event::set_log_facility(id, facility);
|
||||
rv = event::ACCEPTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("%s is not a valid facility.", zValue);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
event::result_t configure_level(event::id_t id, const char* zValue)
|
||||
{
|
||||
event::result_t rv = event::INVALID;
|
||||
|
||||
int32_t level;
|
||||
if (log_level_from_string(&level, zValue))
|
||||
{
|
||||
event::set_log_level(id, level);
|
||||
rv = event::ACCEPTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("%s is not a valid level.", zValue);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
const char* log_level_to_string(int32_t level)
|
||||
{
|
||||
auto begin = this_unit.levels;
|
||||
auto end = begin + N_LEVELS;
|
||||
|
||||
auto i = find_if(begin, end, [level](const NAME_AND_VALUE& item) -> bool
|
||||
{
|
||||
return item.value == level;
|
||||
});
|
||||
|
||||
return i == end ? CN_UNKNOWN : i->zName;
|
||||
}
|
||||
|
||||
bool log_level_from_string(int32_t* pLevel, const char* zValue)
|
||||
{
|
||||
NAME_AND_VALUE key = { zValue };
|
||||
void* pResult = bsearch(&key, this_unit.levels, N_LEVELS, sizeof(NAME_AND_VALUE),
|
||||
name_and_value_compare);
|
||||
|
||||
if (pResult)
|
||||
{
|
||||
const NAME_AND_VALUE* pItem = static_cast<const NAME_AND_VALUE*>(pResult);
|
||||
|
||||
*pLevel = pItem->value;
|
||||
}
|
||||
|
||||
return pResult != nullptr;
|
||||
}
|
||||
|
||||
const char* log_facility_to_string(int32_t facility)
|
||||
{
|
||||
auto begin = this_unit.facilities;
|
||||
auto end = begin + N_FACILITIES;
|
||||
|
||||
auto i = find_if(begin, end, [facility](const NAME_AND_VALUE& item) -> bool
|
||||
{
|
||||
return item.value == facility;
|
||||
});
|
||||
|
||||
return i == end ? CN_UNKNOWN : i->zName;
|
||||
}
|
||||
|
||||
bool log_facility_from_string(int32_t* pFacility, const char* zValue)
|
||||
{
|
||||
NAME_AND_VALUE key = { zValue };
|
||||
void* pResult = bsearch(&key, this_unit.facilities, N_FACILITIES, sizeof(NAME_AND_VALUE),
|
||||
name_and_value_compare);
|
||||
|
||||
if (pResult)
|
||||
{
|
||||
const NAME_AND_VALUE* pItem = static_cast<const NAME_AND_VALUE*>(pResult);
|
||||
|
||||
*pFacility = pItem->value;
|
||||
}
|
||||
|
||||
return pResult != nullptr;
|
||||
}
|
||||
|
||||
|
||||
namespace event
|
||||
{
|
||||
|
||||
const char* to_string(id_t id)
|
||||
{
|
||||
auto begin = this_unit.events;
|
||||
auto end = begin + N_EVENTS;
|
||||
|
||||
auto i = find_if(begin, end, [id](const EVENT& item) -> bool
|
||||
{
|
||||
return item.id == id;
|
||||
});
|
||||
|
||||
return i == end ? CN_UNKNOWN : i->zName;
|
||||
}
|
||||
|
||||
bool from_string(id_t* pId, const char* zValue)
|
||||
{
|
||||
EVENT key = { zValue };
|
||||
void* pResult = bsearch(&key, this_unit.events, N_EVENTS, sizeof(EVENT),
|
||||
event_compare);
|
||||
|
||||
if (pResult)
|
||||
{
|
||||
const EVENT* pItem = static_cast<const EVENT*>(pResult);
|
||||
|
||||
*pId = pItem->id;
|
||||
}
|
||||
|
||||
return pResult != nullptr;
|
||||
}
|
||||
|
||||
void set_log_facility(id_t id, int32_t facility)
|
||||
{
|
||||
bool rv = false;
|
||||
ss_dassert((id >= 0) && (id < N_EVENTS));
|
||||
|
||||
// We silently strip away other than the relevant bits.
|
||||
facility = facility & LOG_FACMASK;
|
||||
|
||||
EVENT& event = this_unit.events[id];
|
||||
|
||||
atomic_store_int32(&event.facility, facility);
|
||||
}
|
||||
|
||||
int32_t get_log_facility(id_t id)
|
||||
{
|
||||
ss_dassert((id >= 0) && (id < N_EVENTS));
|
||||
|
||||
const EVENT& event = this_unit.events[id];
|
||||
|
||||
return atomic_load_int32(&event.facility);
|
||||
}
|
||||
|
||||
void set_log_level(id_t id, int32_t level)
|
||||
{
|
||||
ss_dassert((id >= 0) && (id < N_EVENTS));
|
||||
|
||||
// We silently strip away other than the relevant bits.
|
||||
level = level & LOG_PRIMASK;
|
||||
|
||||
EVENT& event = this_unit.events[id];
|
||||
|
||||
atomic_store_int32(&event.level, level);
|
||||
}
|
||||
|
||||
int32_t get_log_level(id_t id)
|
||||
{
|
||||
ss_dassert((id >= 0) && (id < N_EVENTS));
|
||||
|
||||
const EVENT& event = this_unit.events[id];
|
||||
|
||||
return atomic_load_int32(&event.level);
|
||||
}
|
||||
|
||||
result_t configure(const char* zName, const char* zValue)
|
||||
{
|
||||
result_t rv = IGNORED;
|
||||
|
||||
if (strncmp(zName, EVENT_PREFIX, sizeof(EVENT_PREFIX) - 1) == 0)
|
||||
{
|
||||
rv = INVALID;
|
||||
|
||||
string name(zName + sizeof(EVENT_PREFIX) - 1); // Character following '.'
|
||||
|
||||
auto i = name.find_first_of('.');
|
||||
|
||||
if (i != string::npos)
|
||||
{
|
||||
string event = name.substr(0, i);
|
||||
string property = name.substr(i + 1);
|
||||
|
||||
id_t id;
|
||||
if (from_string(&id, event.c_str()))
|
||||
{
|
||||
ss_dassert((id >= 0) && (id < N_EVENTS));
|
||||
|
||||
if (property == CN_FACILITY)
|
||||
{
|
||||
rv = configure_facility(id, zValue);
|
||||
}
|
||||
else if (property == CN_LEVEL)
|
||||
{
|
||||
rv = configure_level(id, zValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("%s is neither %s nor %s.", property.c_str(), CN_FACILITY, CN_LEVEL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("%s does not refer to a known event.", zValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("%s is not a valid event configuration.", zName);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void log(id_t event_id,
|
||||
const char* modname,
|
||||
const char* file, int line, const char* function,
|
||||
const char* format, ...)
|
||||
{
|
||||
va_list valist;
|
||||
|
||||
ss_dassert((event_id >= 0) && (event_id < N_EVENTS));
|
||||
|
||||
const EVENT& event = this_unit.events[event_id];
|
||||
|
||||
int priority = atomic_load_int32(&event.facility) | atomic_load_int32(&event.level);
|
||||
|
||||
va_start(valist, format);
|
||||
int len = vsnprintf(NULL, 0, format, valist);
|
||||
va_end(valist);
|
||||
|
||||
if (len > BUFSIZ)
|
||||
{
|
||||
len = BUFSIZ;
|
||||
}
|
||||
|
||||
char message[len + 1];
|
||||
|
||||
va_start(valist, format);
|
||||
vsnprintf(message, len + 1, format, valist);
|
||||
va_end(valist);
|
||||
|
||||
mxs_log_message(priority, modname, file, line, function, "%s", message);
|
||||
}
|
||||
|
||||
} // event
|
||||
|
||||
} // maxscale
|
46
server/core/internal/event.hh
Normal file
46
server/core/internal/event.hh
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2020-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
#include <maxscale/event.hh>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
namespace event
|
||||
{
|
||||
|
||||
enum result_t
|
||||
{
|
||||
IGNORED, /**< The configuration was ignored, it does not affect events. */
|
||||
INVALID, /**< The configuration was invalid. */
|
||||
ACCEPTED /**< The configuration was accepted. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configure an event
|
||||
*
|
||||
* @param zName A MaxScale event configuration item name,
|
||||
* such as "event.authentication_failure.facility"
|
||||
* @param zValue The value it should be set to, e.g. "LOG_ERROR".
|
||||
*
|
||||
* @return IGNORED, if @c zName does not start with "event.",
|
||||
* INVALID, if @c zName or @c zValue is invalid, and
|
||||
* ACCEPTED, if @c zName and @c zValue are valid.
|
||||
*/
|
||||
result_t configure(const char* zName, const char* zValue);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ add_executable(test_atomic test_atomic.cc)
|
||||
add_executable(test_buffer test_buffer.cc)
|
||||
add_executable(test_config test_config.cc)
|
||||
add_executable(test_dcb test_dcb.cc)
|
||||
add_executable(test_event test_event.cc)
|
||||
add_executable(test_filter test_filter.cc)
|
||||
add_executable(test_hash test_hash.cc)
|
||||
add_executable(test_hint test_hint.cc)
|
||||
@ -35,6 +36,7 @@ target_link_libraries(test_atomic maxscale-common)
|
||||
target_link_libraries(test_buffer maxscale-common)
|
||||
target_link_libraries(test_config maxscale-common)
|
||||
target_link_libraries(test_dcb maxscale-common)
|
||||
target_link_libraries(test_event maxscale-common)
|
||||
target_link_libraries(test_filter maxscale-common)
|
||||
target_link_libraries(test_hash maxscale-common)
|
||||
target_link_libraries(test_hint maxscale-common)
|
||||
@ -65,6 +67,7 @@ add_test(test_atomic test_atomic)
|
||||
add_test(test_buffer test_buffer)
|
||||
add_test(test_config test_config)
|
||||
add_test(test_dcb test_dcb)
|
||||
add_test(test_event test_event)
|
||||
add_test(test_filter test_filter)
|
||||
add_test(test_hash test_hash)
|
||||
add_test(test_hint test_hint)
|
||||
|
471
server/core/test/test_event.cc
Normal file
471
server/core/test/test_event.cc
Normal file
@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2020-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include "../internal/event.hh"
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <maxscale/debug.h>
|
||||
|
||||
using namespace maxscale;
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct NAME_AND_VALUE
|
||||
{
|
||||
const char* zName;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
const NAME_AND_VALUE levels[] =
|
||||
{
|
||||
{
|
||||
"LOG_ALERT",
|
||||
LOG_ALERT,
|
||||
},
|
||||
{
|
||||
"LOG_CRIT",
|
||||
LOG_CRIT,
|
||||
},
|
||||
{
|
||||
"LOG_DEBUG",
|
||||
LOG_DEBUG,
|
||||
},
|
||||
{
|
||||
"LOG_EMER",
|
||||
LOG_EMERG,
|
||||
},
|
||||
{
|
||||
"LOG_ERR",
|
||||
LOG_ERR,
|
||||
},
|
||||
{
|
||||
"LOG_INFO",
|
||||
LOG_INFO,
|
||||
},
|
||||
{
|
||||
"LOG_NOTICE",
|
||||
LOG_NOTICE,
|
||||
},
|
||||
{
|
||||
"LOG_WARNING",
|
||||
LOG_WARNING,
|
||||
},
|
||||
{
|
||||
"BLAH",
|
||||
-1
|
||||
}
|
||||
};
|
||||
|
||||
const int N_LEVELS = sizeof(levels) / sizeof(levels[0]);
|
||||
|
||||
// Keep these in alphabetical order.
|
||||
const NAME_AND_VALUE facilities[] =
|
||||
{
|
||||
{
|
||||
"LOG_AUTH",
|
||||
LOG_AUTH
|
||||
},
|
||||
{
|
||||
"LOG_AUTHPRIV",
|
||||
LOG_AUTHPRIV
|
||||
},
|
||||
{
|
||||
"LOG_CRON",
|
||||
LOG_CRON
|
||||
},
|
||||
{
|
||||
"LOG_DAEMON",
|
||||
LOG_DAEMON
|
||||
},
|
||||
{
|
||||
"LOG_FTP",
|
||||
LOG_FTP
|
||||
},
|
||||
{
|
||||
"LOG_KERN",
|
||||
LOG_KERN
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL0",
|
||||
LOG_LOCAL0
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL1",
|
||||
LOG_LOCAL1
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL2",
|
||||
LOG_LOCAL2
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL3",
|
||||
LOG_LOCAL3
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL4",
|
||||
LOG_LOCAL4
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL5",
|
||||
LOG_LOCAL5
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL6",
|
||||
LOG_LOCAL6
|
||||
},
|
||||
{
|
||||
"LOG_LOCAL7",
|
||||
LOG_LOCAL0
|
||||
},
|
||||
{
|
||||
"LOG_LPR",
|
||||
LOG_LPR
|
||||
},
|
||||
{
|
||||
"LOG_MAIL",
|
||||
LOG_MAIL
|
||||
},
|
||||
{
|
||||
"LOG_NEWS",
|
||||
LOG_NEWS
|
||||
},
|
||||
{
|
||||
"LOG_SYSLOG",
|
||||
LOG_SYSLOG
|
||||
},
|
||||
{
|
||||
"LOG_USER",
|
||||
LOG_USER
|
||||
},
|
||||
{
|
||||
"LOG_UUCP",
|
||||
LOG_UUCP
|
||||
},
|
||||
{
|
||||
"BLAH",
|
||||
-1
|
||||
}
|
||||
};
|
||||
|
||||
const int N_FACILITIES = sizeof(facilities) / sizeof(facilities[0]);
|
||||
|
||||
|
||||
template<class T>
|
||||
int test_names_and_values(const NAME_AND_VALUE* begin,
|
||||
const NAME_AND_VALUE* end,
|
||||
bool (*from_string)(T*, const char* zName),
|
||||
const char* (*to_string)(T),
|
||||
const char* zProperty)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
for_each(begin, end, [&errors, zProperty, from_string, to_string](const NAME_AND_VALUE& item)
|
||||
{
|
||||
T value;
|
||||
bool rv = from_string(&value, item.zName);
|
||||
|
||||
if (item.value != -1)
|
||||
{
|
||||
if (rv)
|
||||
{
|
||||
if (value != item.value)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Wrong " << zProperty << " was returned for "
|
||||
<< item.zName << ", " << item.value << " was expected, but "
|
||||
<< value << " was returned." << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: " << item.zName << " was not recognized as a syslog "
|
||||
<< zProperty << "." << endl;
|
||||
}
|
||||
|
||||
const char* zName = to_string(static_cast<T>(item.value));
|
||||
|
||||
if (strcmp(zName, item.zName) != 0)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Code " << item.value << " was converted to " << zName
|
||||
<< " although " << item.zName << " was expected." << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rv)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: " << item.zName << " was incorrectly recognized "
|
||||
<< "as a syslog " << zProperty << " salthough it should not "
|
||||
<< "have been." << endl;
|
||||
}
|
||||
|
||||
const char* zName = to_string(static_cast<T>(item.value));
|
||||
|
||||
if (strcmp(zName, "Unknown") != 0)
|
||||
{
|
||||
cerr << "error: Invalid code " << item.value << " was not converted "
|
||||
<< "to Unknown as expected but to " << zName << "." << endl;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int test_levels()
|
||||
{
|
||||
const NAME_AND_VALUE* begin = levels;
|
||||
const NAME_AND_VALUE* end = begin + N_LEVELS;
|
||||
|
||||
return test_names_and_values(begin, end, &log_level_from_string, &log_level_to_string, "level");
|
||||
}
|
||||
|
||||
int test_facilities()
|
||||
{
|
||||
const NAME_AND_VALUE* begin = facilities;
|
||||
const NAME_AND_VALUE* end = facilities + N_LEVELS;
|
||||
|
||||
return test_names_and_values(begin, end, &log_facility_from_string, &log_facility_to_string, "facility");
|
||||
}
|
||||
|
||||
|
||||
const NAME_AND_VALUE events[] =
|
||||
{
|
||||
{
|
||||
"authentication_failure",
|
||||
event::AUTHENTICATION_FAILURE
|
||||
}
|
||||
};
|
||||
|
||||
const int N_EVENTS = sizeof(events) / sizeof(events[0]);
|
||||
|
||||
int test_event_basics()
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
const NAME_AND_VALUE* begin = events;
|
||||
const NAME_AND_VALUE* end = events + N_EVENTS;
|
||||
|
||||
errors += test_names_and_values(begin, end, &event::from_string, &event::to_string, "event");
|
||||
|
||||
for_each(begin, end, [&errors](const NAME_AND_VALUE& item)
|
||||
{
|
||||
event::id_t id = static_cast<event::id_t>(item.value);
|
||||
|
||||
int32_t facility = event::get_log_facility(id);
|
||||
|
||||
if (facility != event::DEFAULT_FACILITY)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Default facility for " << event::to_string(id) << " was "
|
||||
<< log_facility_to_string(facility) << " and not "
|
||||
<< log_facility_to_string(event::DEFAULT_FACILITY)
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
event::set_log_facility(id, LOG_LOCAL0);
|
||||
|
||||
facility = event::get_log_facility(id);
|
||||
|
||||
if (facility != LOG_LOCAL0)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Set facility LOG_LOCAL0 as not stored, but was "
|
||||
<< log_facility_to_string(facility) << "." << endl;
|
||||
}
|
||||
|
||||
int32_t level = event::get_log_level(id);
|
||||
|
||||
if (level != event::DEFAULT_LEVEL)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Default level for " << event::to_string(id) << " was "
|
||||
<< log_level_to_string(level) << " and not "
|
||||
<< log_level_to_string(event::DEFAULT_LEVEL)
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
event::set_log_level(id, LOG_ALERT);
|
||||
|
||||
level = event::get_log_level(id);
|
||||
|
||||
if (level != LOG_ALERT)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Set level LOG_ALERT as not stored, but was "
|
||||
<< log_level_to_string(level) << "." << endl;
|
||||
}
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
enum class What
|
||||
{
|
||||
FACILITY,
|
||||
LEVEL,
|
||||
IRRELEVANT,
|
||||
};
|
||||
|
||||
struct CONFIGURATION
|
||||
{
|
||||
const char* zParameter;
|
||||
const char* zValue;
|
||||
event::id_t id;
|
||||
event::result_t result;
|
||||
What what;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
const CONFIGURATION configurations[] =
|
||||
{
|
||||
{
|
||||
"event.authentication_failure.facility",
|
||||
"LOG_LOCAL0",
|
||||
event::AUTHENTICATION_FAILURE,
|
||||
event::ACCEPTED,
|
||||
What::FACILITY,
|
||||
LOG_LOCAL0
|
||||
},
|
||||
{
|
||||
"event.authentication_failure.level",
|
||||
"LOG_ALERT",
|
||||
event::AUTHENTICATION_FAILURE,
|
||||
event::ACCEPTED,
|
||||
What::LEVEL,
|
||||
LOG_ALERT
|
||||
},
|
||||
{
|
||||
"event.authentication_failure.facility",
|
||||
"LOG_BLAH",
|
||||
event::AUTHENTICATION_FAILURE,
|
||||
event::INVALID,
|
||||
What::FACILITY,
|
||||
-1
|
||||
},
|
||||
{
|
||||
"event.authentication_failure.level",
|
||||
"LOG_BLAH",
|
||||
event::AUTHENTICATION_FAILURE,
|
||||
event::INVALID,
|
||||
What::LEVEL,
|
||||
-1
|
||||
},
|
||||
{
|
||||
"event.blah.facility",
|
||||
"LOG_LOCAL0",
|
||||
static_cast<event::id_t>(-1),
|
||||
event::INVALID,
|
||||
What::FACILITY,
|
||||
LOG_LOCAL0
|
||||
},
|
||||
{
|
||||
"blah",
|
||||
"LOG_LOCAL0",
|
||||
static_cast<event::id_t>(-1),
|
||||
event::IGNORED,
|
||||
What::IRRELEVANT,
|
||||
LOG_LOCAL0
|
||||
}
|
||||
};
|
||||
|
||||
const size_t N_CONFIGURATIONS = sizeof(configurations) / sizeof(configurations[0]);
|
||||
|
||||
int test_event_configuration()
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
const CONFIGURATION* begin = configurations;
|
||||
const CONFIGURATION* end = begin + N_CONFIGURATIONS;
|
||||
|
||||
for_each(begin, end, [&errors](const CONFIGURATION& c)
|
||||
{
|
||||
event::result_t result = event::configure(c.zParameter, c.zValue);
|
||||
|
||||
if (result == c.result)
|
||||
{
|
||||
if (result == event::ACCEPTED)
|
||||
{
|
||||
if (c.what == What::FACILITY)
|
||||
{
|
||||
int32_t facility = event::get_log_facility(c.id);
|
||||
|
||||
if (facility != c.value)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Configuration \""
|
||||
<< c.zParameter << "=" << c.zValue
|
||||
<< " did not affect the facility in the expected way."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ss_dassert(c.what == What::LEVEL);
|
||||
|
||||
int32_t level = event::get_log_level(c.id);
|
||||
|
||||
if (level != c.value)
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Configuration \""
|
||||
<< c.zParameter << "=" << c.zValue
|
||||
<< " did not affect the level in the expected way."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++errors;
|
||||
cerr << "error: Configuration \""
|
||||
<< c.zParameter << "=" << c.zValue
|
||||
<< " did not produce the expected result."
|
||||
<< endl;
|
||||
}
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int test_events()
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += test_event_basics();
|
||||
errors += test_event_configuration();
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += test_levels();
|
||||
errors += test_facilities();
|
||||
errors += test_events();
|
||||
|
||||
return errors;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user