mirror of https://gitee.com/bigwinds/arangodb
566 lines
20 KiB
C++
566 lines
20 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief logger
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Dr. Frank Celler
|
|
/// @author Achim Brandt
|
|
/// @author Copyright 2007-2012, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "Logger.h"
|
|
|
|
#ifdef TRI_ENABLE_SYSLOG
|
|
#define SYSLOG_NAMES
|
|
#include <syslog.h>
|
|
#endif
|
|
|
|
#include <fstream>
|
|
|
|
#include "Basics/Mutex.h"
|
|
#include "Basics/MutexLocker.h"
|
|
#include "Basics/StringBuffer.h"
|
|
#include "Basics/StringUtils.h"
|
|
#include "Basics/Thread.h"
|
|
|
|
using namespace triagens::basics;
|
|
using namespace std;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- public functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Logging
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets the log level
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_SetLogLevelLogging (string const& level) {
|
|
TRI_SetLogLevelLogging(level.c_str());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets the log severity
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_SetLogSeverityLogging (string const& severities) {
|
|
TRI_SetLogSeverityLogging(severities.c_str());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief defines an output prefix
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_SetPrefixLogging (string const& prefix) {
|
|
TRI_SetPrefixLogging(prefix.c_str());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets the file to log for debug and trace
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_SetFileToLog (string const& file) {
|
|
TRI_SetFileToLog(file.c_str());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private variables
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Logging
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief logger format
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static string LoggerFormat = "%Z;1;%S;%C;%H;%p-%t;%F;%A;%f;%m;%K;%f:%l;%x;%P;%u;%V;%U;%E";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief special characters which must be escaped
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static string const SpecialCharacters = ";%\r\t\n";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Logging
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief outputs machine format
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void OutputMachine (string const& text, LoggerData::Info const& info) {
|
|
char const* format = LoggerFormat.c_str();
|
|
char const* end = format + LoggerFormat.size();
|
|
time_t tt = time(0);
|
|
|
|
StringBuffer line(TRI_CORE_MEM_ZONE);
|
|
|
|
for (; format < end; ++format) {
|
|
if (*format == '%') {
|
|
++format;
|
|
|
|
switch (*format) {
|
|
|
|
// .............................................................................
|
|
// end-of-line
|
|
// .............................................................................
|
|
|
|
case '\0':
|
|
--format;
|
|
break;
|
|
|
|
// .............................................................................
|
|
// application name
|
|
// .............................................................................
|
|
|
|
case 'A': {
|
|
line.appendText(info._applicationName._name);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// category
|
|
// .............................................................................
|
|
|
|
case 'C': {
|
|
if (info._severity == TRI_LOG_SEVERITY_FUNCTIONAL && ! info._functional._name.empty()) {
|
|
line.appendText(info._functional._name);
|
|
}
|
|
else {
|
|
switch (info._category) {
|
|
case TRI_LOG_CATEGORY_FATAL: line.appendText("FATAL"); break;
|
|
case TRI_LOG_CATEGORY_ERROR: line.appendText("ERROR"); break;
|
|
case TRI_LOG_CATEGORY_WARNING: { line.appendText("WARNING"); break; }
|
|
case TRI_LOG_CATEGORY_REQUEST_IN_START: line.appendText("REQUEST-IN-START"); break;
|
|
case TRI_LOG_CATEGORY_REQUEST_IN_END: line.appendText("REQUEST-IN-END"); break;
|
|
case TRI_LOG_CATEGORY_REQUEST_OUT_START: line.appendText("REQUEST-OUT-START"); break;
|
|
case TRI_LOG_CATEGORY_REQUEST_OUT_END: line.appendText("REQUEST-OUT-END"); break;
|
|
case TRI_LOG_CATEGORY_HEARTBEAT: line.appendText("HEARTBEAT"); break;
|
|
|
|
case TRI_LOG_CATEGORY_MODULE_IN_START: line.appendText("REQUEST-MODULE-IN-START"); break;
|
|
case TRI_LOG_CATEGORY_MODULE_IN_END: line.appendText("REQUEST-MODULE-IN-END"); break;
|
|
case TRI_LOG_CATEGORY_FUNCTION_IN_START: line.appendText("FUNCTION-IN-START"); break;
|
|
case TRI_LOG_CATEGORY_FUNCTION_IN_END: line.appendText("FUNCTION-IN-END"); break;
|
|
case TRI_LOG_CATEGORY_STEP: line.appendText("STEP"); break;
|
|
case TRI_LOG_CATEGORY_LOOP: line.appendText("LOOP"); break;
|
|
case TRI_LOG_CATEGORY_HEARTPULSE: line.appendText("HEARTPULSE"); break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// extras
|
|
// .............................................................................
|
|
|
|
case 'E': {
|
|
for (vector<LoggerData::Extra>::const_iterator i = info._extras.begin();
|
|
i != info._extras.end();
|
|
++i) {
|
|
if (i != info._extras.begin()) {
|
|
line.appendChar(';');
|
|
}
|
|
|
|
LoggerData::Extra const& extra = *i;
|
|
|
|
line.appendText(StringUtils::escapeHex(extra._name, SpecialCharacters));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// facility
|
|
// .............................................................................
|
|
|
|
case 'F': {
|
|
line.appendText(info._facility._name);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// module name
|
|
// .............................................................................
|
|
|
|
case 'f': {
|
|
line.appendText(info._position._file);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// host name
|
|
// .............................................................................
|
|
|
|
case 'H': {
|
|
line.appendText(info._hostName._name);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// task
|
|
// .............................................................................
|
|
|
|
case 'K': {
|
|
line.appendText(info._task._name);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// line
|
|
// .............................................................................
|
|
|
|
case 'l': {
|
|
line.appendInteger(info._position._line);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// message identifier
|
|
// .............................................................................
|
|
|
|
case 'M': {
|
|
line.appendText(info._messageIdentifier._name);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// method name
|
|
// .............................................................................
|
|
|
|
case 'm': {
|
|
line.appendText(info._position._function);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// process identifier
|
|
// .............................................................................
|
|
|
|
case 'p': {
|
|
line.appendInteger((uint64_t) info._processIdentifier._process);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// peg
|
|
// .............................................................................
|
|
|
|
case 'P': {
|
|
line.appendText(info._peg._name);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// severity
|
|
// .............................................................................
|
|
|
|
case 'S': {
|
|
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_TECHNICAL: line.appendInteger(6); break;
|
|
case TRI_LOG_SEVERITY_DEVELOPMENT: line.appendInteger(7); break;
|
|
default: line.appendInteger(7); break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// pthread identifier
|
|
// .............................................................................
|
|
|
|
case 's': {
|
|
line.appendInteger((uint64_t) info._processIdentifier._threadProcess);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// timestamp
|
|
// .............................................................................
|
|
|
|
case 'T': {
|
|
struct tm tb;
|
|
|
|
TRI_gmtime(tt, &tb);
|
|
|
|
char s[32];
|
|
strftime(s, sizeof(s) - 1, "%Y-%m-%dT%H:%M:%S", &tb);
|
|
|
|
line.appendText(s);
|
|
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// thread identifier
|
|
// .............................................................................
|
|
|
|
case 't': {
|
|
line.appendInteger((uint64_t) info._processIdentifier._thread);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// measure unit
|
|
// .............................................................................
|
|
|
|
case 'U': {
|
|
switch (info._measure._unit) {
|
|
case LoggerData::UNIT_SECONDS: line.appendText("s"); break;
|
|
case LoggerData::UNIT_MILLI_SECONDS: line.appendText("ms"); break;
|
|
case LoggerData::UNIT_MICRO_SECONDS: line.appendText("us"); break;
|
|
case LoggerData::UNIT_NANO_SECONDS: line.appendText("ns"); break;
|
|
|
|
case LoggerData::UNIT_BYTE: line.appendText("b"); break;
|
|
case LoggerData::UNIT_KILO_BYTE: line.appendText("kb"); break;
|
|
case LoggerData::UNIT_MEGA_BYTE: line.appendText("mb"); break;
|
|
case LoggerData::UNIT_GIGA_BYTE: line.appendText("gb"); break;
|
|
|
|
case LoggerData::UNIT_LESS: break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// user identifier
|
|
// .............................................................................
|
|
|
|
case 'u': {
|
|
line.appendText(info._userIdentifier._user);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// measure value
|
|
// .............................................................................
|
|
|
|
case 'V': {
|
|
line.appendDecimal(info._measure._value);
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// text
|
|
// .............................................................................
|
|
|
|
case 'x': {
|
|
if (! info._prefix.empty()) {
|
|
line.appendText(StringUtils::escapeHex(info._prefix, SpecialCharacters));
|
|
}
|
|
|
|
line.appendText(StringUtils::escapeHex(text, SpecialCharacters));
|
|
|
|
break;
|
|
}
|
|
|
|
// .............................................................................
|
|
// timestamp in zulu
|
|
// .............................................................................
|
|
|
|
case 'Z': {
|
|
struct tm tb;
|
|
|
|
TRI_gmtime(tt, &tb);
|
|
|
|
char s[32];
|
|
strftime(s, sizeof(s) - 1, "%Y-%m-%dT%H:%M:%SZ", &tb);
|
|
|
|
line.appendText(s);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
line.appendChar(*format);
|
|
}
|
|
}
|
|
|
|
TRI_RawLog(info._level, info._severity, line.c_str(), line.length() - 1);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- class Logger
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- static variables
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Logging
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief global logger
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Logger Logger::_singleton;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- static public methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Logging
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief changes the application name
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Logger::setApplicationName (string const& name) {
|
|
LoggerData::Info::_applicationName._name = name;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief changes the facility
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Logger::setFacility (string const& name) {
|
|
LoggerData::Info::_facility._name = name;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief changes the host name
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Logger::setHostName (string const& name) {
|
|
LoggerData::Info::_hostName._name = name;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief changes the log format
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Logger::setLogFormat (string const& format) {
|
|
LoggerFormat = format;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Logging
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief constructs a new logger
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Logger::Logger () {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destructs a logger
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Logger::~Logger () {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Logging
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief output text
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Logger::output (string const& text, LoggerData::Info const& info) {
|
|
|
|
// human readable
|
|
if (info._severity == TRI_LOG_SEVERITY_HUMAN) {
|
|
if (! TRI_IsHumanLogging()) {
|
|
return;
|
|
}
|
|
|
|
TRI_Log(info._position._function.c_str(),
|
|
info._position._file.c_str(),
|
|
info._position._line,
|
|
info._level,
|
|
info._severity,
|
|
"%s", text.c_str());
|
|
}
|
|
|
|
// machine readable logging
|
|
else {
|
|
OutputMachine(text, info);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Local Variables:
|
|
// mode: outline-minor
|
|
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
|
// End:
|