mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
b69f270080
17
CHANGELOG
17
CHANGELOG
|
@ -1,6 +1,23 @@
|
|||
v1.4
|
||||
----
|
||||
|
||||
* renamed command-line option `--log.filter` to `--log.source-filter` to avoid
|
||||
misunderstandings
|
||||
|
||||
* introduced new command-line option `--log.content-filter` to optionally restrict
|
||||
logging to just specific log messages (containing the filter string, case-sensitive).
|
||||
|
||||
For example, to filter on just log entries which contain `ArangoDB`, use:
|
||||
|
||||
--log.content-filter "ArangoDB"
|
||||
|
||||
* added optional command-line option `--log.requests-file` to log incoming HTTP
|
||||
requests to a file.
|
||||
|
||||
When used, all HTTP requests will be logged to the specified file, containing the
|
||||
client IP address, HTTP method, requests URL, HTTP response code, and size of the
|
||||
response body.
|
||||
|
||||
* added a signal handler for SIGUSR1 signal:
|
||||
|
||||
when ArangoDB receives this signal, it will respond all further incoming requests
|
||||
|
|
|
@ -230,6 +230,10 @@ General Logging Options {#CommandLineLoggingGeneral}
|
|||
@anchor CommandLineLoggingLogFile
|
||||
@copydetails triagens::rest::ApplicationServer::_logFile
|
||||
|
||||
@CLEARPAGE
|
||||
@anchor CommandLineLoggingLogRequestsFile
|
||||
@copydetails triagens::rest::ApplicationServer::_logRequestsFile
|
||||
|
||||
@CLEARPAGE
|
||||
@anchor CommandLineLoggingLogSeverity
|
||||
@copydetails triagens::rest::ApplicationServer::_logSeverity
|
||||
|
@ -258,8 +262,12 @@ Human Readable Logging {#CommandLineLoggingHuman}
|
|||
@copydetails triagens::rest::ApplicationServer::_logThreadId
|
||||
|
||||
@CLEARPAGE
|
||||
@anchor CommandLineLoggingLogFilter
|
||||
@copydetails triagens::rest::ApplicationServer::_logFilter
|
||||
@anchor CommandLineLoggingLogSourceFilter
|
||||
@copydetails triagens::rest::ApplicationServer::_logSourceFilter
|
||||
|
||||
@CLEARPAGE
|
||||
@anchor CommandLineLoggingLogContentFilter
|
||||
@copydetails triagens::rest::ApplicationServer::_logContentFilter
|
||||
|
||||
@CLEARPAGE
|
||||
Machine Readable Logging {#CommandLineLoggingMachine}
|
||||
|
|
|
@ -41,6 +41,7 @@ TOC {#CommandLineTOC}
|
|||
- @ref CommandLineLogging
|
||||
- @ref CommandLineLoggingGeneral
|
||||
- @ref CommandLineLoggingLogFile "log.file"
|
||||
- @ref CommandLineLoggingLogRequestsFile "log.requests-file"
|
||||
- @ref CommandLineLoggingLogSeverity "log.severity"
|
||||
- @ref CommandLineLoggingLogSyslog "log.syslog"
|
||||
- @ref CommandLineLoggingHuman
|
||||
|
@ -48,7 +49,8 @@ TOC {#CommandLineTOC}
|
|||
- @ref CommandLineLoggingLogLineNumber "log.line-number"
|
||||
- @ref CommandLineLoggingLogPrefix "log.prefix"
|
||||
- @ref CommandLineLoggingLogThread "log.thread"
|
||||
- @ref CommandLineLoggingLogFilter "log.filter"
|
||||
- @ref CommandLineLoggingLogSourceFilter "log.source-filter"
|
||||
- @ref CommandLineLoggingLogContentFilter "log.content-filter"
|
||||
- @ref CommandLineLoggingMachine
|
||||
- @ref CommandLineLoggingLogApplication "log.application"
|
||||
- @ref CommandLineLoggingLogFacility "log.facility"
|
||||
|
|
|
@ -292,7 +292,7 @@ void ArangoClient::parse (ProgramOptions& options,
|
|||
|
||||
// setup the logging
|
||||
TRI_SetLogLevelLogging(_logLevel.c_str());
|
||||
TRI_CreateLogAppenderFile("-");
|
||||
TRI_CreateLogAppenderFile("-", 0, TRI_LOG_SEVERITY_UNKNOWN, false);
|
||||
TRI_SetLineNumberLogging(false);
|
||||
TRI_SetThreadIdentifierLogging(false);
|
||||
|
||||
|
|
|
@ -28,7 +28,12 @@
|
|||
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
exports.GraphAPI = {
|
||||
var GraphAPI,
|
||||
arangodb = require("org/arangodb"),
|
||||
arangosh = require("org/arangodb/arangosh");
|
||||
|
||||
|
||||
GraphAPI = {
|
||||
send: function (method, graphKey, path, data) {
|
||||
var results = arangodb.arango[method]("/_api/graph/" +
|
||||
encodeURIComponent(graphKey) +
|
||||
|
@ -171,3 +176,5 @@ exports.GraphAPI = {
|
|||
return new ArangoQueryCursor(database, results);
|
||||
}
|
||||
};
|
||||
|
||||
exports.GraphAPI = GraphAPI;
|
||||
|
|
|
@ -145,10 +145,13 @@ ApplicationServer::ApplicationServer (std::string const& name, std::string const
|
|||
_logFormat(),
|
||||
_logSeverity("human"),
|
||||
_logFile("+"),
|
||||
_logRequestsFile(""),
|
||||
_logPrefix(),
|
||||
_logSyslog(),
|
||||
_logThreadId(false),
|
||||
_logLineNumber(false),
|
||||
_logSourceFilter(),
|
||||
_logContentFilter(),
|
||||
_randomGenerator(5) {
|
||||
}
|
||||
|
||||
|
@ -183,10 +186,13 @@ ApplicationServer::ApplicationServer (std::string const& name, std::string const
|
|||
_logFormat(),
|
||||
_logSeverity("human"),
|
||||
_logFile("+"),
|
||||
_logRequestsFile(""),
|
||||
_logPrefix(),
|
||||
_logSyslog(),
|
||||
_logThreadId(false),
|
||||
_logLineNumber(false),
|
||||
_logSourceFilter(),
|
||||
_logContentFilter(),
|
||||
_randomGenerator(3) {
|
||||
storeRealPrivileges();
|
||||
}
|
||||
|
@ -279,6 +285,11 @@ void ApplicationServer::setupLogging (bool threaded, bool daemon) {
|
|||
if (_options.has("log.line-number")) {
|
||||
_logLineNumber = true;
|
||||
}
|
||||
|
||||
if (! _logRequestsFile.empty()) {
|
||||
// add this so the user does not need to think about it
|
||||
_logSeverity += ",usage";
|
||||
}
|
||||
|
||||
TRI_SetLineNumberLogging(_logLineNumber);
|
||||
|
||||
|
@ -287,30 +298,64 @@ void ApplicationServer::setupLogging (bool threaded, bool daemon) {
|
|||
TRI_SetPrefixLogging(_logPrefix);
|
||||
TRI_SetThreadIdentifierLogging(_logThreadId);
|
||||
|
||||
for (vector<string>::iterator i = _logFilter.begin(); i != _logFilter.end(); ++i) {
|
||||
for (vector<string>::iterator i = _logSourceFilter.begin(); i != _logSourceFilter.end(); ++i) {
|
||||
TRI_SetFileToLog(i->c_str());
|
||||
}
|
||||
|
||||
#ifdef TRI_ENABLE_SYSLOG
|
||||
if (_logSyslog != "") {
|
||||
TRI_CreateLogAppenderSyslog(_logPrefix.c_str(), _logSyslog.c_str());
|
||||
}
|
||||
#endif
|
||||
char const* contentFilter = 0;
|
||||
|
||||
if (_logFile.length() > 0) {
|
||||
if (_options.has("log.content-filter")) {
|
||||
contentFilter = _logContentFilter.c_str();
|
||||
}
|
||||
|
||||
// requests log (must come before the regular logs)
|
||||
if (! _logRequestsFile.empty()) {
|
||||
string filename = _logRequestsFile;
|
||||
|
||||
if (daemon && filename != "+" && filename != "-") {
|
||||
filename = filename + ".daemon";
|
||||
}
|
||||
|
||||
// this appender consumes all usage log messages, so they are not propagated to any others
|
||||
struct TRI_log_appender_s* appender = TRI_CreateLogAppenderFile(filename.c_str(),
|
||||
0,
|
||||
TRI_LOG_SEVERITY_USAGE,
|
||||
true);
|
||||
|
||||
// the user specified a requests log file to use but it could not be created. bail out
|
||||
if (appender == 0) {
|
||||
LOGGER_FATAL_AND_EXIT("failed to create requests logfile '" << filename << "'. Please check the path and permissions.");
|
||||
}
|
||||
}
|
||||
|
||||
// regular log file
|
||||
if (! _logFile.empty()) {
|
||||
string filename = _logFile;
|
||||
|
||||
if (daemon && filename != "+" && filename != "-") {
|
||||
filename = filename + ".daemon";
|
||||
}
|
||||
|
||||
struct TRI_log_appender_s* appender = TRI_CreateLogAppenderFile(filename.c_str());
|
||||
struct TRI_log_appender_s* appender = TRI_CreateLogAppenderFile(filename.c_str(),
|
||||
contentFilter,
|
||||
TRI_LOG_SEVERITY_UNKNOWN,
|
||||
false);
|
||||
|
||||
// the user specified a log file to use but it could not be created. bail out
|
||||
if (appender == 0) {
|
||||
LOGGER_FATAL_AND_EXIT("failed to create logfile '" << filename << "'. Please check the path and permissions.");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TRI_ENABLE_SYSLOG
|
||||
if (_logSyslog != "") {
|
||||
TRI_CreateLogAppenderSyslog(_logPrefix.c_str(),
|
||||
_logSyslog.c_str(),
|
||||
contentFilter,
|
||||
TRI_LOG_SEVERITY_UNKNOWN,
|
||||
false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -791,13 +836,15 @@ void ApplicationServer::setupOptions (map<string, ProgramOptionsDescription>& op
|
|||
|
||||
options[OPTIONS_LOGGER]
|
||||
("log.file", &_logFile, "log to file")
|
||||
("log.requests-file", &_logRequestsFile, "log requests to file")
|
||||
("log.level,l", &_logLevel, "log level for severity 'human'")
|
||||
;
|
||||
|
||||
options[OPTIONS_LOGGER + ":help-log"]
|
||||
("log.application", &_logApplicationName, "application name for syslog")
|
||||
("log.facility", &_logFacility, "facility name for syslog")
|
||||
("log.filter", &_logFilter, "only debug and trace messages originated by specific C source file")
|
||||
("log.source-filter", &_logSourceFilter, "only debug and trace messages originated by specific C source file")
|
||||
("log.content-filter", &_logContentFilter, "only log message containing the specified string (case-sensitive)")
|
||||
("log.format", &_logFormat, "log format")
|
||||
("log.hostname", &_logHostName, "host name")
|
||||
("log.line-number", "always log file and line number")
|
||||
|
|
|
@ -705,11 +705,11 @@ namespace triagens {
|
|||
string _logSeverity;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief log level
|
||||
/// @brief log file
|
||||
///
|
||||
/// @CMDOPT{\--log.file @CA{filename}}
|
||||
///
|
||||
/// This option allows the user to specify the name of a file to which
|
||||
/// This option allows the user to specify the name of a file to which
|
||||
/// information is logged. By default, if no log file is specified, the standard
|
||||
/// output is used. Note that if the file named by @CA{filename} does not
|
||||
/// exist, it will be created. If the file cannot be created (e.g. due to
|
||||
|
@ -722,6 +722,24 @@ namespace triagens {
|
|||
|
||||
string _logFile;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief log file for requests
|
||||
///
|
||||
/// @CMDOPT{\--log.requests-file @CA{filename}}
|
||||
///
|
||||
/// This option allows the user to specify the name of a file to which
|
||||
/// requests are logged. By default, no log file is used and requests are
|
||||
/// not logged. Note that if the file named by @CA{filename} does not
|
||||
/// exist, it will be created. If the file cannot be created (e.g. due to
|
||||
/// missing file privileges), the server will refuse to start. If the specified
|
||||
/// file already exists, output is appended to that file.
|
||||
///
|
||||
/// Use @LIT{+} to log to standard error. Use @LIT{-} to log to standard output.
|
||||
/// Use @LIT{""} to disable request logging altogether.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string _logRequestsFile;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief log prefix
|
||||
///
|
||||
|
@ -787,15 +805,25 @@ namespace triagens {
|
|||
bool _logLineNumber;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief log filter
|
||||
/// @brief log source filter
|
||||
///
|
||||
/// @CMDOPT{\--log.filter @CA{arg}}
|
||||
/// @CMDOPT{\--log.source-filter @CA{arg}}
|
||||
///
|
||||
/// For debug and trace messages, only log those messages originated from the
|
||||
/// C source file @CA{arg}. The argument can be used multiple times.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<string> _logFilter;
|
||||
vector<string> _logSourceFilter;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief log content filter
|
||||
///
|
||||
/// @CMDOPT{\--log.content-filter @CA{arg}}
|
||||
///
|
||||
/// Only log message containing the specified string @CA{arg}.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string _logContentFilter;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief random number generator to use
|
||||
|
|
|
@ -66,6 +66,9 @@ typedef struct TRI_log_appender_s {
|
|||
void (*log) (struct TRI_log_appender_s*, TRI_log_level_e, TRI_log_severity_e, char const* msg, size_t length);
|
||||
void (*reopen) (struct TRI_log_appender_s*);
|
||||
void (*close) (struct TRI_log_appender_s*);
|
||||
char* _contentFilter; // an optional content filter for log messages
|
||||
TRI_log_severity_e _severityFilter; // appender will care only about message with a specific severity. set to TRI_LOG_SEVERITY_UNKNOWN to catch all
|
||||
bool _consume; // whether or not the appender will consume the message (true) or let it through to other appenders (false)
|
||||
}
|
||||
TRI_log_appender_t;
|
||||
|
||||
|
@ -172,6 +175,12 @@ static TRI_thread_t LoggingThread;
|
|||
|
||||
static sig_atomic_t LoggingThreadActive = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief usage logging
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static sig_atomic_t IsUsage = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief human readable logging
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -455,10 +464,17 @@ static int GenerateMessage (char* buffer,
|
|||
// .............................................................................
|
||||
|
||||
if (ShowThreadIdentifier) {
|
||||
n = snprintf(buffer + m, size - m, "[%llu-%llu] ", (unsigned long long) currentProcessId, (unsigned long long) currentThreadId);
|
||||
n = snprintf(buffer + m,
|
||||
size - m,
|
||||
"[%llu-%llu] ",
|
||||
(unsigned long long) currentProcessId,
|
||||
(unsigned long long) currentThreadId);
|
||||
}
|
||||
else {
|
||||
n = snprintf(buffer + m, size - m, "[%llu] ", (unsigned long long) currentProcessId);
|
||||
n = snprintf(buffer + m,
|
||||
size - m,
|
||||
"[%llu] ",
|
||||
(unsigned long long) currentProcessId);
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
|
@ -477,12 +493,12 @@ static int GenerateMessage (char* buffer,
|
|||
ll = "UNKNOWN";
|
||||
|
||||
switch (level) {
|
||||
case TRI_LOG_LEVEL_FATAL: ll = "FATAL"; break;
|
||||
case TRI_LOG_LEVEL_ERROR: ll = "ERROR"; break;
|
||||
case TRI_LOG_LEVEL_FATAL: ll = "FATAL"; break;
|
||||
case TRI_LOG_LEVEL_ERROR: ll = "ERROR"; break;
|
||||
case TRI_LOG_LEVEL_WARNING: ll = "WARNING"; break;
|
||||
case TRI_LOG_LEVEL_INFO: ll = "INFO"; break;
|
||||
case TRI_LOG_LEVEL_DEBUG: ll = "DEBUG"; break;
|
||||
case TRI_LOG_LEVEL_TRACE: ll = "TRACE"; break;
|
||||
case TRI_LOG_LEVEL_INFO: ll = "INFO"; break;
|
||||
case TRI_LOG_LEVEL_DEBUG: ll = "DEBUG"; break;
|
||||
case TRI_LOG_LEVEL_TRACE: ll = "TRACE"; break;
|
||||
}
|
||||
|
||||
n = snprintf(buffer + m, size - m, "%s ", ll);
|
||||
|
@ -597,7 +613,8 @@ static void OutputMessage (TRI_log_level_e level,
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// copy message to ring buffer of recent log messages
|
||||
if (severity == TRI_LOG_SEVERITY_HUMAN) {
|
||||
// we start copying the message from the given offset to skip any irrelevant
|
||||
// or redundant message parts such as date, info etc. The offset might be 0 though.
|
||||
|
@ -645,7 +662,27 @@ static void OutputMessage (TRI_log_level_e level,
|
|||
TRI_log_appender_t* appender;
|
||||
|
||||
appender = Appenders._buffer[i];
|
||||
|
||||
assert(appender != NULL);
|
||||
|
||||
// apply severity filter
|
||||
if (appender->_severityFilter != TRI_LOG_SEVERITY_UNKNOWN &&
|
||||
appender->_severityFilter != severity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// apply content filter on log message
|
||||
if (appender->_contentFilter != NULL) {
|
||||
if (! TRI_IsContainedString(message, appender->_contentFilter)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
appender->log(appender, level, severity, message, length);
|
||||
|
||||
if (appender->_consume) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_UnlockSpin(&AppendersLock);
|
||||
|
@ -715,7 +752,27 @@ static void MessageQueueWorker (void* data) {
|
|||
TRI_log_appender_t* appender;
|
||||
|
||||
appender = Appenders._buffer[i];
|
||||
|
||||
assert(appender != NULL);
|
||||
|
||||
// apply severity filter
|
||||
if (appender->_severityFilter != TRI_LOG_SEVERITY_UNKNOWN &&
|
||||
appender->_severityFilter != msg->_severity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// apply content filter on log message
|
||||
if (appender->_contentFilter != NULL) {
|
||||
if (! TRI_IsContainedString(msg->_message, appender->_contentFilter)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
appender->log(appender, msg->_level, msg->_severity, msg->_message, msg->_length);
|
||||
|
||||
if (appender->_consume) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_UnlockSpin(&AppendersLock);
|
||||
|
@ -983,6 +1040,7 @@ void TRI_SetLogSeverityLogging (char const* severities) {
|
|||
IsTechnical = 0;
|
||||
IsFunctional = 0;
|
||||
IsDevelopment = 0;
|
||||
IsUsage = 0;
|
||||
IsHuman = 0;
|
||||
|
||||
n = split._length;
|
||||
|
@ -1002,6 +1060,9 @@ void TRI_SetLogSeverityLogging (char const* severities) {
|
|||
else if (TRI_CaseEqualString(type, "development")) {
|
||||
IsDevelopment = 1;
|
||||
}
|
||||
else if (TRI_CaseEqualString(type, "usage")) {
|
||||
IsUsage = 1;
|
||||
}
|
||||
else if (TRI_CaseEqualString(type, "human")) {
|
||||
IsHuman = 1;
|
||||
}
|
||||
|
@ -1010,6 +1071,7 @@ void TRI_SetLogSeverityLogging (char const* severities) {
|
|||
IsTechnical = 1;
|
||||
IsFunctional = 1;
|
||||
IsDevelopment = 1;
|
||||
IsUsage = 1;
|
||||
IsHuman = 1;
|
||||
}
|
||||
else if (TRI_CaseEqualString(type, "non-human")) {
|
||||
|
@ -1017,6 +1079,7 @@ void TRI_SetLogSeverityLogging (char const* severities) {
|
|||
IsTechnical = 1;
|
||||
IsFunctional = 1;
|
||||
IsDevelopment = 1;
|
||||
IsUsage = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1072,6 +1135,14 @@ void TRI_SetFileToLog (char const* file) {
|
|||
FilesToLog[TRI_FnvHashString(file) % FilesToLogSize] = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if usage logging is enabled
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_IsUsageLogging () {
|
||||
return IsUsage != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if human logging is enabled
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1458,6 +1529,10 @@ static void LogAppenderFile_Close (TRI_log_appender_t* appender) {
|
|||
TRI_FreeString(TRI_CORE_MEM_ZONE, self->_filename);
|
||||
}
|
||||
|
||||
if (self->base._contentFilter != NULL) {
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, self->base._contentFilter);
|
||||
}
|
||||
|
||||
TRI_DestroySpin(&self->_lock);
|
||||
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, self);
|
||||
|
@ -1480,7 +1555,10 @@ static void LogAppenderFile_Close (TRI_log_appender_t* appender) {
|
|||
/// @brief creates a log appender for file output
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_log_appender_t* TRI_CreateLogAppenderFile (char const* filename) {
|
||||
TRI_log_appender_t* TRI_CreateLogAppenderFile (char const* filename,
|
||||
char const* contentFilter,
|
||||
TRI_log_severity_e severityFilter,
|
||||
bool consume) {
|
||||
log_appender_file_t* appender;
|
||||
|
||||
// no logging
|
||||
|
@ -1496,6 +1574,19 @@ TRI_log_appender_t* TRI_CreateLogAppenderFile (char const* filename) {
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
appender->base._contentFilter = NULL;
|
||||
appender->base._severityFilter = severityFilter;
|
||||
appender->base._consume = consume;
|
||||
|
||||
if (contentFilter != NULL) {
|
||||
if (NULL == (appender->base._contentFilter = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, contentFilter))) {
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, appender);
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// logging to stdout
|
||||
if (TRI_EqualString(filename, "+")) {
|
||||
|
@ -1521,6 +1612,7 @@ TRI_log_appender_t* TRI_CreateLogAppenderFile (char const* filename) {
|
|||
TRI_SetCloseOnExitFile(appender->_fd);
|
||||
|
||||
appender->_filename = TRI_DuplicateString(filename);
|
||||
|
||||
if (appender->_filename == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, appender);
|
||||
|
@ -1530,9 +1622,9 @@ TRI_log_appender_t* TRI_CreateLogAppenderFile (char const* filename) {
|
|||
}
|
||||
|
||||
// set methods
|
||||
appender->base.log = LogAppenderFile_Log;
|
||||
appender->base.log = LogAppenderFile_Log;
|
||||
appender->base.reopen = LogAppenderFile_Reopen;
|
||||
appender->base.close = LogAppenderFile_Close;
|
||||
appender->base.close = LogAppenderFile_Close;
|
||||
|
||||
// create lock
|
||||
TRI_InitSpin(&appender->_lock);
|
||||
|
@ -1607,6 +1699,7 @@ static void LogAppenderSyslog_Log (TRI_log_appender_t* appender,
|
|||
switch (severity) {
|
||||
case TRI_LOG_SEVERITY_EXCEPTION: priority = LOG_CRIT; break;
|
||||
case TRI_LOG_SEVERITY_FUNCTIONAL: priority = LOG_NOTICE; break;
|
||||
case TRI_LOG_SEVERITY_USAGE: priority = LOG_INFO; break;
|
||||
case TRI_LOG_SEVERITY_TECHNICAL: priority = LOG_INFO; break;
|
||||
case TRI_LOG_SEVERITY_DEVELOPMENT: priority = LOG_DEBUG; break;
|
||||
default: priority = LOG_DEBUG; break;
|
||||
|
@ -1653,12 +1746,16 @@ static void LogAppenderSyslog_Close (TRI_log_appender_t* appender) {
|
|||
log_appender_syslog_t* self;
|
||||
|
||||
self = (log_appender_syslog_t*) appender;
|
||||
|
||||
|
||||
TRI_LockMutex(&self->_mutex);
|
||||
closelog();
|
||||
TRI_UnlockMutex(&self->_mutex);
|
||||
|
||||
TRI_DestroyMutex(&self->_mutex);
|
||||
|
||||
if (self->base._contentFilter != NULL) {
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, self->base._contentFilter);
|
||||
}
|
||||
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, self);
|
||||
}
|
||||
|
@ -1684,7 +1781,11 @@ static void LogAppenderSyslog_Close (TRI_log_appender_t* appender) {
|
|||
|
||||
#ifdef TRI_ENABLE_SYSLOG
|
||||
|
||||
TRI_log_appender_t* TRI_CreateLogAppenderSyslog (char const* name, char const* facility) {
|
||||
TRI_log_appender_t* TRI_CreateLogAppenderSyslog (char const* name,
|
||||
char const* facility,
|
||||
char const* contentFilter,
|
||||
TRI_log_severity_e severityFilter,
|
||||
bool consume) {
|
||||
log_appender_syslog_t* appender;
|
||||
int value;
|
||||
|
||||
|
@ -1699,10 +1800,27 @@ TRI_log_appender_t* TRI_CreateLogAppenderSyslog (char const* name, char const* f
|
|||
// allocate space
|
||||
appender = (log_appender_syslog_t*) TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(log_appender_syslog_t), false);
|
||||
|
||||
if (appender == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
appender->base._contentFilter = NULL;
|
||||
appender->base._severityFilter = severityFilter;
|
||||
appender->base._consume = consume;
|
||||
|
||||
// set methods
|
||||
appender->base.log = LogAppenderSyslog_Log;
|
||||
appender->base.reopen = LogAppenderSyslog_Reopen;
|
||||
appender->base.close = LogAppenderSyslog_Close;
|
||||
appender->base.log = LogAppenderSyslog_Log;
|
||||
appender->base.reopen = LogAppenderSyslog_Reopen;
|
||||
appender->base.close = LogAppenderSyslog_Close;
|
||||
|
||||
if (contentFilter != NULL) {
|
||||
if (NULL == (appender->base._contentFilter = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, contentFilter))) {
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, appender);
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_InitMutex(&appender->_mutex);
|
||||
|
||||
|
|
|
@ -54,12 +54,12 @@ extern "C" {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
TRI_LOG_LEVEL_FATAL = 1,
|
||||
TRI_LOG_LEVEL_ERROR = 2,
|
||||
TRI_LOG_LEVEL_FATAL = 1,
|
||||
TRI_LOG_LEVEL_ERROR = 2,
|
||||
TRI_LOG_LEVEL_WARNING = 3,
|
||||
TRI_LOG_LEVEL_INFO = 4,
|
||||
TRI_LOG_LEVEL_DEBUG = 5,
|
||||
TRI_LOG_LEVEL_TRACE = 6
|
||||
TRI_LOG_LEVEL_INFO = 4,
|
||||
TRI_LOG_LEVEL_DEBUG = 5,
|
||||
TRI_LOG_LEVEL_TRACE = 6
|
||||
}
|
||||
TRI_log_level_e;
|
||||
|
||||
|
@ -68,12 +68,13 @@ TRI_log_level_e;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
TRI_LOG_SEVERITY_EXCEPTION = 1,
|
||||
TRI_LOG_SEVERITY_TECHNICAL = 2,
|
||||
TRI_LOG_SEVERITY_FUNCTIONAL = 3,
|
||||
TRI_LOG_SEVERITY_EXCEPTION = 1,
|
||||
TRI_LOG_SEVERITY_TECHNICAL = 2,
|
||||
TRI_LOG_SEVERITY_FUNCTIONAL = 3,
|
||||
TRI_LOG_SEVERITY_DEVELOPMENT = 4,
|
||||
TRI_LOG_SEVERITY_HUMAN = 5,
|
||||
TRI_LOG_SEVERITY_UNKNOWN = 6
|
||||
TRI_LOG_SEVERITY_USAGE = 5,
|
||||
TRI_LOG_SEVERITY_HUMAN = 6,
|
||||
TRI_LOG_SEVERITY_UNKNOWN = 7
|
||||
}
|
||||
TRI_log_severity_e;
|
||||
|
||||
|
@ -84,9 +85,9 @@ TRI_log_severity_e;
|
|||
typedef enum {
|
||||
|
||||
// exceptions
|
||||
TRI_LOG_CATEGORY_FATAL = 1000,
|
||||
TRI_LOG_CATEGORY_ERROR = 1001,
|
||||
TRI_LOG_CATEGORY_WARNING = 1002,
|
||||
TRI_LOG_CATEGORY_FATAL = 1000,
|
||||
TRI_LOG_CATEGORY_ERROR = 1001,
|
||||
TRI_LOG_CATEGORY_WARNING = 1002,
|
||||
|
||||
// technical
|
||||
TRI_LOG_CATEGORY_HEARTBEAT = 2000,
|
||||
|
@ -179,6 +180,12 @@ void TRI_SetFunctionLogging (bool show);
|
|||
|
||||
void TRI_SetFileToLog (char const* file);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if usage logging is enabled
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_IsUsageLogging (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if human logging is enabled
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -433,6 +440,28 @@ void CLEANUP_LOGGING_AND_EXIT_ON_FATAL_ERROR (void);
|
|||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief logs usage messages
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#undef LOG_USAGE
|
||||
|
||||
#ifdef TRI_ENABLE_LOGGER
|
||||
|
||||
#define LOG_USAGE(...) \
|
||||
do { \
|
||||
LOG_ARG_CHECK(__VA_ARGS__) \
|
||||
if (TRI_IsUsageLogging()) { \
|
||||
TRI_Log(__FUNCTION__, __FILE__, __LINE__, TRI_LOG_LEVEL_INFO, TRI_LOG_SEVERITY_USAGE, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define LOG_USAGE(...) while (0)
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -473,14 +502,21 @@ struct TRI_log_appender_s;
|
|||
/// @brief creates a log append for file output
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_log_appender_s* TRI_CreateLogAppenderFile (char const* filename);
|
||||
struct TRI_log_appender_s* TRI_CreateLogAppenderFile (char const*,
|
||||
char const*,
|
||||
TRI_log_severity_e,
|
||||
bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a log append for syslog
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_SYSLOG
|
||||
struct TRI_log_appender_s* TRI_CreateLogAppenderSyslog (char const* name, char const* facility);
|
||||
struct TRI_log_appender_s* TRI_CreateLogAppenderSyslog (char const*,
|
||||
char const*,
|
||||
char const*,
|
||||
TRI_log_severity_e,
|
||||
bool);
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -524,6 +524,14 @@ bool TRI_IsPrefixString (char const* full, char const* prefix) {
|
|||
return strncmp(full, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests if second string is contained in the first
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_IsContainedString (char const* full, char const* part) {
|
||||
return strstr(full, part) != NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief duplicates a string, without using a memory zone
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -111,6 +111,12 @@ bool TRI_CaseEqualString2 (char const* left, char const* right, size_t n);
|
|||
|
||||
bool TRI_IsPrefixString (char const* full, char const* prefix);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests if second string is contained in the first
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_IsContainedString (char const* full, char const* part);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief duplicates a string, without using a memory zone
|
||||
///
|
||||
|
|
|
@ -140,6 +140,10 @@ namespace triagens {
|
|||
this->_bodyLength = 0;
|
||||
this->_readRequestBody = false;
|
||||
this->_requestPending = false;
|
||||
|
||||
this->_httpVersion = HttpRequest::HTTP_UNKNOWN;
|
||||
this->_requestType = HttpRequest::HTTP_REQUEST_ILLEGAL;
|
||||
this->_fullUrl = "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -223,8 +227,11 @@ namespace triagens {
|
|||
return true;
|
||||
}
|
||||
|
||||
// check HTTP protocol
|
||||
if (! this->_request->isHttp10() && ! this->_request->isHttp11()) {
|
||||
// check HTTP protocol version
|
||||
_httpVersion = this->_request->httpVersion();
|
||||
|
||||
if (_httpVersion != HttpRequest::HTTP_1_0 &&
|
||||
_httpVersion != HttpRequest::HTTP_1_1) {
|
||||
HttpResponse response(HttpResponse::HTTP_VERSION_NOT_SUPPORTED);
|
||||
this->handleResponse(&response);
|
||||
this->resetState();
|
||||
|
@ -233,7 +240,8 @@ namespace triagens {
|
|||
}
|
||||
|
||||
// check max URL length
|
||||
if (this->_request->fullUrl().length() > 16384) {
|
||||
_fullUrl = this->_request->fullUrl();
|
||||
if (_fullUrl.size() > 16384) {
|
||||
HttpResponse response(HttpResponse::REQUEST_URI_TOO_LONG);
|
||||
this->handleResponse(&response);
|
||||
this->resetState();
|
||||
|
@ -306,15 +314,6 @@ namespace triagens {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// enable the following statement for excessive logging of incoming requests
|
||||
// LOGGER_INFO(this->_connectionInfo.serverAddress << "," << this->_connectionInfo.serverPort << "," <<
|
||||
// this->_connectionInfo.clientAddress << "," <<
|
||||
// HttpRequest::translateMethod(this->_request->requestType()) << "," <<
|
||||
// HttpRequest::translateVersion(this->_request->httpVersion()) << "," <<
|
||||
// this->_bodyLength << "," <<
|
||||
// this->_request->fullUrl());
|
||||
|
||||
// .............................................................................
|
||||
// check if server is active
|
||||
// .............................................................................
|
||||
|
@ -530,15 +529,13 @@ namespace triagens {
|
|||
|
||||
// not authenticated
|
||||
else {
|
||||
string realm = "basic realm=\"" + this->_server->getHandlerFactory()->authenticationRealm(this->_request) + "\"";
|
||||
|
||||
delete this->_request;
|
||||
this->_request = 0;
|
||||
const string realm = "basic realm=\"" + this->_server->getHandlerFactory()->authenticationRealm(this->_request) + "\"";
|
||||
|
||||
HttpResponse response(HttpResponse::UNAUTHORIZED);
|
||||
response.setHeader("www-authenticate", strlen("www-authenticate"), realm.c_str());
|
||||
|
||||
this->handleResponse(&response);
|
||||
this->resetState();
|
||||
}
|
||||
|
||||
return processRead();
|
||||
|
@ -606,6 +603,14 @@ namespace triagens {
|
|||
|
||||
LOGGER_TRACE("HTTP WRITE FOR " << static_cast<Task*>(this) << ":\n" << buffer->c_str());
|
||||
|
||||
// disable the following statement to prevent excessive logging of incoming requests
|
||||
LOGGER_USAGE(this->_connectionInfo.clientAddress << " \"" <<
|
||||
HttpRequest::translateMethod(this->_requestType) << " " <<
|
||||
this->_fullUrl << " " <<
|
||||
HttpRequest::translateVersion(this->_httpVersion) << "\" " <<
|
||||
response->responseCode() << " " <<
|
||||
response->body().length());
|
||||
|
||||
// clear body
|
||||
response->body().clear();
|
||||
|
||||
|
@ -670,12 +675,24 @@ namespace triagens {
|
|||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief http version number used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HttpRequest::HttpVersion _httpVersion;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief type of request (GET, POST, ...)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HttpRequest::HttpRequestType _requestType;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief value of requested URL
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string _fullUrl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief value of the HTTP origin header the client sent (if any).
|
||||
/// this is only used for CORS
|
||||
|
|
|
@ -104,6 +104,12 @@ void TRI_SetFileToLog (string const& file) {
|
|||
|
||||
static string LoggerFormat = "%Z;1;%S;%C;%H;%p-%t;%F;%A;%f;%m;%K;%f:%l;%x;%P;%u;%V;%U;%E";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief logger format for raw logging
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static string LoggerRawFormat = "%Z %x";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief special characters which must be escaped
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -128,8 +134,18 @@ static string const SpecialCharacters = ";%\r\t\n";
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void OutputMachine (string const& text, LoggerData::Info const& info) {
|
||||
char const* format = LoggerFormat.c_str();
|
||||
char const* end = format + LoggerFormat.size();
|
||||
char const* format;
|
||||
char const* end;
|
||||
|
||||
if (info._severity == TRI_LOG_SEVERITY_USAGE) {
|
||||
format = LoggerRawFormat.c_str();
|
||||
end = format + LoggerRawFormat.size();
|
||||
}
|
||||
else {
|
||||
format = LoggerFormat.c_str();
|
||||
end = format + LoggerFormat.size();
|
||||
}
|
||||
|
||||
time_t tt = time(0);
|
||||
|
||||
StringBuffer line(TRI_CORE_MEM_ZONE);
|
||||
|
@ -298,6 +314,7 @@ static void OutputMachine (string const& text, LoggerData::Info const& info) {
|
|||
switch (info._severity) {
|
||||
case TRI_LOG_SEVERITY_EXCEPTION: line.appendInteger(2); break;
|
||||
case TRI_LOG_SEVERITY_FUNCTIONAL: line.appendInteger(5); break;
|
||||
case TRI_LOG_SEVERITY_USAGE: line.appendInteger(5); break;
|
||||
case TRI_LOG_SEVERITY_TECHNICAL: line.appendInteger(6); break;
|
||||
case TRI_LOG_SEVERITY_DEVELOPMENT: line.appendInteger(7); break;
|
||||
default: line.appendInteger(7); break;
|
||||
|
@ -534,7 +551,6 @@ Logger::~Logger () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Logger::output (string const& text, LoggerData::Info const& info) {
|
||||
|
||||
// human readable
|
||||
if (info._severity == TRI_LOG_SEVERITY_HUMAN) {
|
||||
if (! TRI_IsHumanLogging()) {
|
||||
|
@ -547,12 +563,18 @@ void Logger::output (string const& text, LoggerData::Info const& info) {
|
|||
info._level,
|
||||
info._severity,
|
||||
"%s", text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
// usage logging
|
||||
else if (info._severity == TRI_LOG_SEVERITY_USAGE) {
|
||||
if (! TRI_IsUsageLogging()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// machine readable logging
|
||||
else {
|
||||
OutputMachine(text, info);
|
||||
}
|
||||
OutputMachine(text, info);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -358,6 +358,31 @@
|
|||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief logs usage messages
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_LOGGER
|
||||
|
||||
#define LOGGER_USAGE(a) \
|
||||
do { \
|
||||
if (TRI_IsUsageLogging()) { \
|
||||
triagens::basics::Logger::_singleton \
|
||||
<< TRI_LOG_LEVEL_INFO \
|
||||
<< TRI_LOG_SEVERITY_USAGE \
|
||||
<< triagens::basics::LoggerData::Position(__FUNCTION__, __FILE__, __LINE__) \
|
||||
<< a; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define LOGGER_USAGE(a) \
|
||||
while (0)
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief logs non-human messsages
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue