Boost logo

Boost :

From: John Torjo (john.lists_at_[hidden])
Date: 2004-04-15 05:26:08


Dear boosters,

I know a while ago there was some interest in a logging library. And of
course, there are so many ways you can do logging, that it was somehow
agreed that a unique logging library can't address them.

However ;), recently I discovered a very easy way to do logging.
Gradually, I've come to this class (shown at the end).

Using it is extremely easy, and it totally decouples what you write from
where it's written.
The idea is to have a function that takes a const std::string&
parameter, and it will be called whenever a new message is logged.
If you want thread-safety, it's just too simple... Just implement it
within your function.

Example:

// log.h
logstream errors_log();
logstream activity_log();

// log.cpp
void do_log( const std::string & msg) { // ... thread-safe writing to cout
    scoped_lock lock(some_static_mutex);
    std::cout << msg; std::cout.flush();
}
logstream errors_log() { return logstream(&do_log) << "[ERROR] "; }
logstream activity_log() { return logstream(&do_log) << "[activity] "; }

// in code
#include "log.h"
activity_log() << "application started (" << ver.major_ver << "." <<
ver.minor_ver << ")" << std::endl;
errors_log() << "too many users" << users << std::endl;
// etc.

Also, I have an idea of how to enable/disable (parts of) logging at
runtime. Same for very easily enabling/disabling logging of different
modules.

Any interest in such a library?

Best,
John

#ifndef LOG_LOGSTREAM_HPP
#define LOG_LOGSTREAM_HPP

#pragma once

// Copyright (c) John Torjo - 2004

#include <iosfwd>
#include <sstream>

namespace log {

// allow finding the prototype for a log function
template<class char_type, class traits = ::std::char_traits<char_type>,
class aloc = ::std::allocator<char_type> >
struct log_func {
    typedef void (*type)(const std::basic_string<char_type,traits,aloc> &);
};

// allow writing to a log
template<class char_type, class traits = ::std::char_traits<char_type>,
class aloc = ::std::allocator<char_type> >
struct basic_logstream {
    typedef typename log_func<char_type,traits,aloc>::type log_func_type;
    typedef ::std::basic_ostringstream<char_type,traits,aloc>
ostring_stream_type;

    explicit basic_logstream( log_func_type func) : m_func(func) {}
    basic_logstream( basic_logstream & other) : m_func(other.m_func) {
        m_buffer << other.m_buffer.str();
        other.m_func = 0;
    }
    ~basic_logstream() {
        if ( m_func)
            m_func( m_buffer.str() );
    }

    template< class T>
    basic_logstream & operator<<( const T & val) {
        m_buffer << val;
        return *this;
    }

    typedef std::ostream & (*ostream_func)(std::ostream & );
    basic_logstream & operator<<( ostream_func f) {
        f( m_buffer);
        return *this;
    }

private:
    ostring_stream_type m_buffer;
    log_func_type m_func;
};

typedef basic_logstream<char> logstream;
typedef basic_logstream<wchar_t> wlogstream;

}

#endif


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk