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
----
* 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

View File

@ -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}

View File

@ -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"

View File

@ -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);

View File

@ -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;

View File

@ -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")

View File

@ -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

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 (*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);

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

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);
////////////////////////////////////////////////////////////////////////////////
/// @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
///

View File

@ -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

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";
////////////////////////////////////////////////////////////////////////////////
/// @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);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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
////////////////////////////////////////////////////////////////////////////////