Logo Search packages:      
Sourcecode: poco version File versions  Download package

Logger.cpp

//
// Logger.cpp
//
// $Id: //poco/1.2/Foundation/src/Logger.cpp#3 $
//
// 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 "Poco/Logger.h"
#include "Poco/Formatter.h"
#include "Poco/LoggingRegistry.h"
#include "Poco/Exception.h"
#include "Poco/NumberFormatter.h"


namespace Poco {


Logger::LoggerMap* Logger::_pLoggerMap = 0;
Mutex Logger::_mapMtx;
const std::string Logger::ROOT;


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


00064 void Logger::setChannel(Channel* pChannel)
{
      if (_pChannel) _pChannel->release();
      _pChannel = pChannel;
      if (_pChannel) _pChannel->duplicate();
}


00072 Channel* Logger::getChannel() const
{
      return _pChannel;
}


00078 void Logger::setLevel(int level)
{
      _level = level;
}


00084 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);
}


00107 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);
}


00118 void Logger::log(const Message& msg)
{
      if (_level >= msg.getPriority() && _pChannel)
      {
            _pChannel->log(msg);
      }
}


00127 void Logger::log(const Exception& exc)
{
      error(exc.displayText());
}


00133 void Logger::dump(const std::string& msg, const void* buffer, std::size_t length, Message::Priority prio)
{
      if (_level >= prio && _pChannel)
      {
            std::string text(msg);
            formatDump(text, buffer, length);
            _pChannel->log(Message(_name, text, prio));
      }
}


00144 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);
            }
      }
}


00160 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);
            }
      }
}


00176 void Logger::setProperty(const std::string& loggerName, const std::string& propertyName, const std::string& value)
{
      Mutex::ScopedLock lock(_mapMtx);

      if (_pLoggerMap)
      {
            std::string::size_type len = loggerName.length();
            for (LoggerMap::iterator it = _pLoggerMap->begin(); it != _pLoggerMap->end(); ++it)
            {
                  if (len == 0 || it->first.compare(0, len, loggerName) == 0 && (it->first.length() == len || it->first[len] == '.'))
                        it->second->setProperty(propertyName, value);
            }
      }
}


00192 std::string Logger::format(const std::string& fmt, const std::string& arg)
{
      std::string args[] =
      {
            arg
      };
      return format(fmt, 1, args);
}


00202 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);
}


00213 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);
}


00225 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, std::size_t 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;
      }
}


00305 Logger& Logger::get(const std::string& name)
{
      Mutex::ScopedLock lock(_mapMtx);

      return unsafeGet(name);
}


00313 Logger& Logger::unsafeGet(const std::string& name)
{
      Logger* pLogger = find(name);
      if (!pLogger)
      {
            if (name == ROOT)
            {
                  pLogger = new Logger(name, 0, Message::PRIO_INFORMATION);
            }
            else
            {
                  Logger& par = parent(name);
                  pLogger = new Logger(name, par.getChannel(), par.getLevel());
            }
            add(pLogger);
      }
      return *pLogger;
}


00333 Logger& Logger::create(const std::string& name, Channel* pChannel, int level)
{
      Mutex::ScopedLock lock(_mapMtx);

      if (find(name)) throw ExistsException();
      Logger* pLogger = new Logger(name, pChannel, level);
      add(pLogger);
      return *pLogger;
}


00344 Logger& Logger::root()
{
      Mutex::ScopedLock lock(_mapMtx);

      return unsafeGet(ROOT);
}


00352 Logger* Logger::has(const std::string& name)
{
      Mutex::ScopedLock lock(_mapMtx);

      return find(name);
}


00360 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;
      }
}


Logger* Logger::find(const std::string& name)
{
      if (_pLoggerMap)
      {
            LoggerMap::iterator it = _pLoggerMap->find(name);
            if (it != _pLoggerMap->end())
                  return it->second;
      }
      return 0;
}


00388 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);
            }
      }
}


00404 void Logger::names(std::vector<std::string>& names)
{
      Mutex::ScopedLock lock(_mapMtx);

      names.clear();
      if (_pLoggerMap)
      {
            for (LoggerMap::const_iterator it = _pLoggerMap->begin(); it != _pLoggerMap->end(); ++it)
            {
                  names.push_back(it->first);
            }
      }
}


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 = find(pname);
            if (pParent)
                  return *pParent;
            else
                  return parent(pname);
      }
      else return unsafeGet(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));
}


} // namespace Poco

Generated by  Doxygen 1.6.0   Back to index