mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-28 03:20:11 +01:00
initial import
This commit is contained in:
416
Foundation/src/Logger.cpp
Normal file
416
Foundation/src/Logger.cpp
Normal file
@@ -0,0 +1,416 @@
|
||||
//
|
||||
// Logger.cpp
|
||||
//
|
||||
// $Id: //poco/1.1.0/Foundation/src/Logger.cpp#2 $
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Logging
|
||||
// Module: Logger
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Foundation/Logger.h"
|
||||
#include "Foundation/Formatter.h"
|
||||
#include "Foundation/LoggingRegistry.h"
|
||||
#include "Foundation/Exception.h"
|
||||
#include "Foundation/NumberFormatter.h"
|
||||
|
||||
|
||||
Foundation_BEGIN
|
||||
|
||||
|
||||
Logger::LoggerMap* Logger::_pLoggerMap = 0;
|
||||
Mutex Logger::_mapMtx;
|
||||
|
||||
|
||||
Logger::Logger(const std::string& name, Channel* pChannel, int level): _name(name), _pChannel(pChannel), _level(level)
|
||||
{
|
||||
if (pChannel) pChannel->duplicate();
|
||||
}
|
||||
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
if (_pChannel) _pChannel->release();
|
||||
}
|
||||
|
||||
|
||||
void Logger::setChannel(Channel* pChannel)
|
||||
{
|
||||
if (_pChannel) _pChannel->release();
|
||||
_pChannel = pChannel;
|
||||
if (_pChannel) _pChannel->duplicate();
|
||||
}
|
||||
|
||||
|
||||
Channel* Logger::getChannel() const
|
||||
{
|
||||
return _pChannel;
|
||||
}
|
||||
|
||||
|
||||
void Logger::setLevel(int level)
|
||||
{
|
||||
_level = level;
|
||||
}
|
||||
|
||||
|
||||
void Logger::setLevel(const std::string& level)
|
||||
{
|
||||
if (level == "fatal")
|
||||
setLevel(Message::PRIO_FATAL);
|
||||
else if (level == "critical")
|
||||
setLevel(Message::PRIO_CRITICAL);
|
||||
else if (level == "error")
|
||||
setLevel(Message::PRIO_ERROR);
|
||||
else if (level == "warning")
|
||||
setLevel(Message::PRIO_WARNING);
|
||||
else if (level == "notice")
|
||||
setLevel(Message::PRIO_NOTICE);
|
||||
else if (level == "information")
|
||||
setLevel(Message::PRIO_INFORMATION);
|
||||
else if (level == "debug")
|
||||
setLevel(Message::PRIO_DEBUG);
|
||||
else if (level == "trace")
|
||||
setLevel(Message::PRIO_TRACE);
|
||||
else
|
||||
throw InvalidArgumentException("Not a valid log level", level);
|
||||
}
|
||||
|
||||
|
||||
void Logger::setProperty(const std::string& name, const std::string& value)
|
||||
{
|
||||
if (name == "channel")
|
||||
setChannel(LoggingRegistry::defaultRegistry().channelForName(value));
|
||||
else if (name == "level")
|
||||
setLevel(value);
|
||||
else
|
||||
Channel::setProperty(name, value);
|
||||
}
|
||||
|
||||
|
||||
void Logger::log(const Message& msg)
|
||||
{
|
||||
if (_level >= msg.getPriority() && _pChannel)
|
||||
{
|
||||
_pChannel->log(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Logger::log(const Exception& exc)
|
||||
{
|
||||
error(exc.displayText());
|
||||
}
|
||||
|
||||
|
||||
void Logger::dump(const std::string& msg, const void* buffer, int length, Message::Priority prio)
|
||||
{
|
||||
if (_level >= prio && _pChannel)
|
||||
{
|
||||
std::string text(msg);
|
||||
formatDump(text, buffer, length);
|
||||
_pChannel->log(Message(_name, text, prio));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Logger::setLevel(const std::string& name, int level)
|
||||
{
|
||||
Mutex::ScopedLock lock(_mapMtx);
|
||||
|
||||
if (_pLoggerMap)
|
||||
{
|
||||
std::string::size_type len = name.length();
|
||||
for (LoggerMap::iterator it = _pLoggerMap->begin(); it != _pLoggerMap->end(); ++it)
|
||||
{
|
||||
if (len == 0 || it->first.compare(0, len, name) == 0 && (it->first.length() == len || it->first[len] == '.'))
|
||||
it->second->setLevel(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Logger::setChannel(const std::string& name, Channel* pChannel)
|
||||
{
|
||||
Mutex::ScopedLock lock(_mapMtx);
|
||||
|
||||
if (_pLoggerMap)
|
||||
{
|
||||
std::string::size_type len = name.length();
|
||||
for (LoggerMap::iterator it = _pLoggerMap->begin(); it != _pLoggerMap->end(); ++it)
|
||||
{
|
||||
if (len == 0 || it->first.compare(0, len, name) == 0 && (it->first.length() == len || it->first[len] == '.'))
|
||||
it->second->setChannel(pChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string Logger::format(const std::string& fmt, const std::string& arg)
|
||||
{
|
||||
std::string args[] =
|
||||
{
|
||||
arg
|
||||
};
|
||||
return format(fmt, 1, args);
|
||||
}
|
||||
|
||||
|
||||
std::string Logger::format(const std::string& fmt, const std::string& arg0, const std::string& arg1)
|
||||
{
|
||||
std::string args[] =
|
||||
{
|
||||
arg0,
|
||||
arg1
|
||||
};
|
||||
return format(fmt, 2, args);
|
||||
}
|
||||
|
||||
|
||||
std::string Logger::format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2)
|
||||
{
|
||||
std::string args[] =
|
||||
{
|
||||
arg0,
|
||||
arg1,
|
||||
arg2
|
||||
};
|
||||
return format(fmt, 3, args);
|
||||
}
|
||||
|
||||
|
||||
std::string Logger::format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2, const std::string& arg3)
|
||||
{
|
||||
std::string args[] =
|
||||
{
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3
|
||||
};
|
||||
return format(fmt, 4, args);
|
||||
}
|
||||
|
||||
|
||||
std::string Logger::format(const std::string& fmt, int argc, std::string argv[])
|
||||
{
|
||||
std::string result;
|
||||
std::string::const_iterator it = fmt.begin();
|
||||
while (it != fmt.end())
|
||||
{
|
||||
if (*it == '$')
|
||||
{
|
||||
++it;
|
||||
if (*it == '$')
|
||||
{
|
||||
result += '$';
|
||||
}
|
||||
else if (*it >= '0' && *it <= '9')
|
||||
{
|
||||
int i = *it - '0';
|
||||
if (i < argc)
|
||||
result += argv[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
result += '$';
|
||||
result += *it;
|
||||
}
|
||||
}
|
||||
else result += *it;
|
||||
++it;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Logger::formatDump(std::string& message, const void* buffer, int length)
|
||||
{
|
||||
const int BYTES_PER_LINE = 16;
|
||||
|
||||
message.reserve(message.size() + length*6);
|
||||
if (!message.empty()) message.append("\n");
|
||||
unsigned char* base = (unsigned char*) buffer;
|
||||
int addr = 0;
|
||||
while (addr < length)
|
||||
{
|
||||
if (addr > 0) message.append("\n");
|
||||
message.append(NumberFormatter::formatHex(addr, 4));
|
||||
message.append(" ");
|
||||
int offset = 0;
|
||||
while (addr + offset < length && offset < BYTES_PER_LINE)
|
||||
{
|
||||
message.append(NumberFormatter::formatHex(base[addr + offset], 2));
|
||||
message.append(offset == 7 ? " " : " ");
|
||||
++offset;
|
||||
}
|
||||
if (offset < 7) message.append(" ");
|
||||
while (offset < BYTES_PER_LINE) { message.append(" "); ++offset; }
|
||||
message.append(" ");
|
||||
offset = 0;
|
||||
while (addr + offset < length && offset < BYTES_PER_LINE)
|
||||
{
|
||||
unsigned char c = base[addr + offset];
|
||||
message += (c >= 32 && c < 127) ? (char) c : '.';
|
||||
++offset;
|
||||
}
|
||||
addr += BYTES_PER_LINE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Logger& Logger::get(const std::string& name)
|
||||
{
|
||||
Mutex::ScopedLock lock(_mapMtx);
|
||||
|
||||
Logger* pLogger = has(name);
|
||||
if (!pLogger)
|
||||
{
|
||||
Logger& par = parent(name);
|
||||
pLogger = new Logger(name, par.getChannel(), par.getLevel());
|
||||
add(pLogger);
|
||||
}
|
||||
return *pLogger;
|
||||
}
|
||||
|
||||
|
||||
Logger& Logger::create(const std::string& name, Channel* pChannel, int level)
|
||||
{
|
||||
Mutex::ScopedLock lock(_mapMtx);
|
||||
|
||||
if (has(name)) throw ExistsException();
|
||||
Logger* pLogger = new Logger(name, pChannel, level);
|
||||
add(pLogger);
|
||||
return *pLogger;
|
||||
}
|
||||
|
||||
|
||||
Logger& Logger::root()
|
||||
{
|
||||
Mutex::ScopedLock lock(_mapMtx);
|
||||
|
||||
Logger* pRoot = has("");
|
||||
if (!pRoot)
|
||||
{
|
||||
pRoot = new Logger("", 0, Message::PRIO_INFORMATION);
|
||||
add(pRoot);
|
||||
}
|
||||
return *pRoot;
|
||||
}
|
||||
|
||||
|
||||
Logger* Logger::has(const std::string& name)
|
||||
{
|
||||
Mutex::ScopedLock lock(_mapMtx);
|
||||
|
||||
if (_pLoggerMap)
|
||||
{
|
||||
LoggerMap::iterator it = _pLoggerMap->find(name);
|
||||
if (it != _pLoggerMap->end())
|
||||
return it->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Logger::shutdown()
|
||||
{
|
||||
Mutex::ScopedLock lock(_mapMtx);
|
||||
|
||||
if (_pLoggerMap)
|
||||
{
|
||||
for (LoggerMap::iterator it = _pLoggerMap->begin(); it != _pLoggerMap->end(); ++it)
|
||||
{
|
||||
it->second->release();
|
||||
}
|
||||
delete _pLoggerMap;
|
||||
_pLoggerMap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Logger::destroy(const std::string& name)
|
||||
{
|
||||
Mutex::ScopedLock lock(_mapMtx);
|
||||
|
||||
if (_pLoggerMap)
|
||||
{
|
||||
LoggerMap::iterator it = _pLoggerMap->find(name);
|
||||
if (it != _pLoggerMap->end())
|
||||
{
|
||||
it->second->release();
|
||||
_pLoggerMap->erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Logger& Logger::parent(const std::string& name)
|
||||
{
|
||||
std::string::size_type pos = name.rfind('.');
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
std::string pname = name.substr(0, pos);
|
||||
Logger* pParent = has(pname);
|
||||
if (pParent)
|
||||
return *pParent;
|
||||
else
|
||||
return parent(pname);
|
||||
}
|
||||
else
|
||||
{
|
||||
return root();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AutoLoggerShutdown
|
||||
{
|
||||
public:
|
||||
AutoLoggerShutdown()
|
||||
{
|
||||
}
|
||||
~AutoLoggerShutdown()
|
||||
{
|
||||
Logger::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Logger::add(Logger* pLogger)
|
||||
{
|
||||
static AutoLoggerShutdown als;
|
||||
|
||||
if (!_pLoggerMap)
|
||||
_pLoggerMap = new LoggerMap;
|
||||
_pLoggerMap->insert(LoggerMap::value_type(pLogger->name(), pLogger));
|
||||
}
|
||||
|
||||
|
||||
Foundation_END
|
||||
Reference in New Issue
Block a user