これは、ある時点で作成したスレッドセーフな行ベースのロギングソリューションです。スレッドセーフのためにブーストミューテックスを使用します。出力ポリシーをプラグインできるため、必要以上に少し複雑です (ファイル、stderr、または他の場所に移動する必要がありますか?)。
ロガー.h:
#ifndef LOGGER_20080723_H_
#define LOGGER_20080723_H_
#include <boost/thread/mutex.hpp>
#include <iostream>
#include <cassert>
#include <sstream>
#include <ctime>
#include <ostream>
namespace logger {
namespace detail {
template<class Ch, class Tr, class A>
class no_output {
private:
struct null_buffer {
template<class T>
null_buffer &operator<<(const T &) {
return *this;
}
};
public:
typedef null_buffer stream_buffer;
public:
void operator()(const stream_buffer &) {
}
};
template<class Ch, class Tr, class A>
class output_to_clog {
public:
typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
public:
void operator()(const stream_buffer &s) {
static boost::mutex mutex;
boost::mutex::scoped_lock lock(mutex);
std::clog << now() << ": " << s.str() << std::endl;
}
private:
static std::string now() {
char buf[64];
const time_t tm = time(0);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tm));
return buf;
}
};
template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
class logger {
typedef OutputPolicy<Ch, Tr, A> output_policy;
public:
~logger() {
output_policy()(m_SS);
}
public:
template<class T>
logger &operator<<(const T &x) {
m_SS << x;
return *this;
}
private:
typename output_policy::stream_buffer m_SS;
};
}
class log : public detail::logger<detail::output_to_clog> {
};
}
#endif
使用法は次のようになります。
logger::log() << "this is a test" << 1234 << "testing";
andは暗黙的であるため、 '\n'
andがないことに注意してください。std::endl
コンテンツはバッファリングされ、テンプレートで指定されたポリシーを使用してアトミックに出力されます。この実装では、ロギング目的であるため、行の前にタイムスタンプも追加されます。ポリシーは完全にオプションです。no_output
ロギングを無効にするときに使用します。