This is an automated email from the git hooks/post-receive script. hmmr-guest pushed a commit to branch WIP in repository aghermann.
commit 6dfde50f6a9046e823fc5d4b09ecdce7dcc7043f Author: Andrei Zavada <[email protected]> Date: Sun Sep 29 02:35:16 2013 +0300 log-facility is here --- upstream/src/aghermann/globals.cc | 30 ++++- upstream/src/aghermann/globals.hh | 9 ++ upstream/src/common/Makefile.am | 2 + upstream/src/common/libcommon.cc | 50 ++++---- upstream/src/common/log-facility.cc | 215 +++++++++++++++++------------------ upstream/src/common/log-facility.hh | 93 +++++++-------- upstream/src/common/string.hh | 6 +- 7 files changed, 224 insertions(+), 181 deletions(-) diff --git a/upstream/src/aghermann/globals.cc b/upstream/src/aghermann/globals.cc index 3da9cfe..514dae4 100644 --- a/upstream/src/aghermann/globals.cc +++ b/upstream/src/aghermann/globals.cc @@ -10,6 +10,8 @@ */ +#include <cstdarg> +#include <cassert> #include <sys/time.h> #include <gsl/gsl_rng.h> @@ -25,6 +27,8 @@ #endif using namespace std; +using namespace agh::global; + gsl_rng *agh::global::rng = nullptr; @@ -51,9 +55,14 @@ init() #ifdef _OPENMP // 2. omp { - agh::global::num_procs = omp_get_max_threads(); + num_procs = omp_get_max_threads(); } #endif + + // 3. log facility + { + default_log_facility = new agh::log::CLogFacility ("-"); + } } @@ -63,8 +72,27 @@ fini() { gsl_rng_free( rng); rng = nullptr; + delete default_log_facility; + default_log_facility = nullptr; +} + + + +agh::log::CLogFacility* agh::global::default_log_facility; + +void +agh::global:: +log( agh::log::TLevel level, const char* issuer, const char* fmt, ...) +{ + assert (default_log_facility); + va_list ap; + va_start (ap, fmt); + default_log_facility -> vmsg( level, issuer, fmt, ap); + va_end (ap); } + + // Local Variables: // Mode: c++ // indent-tabs-mode: nil diff --git a/upstream/src/aghermann/globals.hh b/upstream/src/aghermann/globals.hh index da937bd..f0f5f52 100644 --- a/upstream/src/aghermann/globals.hh +++ b/upstream/src/aghermann/globals.hh @@ -13,6 +13,7 @@ #define AGH_AGHERMANN_GLOBALS_H_ #include <gsl/gsl_rng.h> +#include "common/log-facility.hh" #if HAVE_CONFIG_H && !defined(VERSION) # include "config.h" @@ -27,6 +28,14 @@ extern gsl_rng *rng; extern int num_procs; +extern agh::log::CLogFacility* default_log_facility; +void log( agh::log::TLevel, const char* issuer, const char* fmt, ...) __attribute__ ((format (printf, 3, 4))); + +#define LOG_DEBUG(...) do agh::global::log( agh::log::TLevel::debug, agh::str::sasprintf("%s:%zu", __FILE__, __LINE__).c_str(), __VA_ARGS__); while (0) +#define LOG_INFO(...) do agh::global::log( agh::log::TLevel::info, agh::str::sasprintf("%s:%zu", __FILE__, __LINE__).c_str(), __VA_ARGS__); while (0) +#define LOG_WARN(...) do agh::global::log( agh::log::TLevel::warning, agh::str::sasprintf("%s:%zu", __FILE__, __LINE__).c_str(), __VA_ARGS__); while (0) +#define LOG_ERROR(...) do agh::global::log( agh::log::TLevel::error, agh::str::sasprintf("%s:%zu", __FILE__, __LINE__).c_str(), __VA_ARGS__); while (0) + void init(); void fini(); diff --git a/upstream/src/common/Makefile.am b/upstream/src/common/Makefile.am index 7a24aec..db60389 100644 --- a/upstream/src/common/Makefile.am +++ b/upstream/src/common/Makefile.am @@ -13,5 +13,7 @@ liba_a_SOURCES := \ lang.hh \ libcommon.cc \ string.hh \ + log-facility.cc \ + log-facility.hh \ subject_id.cc \ subject_id.hh diff --git a/upstream/src/common/libcommon.cc b/upstream/src/common/libcommon.cc index 43a3649..c11719a 100644 --- a/upstream/src/common/libcommon.cc +++ b/upstream/src/common/libcommon.cc @@ -33,6 +33,37 @@ using namespace std; +string +agh::str:: +svasprintf( const char* fmt, va_list ap) +{ + char *_; + if (vasprintf( &_, fmt, ap) <= 0) + abort(); + string ret {_}; + free( (void*)_); + return move(ret); +} + + + +string +agh::str:: +sasprintf( const char* fmt, ...) +{ + char *_; + va_list ap; + va_start (ap, fmt); + if (vasprintf( &_, fmt, ap) <= 0) + abort(); + va_end (ap); + + string ret {_}; + free( (void*)_); + return move(ret); +} + + string agh::str:: @@ -60,25 +91,6 @@ pad( const string& r0, size_t to) - -string -agh::str:: -sasprintf( const char* fmt, ...) -{ - char *_; - va_list ap; - va_start (ap, fmt); - if (vasprintf( &_, fmt, ap) <= 0) - abort(); - va_end (ap); - - string ret {_}; - free( (void*)_); - return move(ret); -} - - - list<string> agh::str:: tokens_trimmed( const string& s_, const char* sep) diff --git a/upstream/src/common/log-facility.cc b/upstream/src/common/log-facility.cc index be7fc86..0339e19 100644 --- a/upstream/src/common/log-facility.cc +++ b/upstream/src/common/log-facility.cc @@ -1,145 +1,142 @@ /* - * Author: Andrei Zavada <[email protected]> + * File name: common/log-facility.cc + * Project: Aghermann + * Author: Andrei Zavada <[email protected]> + * Initial version: 2009-06-28 (in aghermann since 2013-09-28) * - * License: GPL-2+ - * - * Initial version: 2009-06-28 + * Purpose: Simple log facility * + * License: GPL */ #include <sys/time.h> #include <cstdarg> #include <cstring> #include <cmath> -#include <fstream> +#include <stdexcept> +#include <gsl/gsl_math.h> +#include "string.hh" -#include "config.h" +#if HAVE_CONFIG_H && !defined(VERSION) +# include "config.h" +#endif #include "log-facility.hh" using namespace std; +using namespace agh::log; -Stilton::CLogFacility:: -CLogFacility( const char *log_fname, - int inlog_threshold, - int instdout_tee_threshold, - unsigned short insec_dec_place, - int bits, - size_t buf_size) - : status (bits), - log_threshold (inlog_threshold), - stdout_tee_threshold (instdout_tee_threshold), - sec_dec_places (insec_dec_place) -{ - _line_buf = new char[_buf_size = buf_size]; - if ( log_fname && strlen(log_fname) ) { - _log_fname = string(log_fname); - _log_strm.open( log_fname); - unitbuf( _log_strm); - } -} - -Stilton::CLogFacility:: -~CLogFacility() +const char* +agh::log:: +level_s( TLevel l) { - if ( _log_fname.size() ) - _log_strm.close(); - delete[] _line_buf; + switch (l) { + case TLevel::debug : return "DEBUG"; + case TLevel::info : return "INFO"; + case TLevel::warning: return "WARN"; + case TLevel::error : return "ERROR"; + case TLevel::self : return "info"; + default: return "eh?"; + } } -void -Stilton::CLogFacility:: -msg( int vrb, const char *client_name, const char* fmt, ...) +CLogFacility:: +CLogFacility( const string& log_fname, + TLevel level_, bool compact_repeated_messages_, + unsigned short sec_dec_places_) + : level (level_), + compact_repeated_messages (compact_repeated_messages_), + sec_dec_places (sec_dec_places_), + _repeating_last (0) { - va_list ap; - va_start (ap, fmt); - msgv( vrb, client_name, fmt, ap); - va_end (ap); + if ( sec_dec_places > 8 ) + throw invalid_argument ("Seconds decimal places too big (>8)"); + if ( log_fname == "-" ) + _f = stdout; + else if ( !(_f = fopen( log_fname.c_str(), "w")) ) + throw runtime_error ("Failed to open log file for writing"); + msg( level, "log-facility", "init"); } - -void -Stilton::CLogFacility:: -msgv( int vrb, const char *client_name, const char* fmt, va_list ap) +CLogFacility:: +~CLogFacility() { -// if ( status & STILTON_LOG_NOLOCK ) -// boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> L( _log_lock); - - if ( log_threshold < vrb && stdout_tee_threshold < vrb ) - return; - - char timestampbuf[32]; - time_t timestamp; time( ×tamp); - struct timeval tp; gettimeofday( &tp, nullptr); - strftime( timestampbuf, 31, "%F %T", localtime( ×tamp)); - char secfracbuf[sec_dec_places+3]; - snprintf( secfracbuf, sec_dec_places+2, ".%0*u", sec_dec_places, - (unsigned)round( tp.tv_usec / pow( 10., 6-sec_dec_places-1))); - - vsnprintf( _line_buf, _buf_size, fmt, ap); - - char *line = strtok( _line_buf, "\n"); - do { - if ( vrb < 0 ) - printf( "%s%sError: %s\n", client_name ? client_name : "", (client_name && strlen(client_name)) ? ": " : "", line); - else if ( stdout_tee_threshold >= vrb ) - printf( "%s%s%s\n", client_name ? client_name : "", (client_name && strlen(client_name)) ? ": " : "", line); - - if ( log_threshold >= vrb && _log_fname.size() ) - _log_strm << timestampbuf << (sec_dec_places > 0 ? secfracbuf : "") << ' ' - << client_name << ": " - << (vrb < 0 ? "Error: " : "") << line << endl; - } while ( (line = strtok( nullptr, "\n")) ); - - if ( _log_fname.size() ) - _log_strm.flush(); + msg( level, "log-facility", "closing"); // will cause any withheld "above message repeated" message to be printed + if ( _f != stdout ) + fclose(_f); } -// a one-liner, possibly unterminated by \n void -Stilton::CLogFacility:: -msg_( int vrb, const char *client_name, const char* fmt, ...) +CLogFacility:: +msg( TLevel this_level, const char *issuer, const char* fmt, ...) { - va_list ap; - va_start (ap, fmt); - msgv_( vrb, client_name, fmt, ap); - va_end (ap); + va_list ap; + va_start (ap, fmt); + vmsg( this_level, issuer, fmt, ap); + va_end (ap); } + void -Stilton::CLogFacility:: -msgv_( int vrb, const char *client_name, const char* fmt, va_list ap) +CLogFacility:: +vmsg( TLevel this_level, const char *issuer, const char* fmt, va_list ap) { -// if ( status & STILTON_LOG_NOLOCK ) -// boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> L( _log_lock); - - if ( log_threshold < vrb && stdout_tee_threshold < vrb ) - return; - - char timestampbuf[32]; - time_t timestamp; time( ×tamp); - struct timeval tp; gettimeofday( &tp, nullptr); - strftime( timestampbuf, 31, "%F %T", localtime( ×tamp)); - char secfracbuf[sec_dec_places+3]; - snprintf( secfracbuf, sec_dec_places+2, ".%0*u", sec_dec_places, - (unsigned)round( tp.tv_usec / pow( 10., 6-sec_dec_places-1))); - - vsnprintf( _line_buf, _buf_size, fmt, ap); - - if ( vrb < 0 ) - printf( "%s%sError: %s", client_name ? client_name : "", (client_name && strlen(client_name)) ? ": " : "", _line_buf); - else if ( stdout_tee_threshold >= vrb ) - printf( "%s%s%s", client_name ? client_name : "", (client_name && strlen(client_name)) ? ": " : "", _line_buf); - - if ( log_threshold >= vrb && _log_fname.size() ) - _log_strm << timestampbuf << (sec_dec_places > 0 ? secfracbuf : "") << ' ' - << client_name << ": " - << (vrb < 0 ? "Error: " : "") << _line_buf << endl; + if ( level > this_level && this_level != TLevel::self ) + return; + + char timestampbuf[32 + 8 + 3]; + { + struct timeval tp; + gettimeofday( &tp, nullptr); + _last_tp = tp; + size_t n = strftime( timestampbuf, 31, "%F %T", localtime( &tp.tv_sec)); + snprintf( timestampbuf+n, sec_dec_places+2, ".%0*u", sec_dec_places, + (unsigned)round( tp.tv_usec / gsl_pow_int( 10., 6-sec_dec_places-1))); + } + + string the_line = agh::str::svasprintf( fmt, ap); + + // treat multiline message as a series of + if ( compact_repeated_messages && the_line == _last_line ) + ++_repeating_last; // defer printing + else { + if ( _repeating_last ) { + fprintf( _f, "%s (above message repeated %zu time(s))\n", timestampbuf, _repeating_last); + _repeating_last = 0; + } + + // puncturing this_line will incidentally cause any multiline messages to never match _last_line, + // -- but it's just ok, because it avoids confusion as to what exactly "above message" can refer to + char *line = strtok( &the_line[0], "\n"); + string to_print; + size_t mline = 0; + do { + if ( mline > 0 ) + fprintf( _f, + "%s %s %*zu %s\n", + timestampbuf, level_s(this_level), + strlen(issuer), mline, + line); + else + fprintf( _f, + "%s %s %s %s\n", + timestampbuf, level_s(this_level), + issuer, + line); + ++mline; + } while ( (line = strtok( nullptr, "\n")) ); + } + + _last_line = the_line; } - -// eof +// Local Variables: +// Mode: c++ +// indent-tabs-mode: nil +// tab-width: 8 +// c-basic-offset: 8 +// End: diff --git a/upstream/src/common/log-facility.hh b/upstream/src/common/log-facility.hh index e48c807..4188453 100644 --- a/upstream/src/common/log-facility.hh +++ b/upstream/src/common/log-facility.hh @@ -1,75 +1,68 @@ /* - * Author: Andrei Zavada <[email protected]> + * File name: common/log-facility.hh + * Project: Aghermann + * Author: Andrei Zavada <[email protected]> + * Initial version: 2009-06-28 (in aghermann since 2013-09-28) * - * License: GPL-2+ - * - * Initial version: 2009-06-28 + * Purpose: Simple log facility * + * License: GPL */ -#ifndef STILTON_LOG_FACILITY_H -#define STILTON_LOG_FACILITY_H +#ifndef AGH_COMMON_LOG_FACILITY_H +#define AGH_COMMON_LOG_FACILITY_H #include <cstdarg> #include <fstream> -//#include <boost/interprocess/sync/interprocess_mutex.hpp> -//#include <boost/interprocess/sync/interprocess_condition.hpp> - - -namespace Stilton { - using namespace std; -using namespace Stilton; -// bitwise OR this with CLogFacility::status to prevent locking even if supported -#define STILTON_LOG_NOLOCK 1 +namespace agh { +namespace log { + +enum TLevel { + self, // reserved for log-facility itself + error = 1, warning, info, debug +}; +const char* level_s( TLevel); class CLogFacility { public: - CLogFacility( const char *log_fname, - int log_threshold = 4, - int stdout_tee_threshold = 2, - unsigned short sec_dec_places = 2, - int bits = 0, - size_t buf_size = 2048); - - int status; - - int log_threshold, - stdout_tee_threshold; - unsigned short - sec_dec_places; - // full-featured; always terminating lines with a \n - void msg( int vrb, const char *client_name, const char* fmt, ...); - void msgv( int vrb, const char *client_name, const char* fmt, va_list); - // raw output: no parsing, not timestamping each line - void msg_( int vrb, const char *client_name, const char* fmt, ...); - void msgv_( int vrb, const char *client_name, const char* fmt, va_list); - - const char *log_fname() const - { return _log_fname.c_str(); } - size_t buf_size() const - { return _buf_size; } - + CLogFacility( const string& log_fname, // "-" means stdout + TLevel level_ = TLevel::info, // print messages of level up and including this + bool compact_repeated_messages_ = true, + unsigned short sec_dec_places = 2); ~CLogFacility(); + void msg( TLevel, const char* issuer, const char* fmt, ...) __attribute__ ((format (printf, 4, 5))); + void vmsg( TLevel, const char* issuer, const char* fmt, va_list); + + TLevel level; + bool compact_repeated_messages:1; + private: - string _log_fname; - size_t _buf_size; - ofstream - _log_strm; - char - *_line_buf; -// boost::interprocess::interprocess_mutex -// _log_lock; + string _log_fname; + FILE* _f; + unsigned short + sec_dec_places; + + string _last_line; + struct timeval + _last_tp; + size_t _repeating_last; }; +#define LOGHERE() -} +}} // namespace agh::log #endif -// EOF +// Local Variables: +// Mode: c++ +// indent-tabs-mode: nil +// tab-width: 8 +// c-basic-offset: 8 +// End: diff --git a/upstream/src/common/string.hh b/upstream/src/common/string.hh index 3083168..bcd7645 100644 --- a/upstream/src/common/string.hh +++ b/upstream/src/common/string.hh @@ -9,9 +9,10 @@ * License: GPL */ -#ifndef _AGH_COMMON_STRING_H -#define _AGH_COMMON_STRING_H +#ifndef AGH_COMMON_STRING_H_ +#define AGH_COMMON_STRING_H_ +#include <cstdarg> #include <cstring> #include <string> #include <list> @@ -31,6 +32,7 @@ enum class TStrCmpCaseOption { }; string sasprintf( const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); +string svasprintf( const char* fmt, va_list aaa); string trim( const string& r0); string pad( const string& r0, size_t to); -- Alioth's /git/debian-med/git-commit-notice on /srv/git.debian.org/git/debian-med/aghermann.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
