1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

This commit is contained in:
Michael Hackstein 2013-07-02 16:17:39 +02:00
commit b69f270080
14 changed files with 413 additions and 72 deletions

View File

@ -1,6 +1,23 @@
v1.4 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: * added a signal handler for SIGUSR1 signal:
when ArangoDB receives this signal, it will respond all further incoming requests when ArangoDB receives this signal, it will respond all further incoming requests

View File

@ -230,6 +230,10 @@ General Logging Options {#CommandLineLoggingGeneral}
@anchor CommandLineLoggingLogFile @anchor CommandLineLoggingLogFile
@copydetails triagens::rest::ApplicationServer::_logFile @copydetails triagens::rest::ApplicationServer::_logFile
@CLEARPAGE
@anchor CommandLineLoggingLogRequestsFile
@copydetails triagens::rest::ApplicationServer::_logRequestsFile
@CLEARPAGE @CLEARPAGE
@anchor CommandLineLoggingLogSeverity @anchor CommandLineLoggingLogSeverity
@copydetails triagens::rest::ApplicationServer::_logSeverity @copydetails triagens::rest::ApplicationServer::_logSeverity
@ -258,8 +262,12 @@ Human Readable Logging {#CommandLineLoggingHuman}
@copydetails triagens::rest::ApplicationServer::_logThreadId @copydetails triagens::rest::ApplicationServer::_logThreadId
@CLEARPAGE @CLEARPAGE
@anchor CommandLineLoggingLogFilter @anchor CommandLineLoggingLogSourceFilter
@copydetails triagens::rest::ApplicationServer::_logFilter @copydetails triagens::rest::ApplicationServer::_logSourceFilter
@CLEARPAGE
@anchor CommandLineLoggingLogContentFilter
@copydetails triagens::rest::ApplicationServer::_logContentFilter
@CLEARPAGE @CLEARPAGE
Machine Readable Logging {#CommandLineLoggingMachine} Machine Readable Logging {#CommandLineLoggingMachine}

View File

@ -41,6 +41,7 @@ TOC {#CommandLineTOC}
- @ref CommandLineLogging - @ref CommandLineLogging
- @ref CommandLineLoggingGeneral - @ref CommandLineLoggingGeneral
- @ref CommandLineLoggingLogFile "log.file" - @ref CommandLineLoggingLogFile "log.file"
- @ref CommandLineLoggingLogRequestsFile "log.requests-file"
- @ref CommandLineLoggingLogSeverity "log.severity" - @ref CommandLineLoggingLogSeverity "log.severity"
- @ref CommandLineLoggingLogSyslog "log.syslog" - @ref CommandLineLoggingLogSyslog "log.syslog"
- @ref CommandLineLoggingHuman - @ref CommandLineLoggingHuman
@ -48,7 +49,8 @@ TOC {#CommandLineTOC}
- @ref CommandLineLoggingLogLineNumber "log.line-number" - @ref CommandLineLoggingLogLineNumber "log.line-number"
- @ref CommandLineLoggingLogPrefix "log.prefix" - @ref CommandLineLoggingLogPrefix "log.prefix"
- @ref CommandLineLoggingLogThread "log.thread" - @ref CommandLineLoggingLogThread "log.thread"
- @ref CommandLineLoggingLogFilter "log.filter" - @ref CommandLineLoggingLogSourceFilter "log.source-filter"
- @ref CommandLineLoggingLogContentFilter "log.content-filter"
- @ref CommandLineLoggingMachine - @ref CommandLineLoggingMachine
- @ref CommandLineLoggingLogApplication "log.application" - @ref CommandLineLoggingLogApplication "log.application"
- @ref CommandLineLoggingLogFacility "log.facility" - @ref CommandLineLoggingLogFacility "log.facility"

View File

@ -292,7 +292,7 @@ void ArangoClient::parse (ProgramOptions& options,
// setup the logging // setup the logging
TRI_SetLogLevelLogging(_logLevel.c_str()); TRI_SetLogLevelLogging(_logLevel.c_str());
TRI_CreateLogAppenderFile("-"); TRI_CreateLogAppenderFile("-", 0, TRI_LOG_SEVERITY_UNKNOWN, false);
TRI_SetLineNumberLogging(false); TRI_SetLineNumberLogging(false);
TRI_SetThreadIdentifierLogging(false); TRI_SetThreadIdentifierLogging(false);

View File

@ -28,7 +28,12 @@
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany /// @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) { send: function (method, graphKey, path, data) {
var results = arangodb.arango[method]("/_api/graph/" + var results = arangodb.arango[method]("/_api/graph/" +
encodeURIComponent(graphKey) + encodeURIComponent(graphKey) +
@ -171,3 +176,5 @@ exports.GraphAPI = {
return new ArangoQueryCursor(database, results); return new ArangoQueryCursor(database, results);
} }
}; };
exports.GraphAPI = GraphAPI;

View File

@ -145,10 +145,13 @@ ApplicationServer::ApplicationServer (std::string const& name, std::string const
_logFormat(), _logFormat(),
_logSeverity("human"), _logSeverity("human"),
_logFile("+"), _logFile("+"),
_logRequestsFile(""),
_logPrefix(), _logPrefix(),
_logSyslog(), _logSyslog(),
_logThreadId(false), _logThreadId(false),
_logLineNumber(false), _logLineNumber(false),
_logSourceFilter(),
_logContentFilter(),
_randomGenerator(5) { _randomGenerator(5) {
} }
@ -183,10 +186,13 @@ ApplicationServer::ApplicationServer (std::string const& name, std::string const
_logFormat(), _logFormat(),
_logSeverity("human"), _logSeverity("human"),
_logFile("+"), _logFile("+"),
_logRequestsFile(""),
_logPrefix(), _logPrefix(),
_logSyslog(), _logSyslog(),
_logThreadId(false), _logThreadId(false),
_logLineNumber(false), _logLineNumber(false),
_logSourceFilter(),
_logContentFilter(),
_randomGenerator(3) { _randomGenerator(3) {
storeRealPrivileges(); storeRealPrivileges();
} }
@ -280,6 +286,11 @@ void ApplicationServer::setupLogging (bool threaded, bool daemon) {
_logLineNumber = true; _logLineNumber = true;
} }
if (! _logRequestsFile.empty()) {
// add this so the user does not need to think about it
_logSeverity += ",usage";
}
TRI_SetLineNumberLogging(_logLineNumber); TRI_SetLineNumberLogging(_logLineNumber);
TRI_SetLogLevelLogging(_logLevel); TRI_SetLogLevelLogging(_logLevel);
@ -287,30 +298,64 @@ void ApplicationServer::setupLogging (bool threaded, bool daemon) {
TRI_SetPrefixLogging(_logPrefix); TRI_SetPrefixLogging(_logPrefix);
TRI_SetThreadIdentifierLogging(_logThreadId); 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()); TRI_SetFileToLog(i->c_str());
} }
#ifdef TRI_ENABLE_SYSLOG char const* contentFilter = 0;
if (_logSyslog != "") {
TRI_CreateLogAppenderSyslog(_logPrefix.c_str(), _logSyslog.c_str());
}
#endif
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; string filename = _logFile;
if (daemon && filename != "+" && filename != "-") { if (daemon && filename != "+" && filename != "-") {
filename = filename + ".daemon"; 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 // the user specified a log file to use but it could not be created. bail out
if (appender == 0) { if (appender == 0) {
LOGGER_FATAL_AND_EXIT("failed to create logfile '" << filename << "'. Please check the path and permissions."); 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] options[OPTIONS_LOGGER]
("log.file", &_logFile, "log to file") ("log.file", &_logFile, "log to file")
("log.requests-file", &_logRequestsFile, "log requests to file")
("log.level,l", &_logLevel, "log level for severity 'human'") ("log.level,l", &_logLevel, "log level for severity 'human'")
; ;
options[OPTIONS_LOGGER + ":help-log"] options[OPTIONS_LOGGER + ":help-log"]
("log.application", &_logApplicationName, "application name for syslog") ("log.application", &_logApplicationName, "application name for syslog")
("log.facility", &_logFacility, "facility 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.format", &_logFormat, "log format")
("log.hostname", &_logHostName, "host name") ("log.hostname", &_logHostName, "host name")
("log.line-number", "always log file and line number") ("log.line-number", "always log file and line number")

View File

@ -705,7 +705,7 @@ namespace triagens {
string _logSeverity; string _logSeverity;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief log level /// @brief log file
/// ///
/// @CMDOPT{\--log.file @CA{filename}} /// @CMDOPT{\--log.file @CA{filename}}
/// ///
@ -722,6 +722,24 @@ namespace triagens {
string _logFile; 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 /// @brief log prefix
/// ///
@ -787,15 +805,25 @@ namespace triagens {
bool _logLineNumber; 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 /// For debug and trace messages, only log those messages originated from the
/// C source file @CA{arg}. The argument can be used multiple times. /// 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 /// @brief random number generator to use

View File

@ -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 (*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 (*reopen) (struct TRI_log_appender_s*);
void (*close) (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; TRI_log_appender_t;
@ -172,6 +175,12 @@ static TRI_thread_t LoggingThread;
static sig_atomic_t LoggingThreadActive = 0; static sig_atomic_t LoggingThreadActive = 0;
////////////////////////////////////////////////////////////////////////////////
/// @brief usage logging
////////////////////////////////////////////////////////////////////////////////
static sig_atomic_t IsUsage = 0;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief human readable logging /// @brief human readable logging
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -455,10 +464,17 @@ static int GenerateMessage (char* buffer,
// ............................................................................. // .............................................................................
if (ShowThreadIdentifier) { 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 { 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) { if (n < 0) {
@ -598,6 +614,7 @@ static void OutputMessage (TRI_log_level_e level,
return; return;
} }
// copy message to ring buffer of recent log messages
if (severity == TRI_LOG_SEVERITY_HUMAN) { if (severity == TRI_LOG_SEVERITY_HUMAN) {
// we start copying the message from the given offset to skip any irrelevant // 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. // 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; TRI_log_appender_t* appender;
appender = Appenders._buffer[i]; 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); appender->log(appender, level, severity, message, length);
if (appender->_consume) {
break;
}
} }
TRI_UnlockSpin(&AppendersLock); TRI_UnlockSpin(&AppendersLock);
@ -715,7 +752,27 @@ static void MessageQueueWorker (void* data) {
TRI_log_appender_t* appender; TRI_log_appender_t* appender;
appender = Appenders._buffer[i]; 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); appender->log(appender, msg->_level, msg->_severity, msg->_message, msg->_length);
if (appender->_consume) {
break;
}
} }
TRI_UnlockSpin(&AppendersLock); TRI_UnlockSpin(&AppendersLock);
@ -983,6 +1040,7 @@ void TRI_SetLogSeverityLogging (char const* severities) {
IsTechnical = 0; IsTechnical = 0;
IsFunctional = 0; IsFunctional = 0;
IsDevelopment = 0; IsDevelopment = 0;
IsUsage = 0;
IsHuman = 0; IsHuman = 0;
n = split._length; n = split._length;
@ -1002,6 +1060,9 @@ void TRI_SetLogSeverityLogging (char const* severities) {
else if (TRI_CaseEqualString(type, "development")) { else if (TRI_CaseEqualString(type, "development")) {
IsDevelopment = 1; IsDevelopment = 1;
} }
else if (TRI_CaseEqualString(type, "usage")) {
IsUsage = 1;
}
else if (TRI_CaseEqualString(type, "human")) { else if (TRI_CaseEqualString(type, "human")) {
IsHuman = 1; IsHuman = 1;
} }
@ -1010,6 +1071,7 @@ void TRI_SetLogSeverityLogging (char const* severities) {
IsTechnical = 1; IsTechnical = 1;
IsFunctional = 1; IsFunctional = 1;
IsDevelopment = 1; IsDevelopment = 1;
IsUsage = 1;
IsHuman = 1; IsHuman = 1;
} }
else if (TRI_CaseEqualString(type, "non-human")) { else if (TRI_CaseEqualString(type, "non-human")) {
@ -1017,6 +1079,7 @@ void TRI_SetLogSeverityLogging (char const* severities) {
IsTechnical = 1; IsTechnical = 1;
IsFunctional = 1; IsFunctional = 1;
IsDevelopment = 1; IsDevelopment = 1;
IsUsage = 1;
} }
} }
@ -1072,6 +1135,14 @@ void TRI_SetFileToLog (char const* file) {
FilesToLog[TRI_FnvHashString(file) % FilesToLogSize] = true; 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 /// @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); 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_DestroySpin(&self->_lock);
TRI_Free(TRI_CORE_MEM_ZONE, self); 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 /// @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; log_appender_file_t* appender;
// no logging // no logging
@ -1497,6 +1575,19 @@ TRI_log_appender_t* TRI_CreateLogAppenderFile (char const* filename) {
return NULL; 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 // logging to stdout
if (TRI_EqualString(filename, "+")) { if (TRI_EqualString(filename, "+")) {
appender->_filename = NULL; appender->_filename = NULL;
@ -1521,6 +1612,7 @@ TRI_log_appender_t* TRI_CreateLogAppenderFile (char const* filename) {
TRI_SetCloseOnExitFile(appender->_fd); TRI_SetCloseOnExitFile(appender->_fd);
appender->_filename = TRI_DuplicateString(filename); appender->_filename = TRI_DuplicateString(filename);
if (appender->_filename == NULL) { if (appender->_filename == NULL) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
TRI_Free(TRI_CORE_MEM_ZONE, appender); TRI_Free(TRI_CORE_MEM_ZONE, appender);
@ -1607,6 +1699,7 @@ static void LogAppenderSyslog_Log (TRI_log_appender_t* appender,
switch (severity) { switch (severity) {
case TRI_LOG_SEVERITY_EXCEPTION: priority = LOG_CRIT; break; case TRI_LOG_SEVERITY_EXCEPTION: priority = LOG_CRIT; break;
case TRI_LOG_SEVERITY_FUNCTIONAL: priority = LOG_NOTICE; 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_TECHNICAL: priority = LOG_INFO; break;
case TRI_LOG_SEVERITY_DEVELOPMENT: priority = LOG_DEBUG; break; case TRI_LOG_SEVERITY_DEVELOPMENT: priority = LOG_DEBUG; break;
default: priority = LOG_DEBUG; break; default: priority = LOG_DEBUG; break;
@ -1660,6 +1753,10 @@ static void LogAppenderSyslog_Close (TRI_log_appender_t* appender) {
TRI_DestroyMutex(&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); TRI_Free(TRI_CORE_MEM_ZONE, self);
} }
@ -1684,7 +1781,11 @@ static void LogAppenderSyslog_Close (TRI_log_appender_t* appender) {
#ifdef TRI_ENABLE_SYSLOG #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; log_appender_syslog_t* appender;
int value; int value;
@ -1699,11 +1800,28 @@ TRI_log_appender_t* TRI_CreateLogAppenderSyslog (char const* name, char const* f
// allocate space // allocate space
appender = (log_appender_syslog_t*) TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(log_appender_syslog_t), false); 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 // set methods
appender->base.log = LogAppenderSyslog_Log; appender->base.log = LogAppenderSyslog_Log;
appender->base.reopen = LogAppenderSyslog_Reopen; appender->base.reopen = LogAppenderSyslog_Reopen;
appender->base.close = LogAppenderSyslog_Close; 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); TRI_InitMutex(&appender->_mutex);
// find facility // find facility

View File

@ -72,8 +72,9 @@ typedef enum {
TRI_LOG_SEVERITY_TECHNICAL = 2, TRI_LOG_SEVERITY_TECHNICAL = 2,
TRI_LOG_SEVERITY_FUNCTIONAL = 3, TRI_LOG_SEVERITY_FUNCTIONAL = 3,
TRI_LOG_SEVERITY_DEVELOPMENT = 4, TRI_LOG_SEVERITY_DEVELOPMENT = 4,
TRI_LOG_SEVERITY_HUMAN = 5, TRI_LOG_SEVERITY_USAGE = 5,
TRI_LOG_SEVERITY_UNKNOWN = 6 TRI_LOG_SEVERITY_HUMAN = 6,
TRI_LOG_SEVERITY_UNKNOWN = 7
} }
TRI_log_severity_e; TRI_log_severity_e;
@ -179,6 +180,12 @@ void TRI_SetFunctionLogging (bool show);
void TRI_SetFileToLog (char const* file); void TRI_SetFileToLog (char const* file);
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if usage logging is enabled
////////////////////////////////////////////////////////////////////////////////
bool TRI_IsUsageLogging (void);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief checks if human logging is enabled /// @brief checks if human logging is enabled
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -433,6 +440,28 @@ void CLEANUP_LOGGING_AND_EXIT_ON_FATAL_ERROR (void);
#endif #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 /// @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 /// @brief creates a log append for syslog
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_ENABLE_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 #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -524,6 +524,14 @@ bool TRI_IsPrefixString (char const* full, char const* prefix) {
return strncmp(full, prefix, strlen(prefix)) == 0; 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 /// @brief duplicates a string, without using a memory zone
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -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); 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 /// @brief duplicates a string, without using a memory zone
/// ///

View File

@ -140,6 +140,10 @@ namespace triagens {
this->_bodyLength = 0; this->_bodyLength = 0;
this->_readRequestBody = false; this->_readRequestBody = false;
this->_requestPending = 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; return true;
} }
// check HTTP protocol // check HTTP protocol version
if (! this->_request->isHttp10() && ! this->_request->isHttp11()) { _httpVersion = this->_request->httpVersion();
if (_httpVersion != HttpRequest::HTTP_1_0 &&
_httpVersion != HttpRequest::HTTP_1_1) {
HttpResponse response(HttpResponse::HTTP_VERSION_NOT_SUPPORTED); HttpResponse response(HttpResponse::HTTP_VERSION_NOT_SUPPORTED);
this->handleResponse(&response); this->handleResponse(&response);
this->resetState(); this->resetState();
@ -233,7 +240,8 @@ namespace triagens {
} }
// check max URL length // 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); HttpResponse response(HttpResponse::REQUEST_URI_TOO_LONG);
this->handleResponse(&response); this->handleResponse(&response);
this->resetState(); 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 // check if server is active
// ............................................................................. // .............................................................................
@ -530,15 +529,13 @@ namespace triagens {
// not authenticated // not authenticated
else { else {
string realm = "basic realm=\"" + this->_server->getHandlerFactory()->authenticationRealm(this->_request) + "\""; const string realm = "basic realm=\"" + this->_server->getHandlerFactory()->authenticationRealm(this->_request) + "\"";
delete this->_request;
this->_request = 0;
HttpResponse response(HttpResponse::UNAUTHORIZED); HttpResponse response(HttpResponse::UNAUTHORIZED);
response.setHeader("www-authenticate", strlen("www-authenticate"), realm.c_str()); response.setHeader("www-authenticate", strlen("www-authenticate"), realm.c_str());
this->handleResponse(&response); this->handleResponse(&response);
this->resetState();
} }
return processRead(); return processRead();
@ -606,6 +603,14 @@ namespace triagens {
LOGGER_TRACE("HTTP WRITE FOR " << static_cast<Task*>(this) << ":\n" << buffer->c_str()); 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 // clear body
response->body().clear(); response->body().clear();
@ -670,12 +675,24 @@ namespace triagens {
private: private:
////////////////////////////////////////////////////////////////////////////////
/// @brief http version number used
////////////////////////////////////////////////////////////////////////////////
HttpRequest::HttpVersion _httpVersion;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief type of request (GET, POST, ...) /// @brief type of request (GET, POST, ...)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
HttpRequest::HttpRequestType _requestType; HttpRequest::HttpRequestType _requestType;
////////////////////////////////////////////////////////////////////////////////
/// @brief value of requested URL
////////////////////////////////////////////////////////////////////////////////
std::string _fullUrl;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief value of the HTTP origin header the client sent (if any). /// @brief value of the HTTP origin header the client sent (if any).
/// this is only used for CORS /// this is only used for CORS

View File

@ -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"; 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 /// @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) { static void OutputMachine (string const& text, LoggerData::Info const& info) {
char const* format = LoggerFormat.c_str(); char const* format;
char const* end = format + LoggerFormat.size(); 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); time_t tt = time(0);
StringBuffer line(TRI_CORE_MEM_ZONE); StringBuffer line(TRI_CORE_MEM_ZONE);
@ -298,6 +314,7 @@ static void OutputMachine (string const& text, LoggerData::Info const& info) {
switch (info._severity) { switch (info._severity) {
case TRI_LOG_SEVERITY_EXCEPTION: line.appendInteger(2); break; case TRI_LOG_SEVERITY_EXCEPTION: line.appendInteger(2); break;
case TRI_LOG_SEVERITY_FUNCTIONAL: line.appendInteger(5); 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_TECHNICAL: line.appendInteger(6); break;
case TRI_LOG_SEVERITY_DEVELOPMENT: line.appendInteger(7); break; case TRI_LOG_SEVERITY_DEVELOPMENT: line.appendInteger(7); break;
default: 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) { void Logger::output (string const& text, LoggerData::Info const& info) {
// human readable // human readable
if (info._severity == TRI_LOG_SEVERITY_HUMAN) { if (info._severity == TRI_LOG_SEVERITY_HUMAN) {
if (! TRI_IsHumanLogging()) { if (! TRI_IsHumanLogging()) {
@ -547,12 +563,18 @@ void Logger::output (string const& text, LoggerData::Info const& info) {
info._level, info._level,
info._severity, info._severity,
"%s", text.c_str()); "%s", text.c_str());
return;
}
// usage logging
else if (info._severity == TRI_LOG_SEVERITY_USAGE) {
if (! TRI_IsUsageLogging()) {
return;
}
} }
// machine readable logging // machine readable logging
else {
OutputMachine(text, info); OutputMachine(text, info);
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -358,6 +358,31 @@
#endif #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 /// @brief logs non-human messsages
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////