// -*- c++ -*- //------------------------------------------------------------------------------ // Logger.h //------------------------------------------------------------------------------ // Copyright (c) 2001 by Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ #ifndef LOGGER_H #define LOGGER_H //System headers #include #include #include #include #include using std::string; using std::stack; //ASSA headers #include "assa/Logger_Impl.h" #include "assa/Singleton.h" #include "assa/MemDump.h" namespace ASSA { // @start namespace ASSA /** @file Logger.h An abstraction to message logging facility. */ class Reactor; /****************************************************************************** Class Logger ******************************************************************************/ class Logger : public Singleton { public: Logger () : m_impl (NULL), m_app_name ("zombie") { /* no-op */ } ~Logger () { this->log_close (); } public: /** Set application name. This should be the first call made * to the newly created Logger object. */ void set_app_name (const std::string& appname_) { m_app_name = appname_; } /** Enable logging for group g_. * @param g_ Group to enable */ void enable_group (Group g_); /** Disable logging for group g_. * @param g_ Group to disable */ void disable_group (Group g_); /** Enable logging for groups_. * @param groups_ Groups to enable */ void enable_groups (u_long groups_); /** Disable logging for groups_. * @param groups_ Groups to disable */ void disable_groups (u_long groups_); void enable_all_groups (void); void disable_all_groups (void); bool group_enabled (Group g_) const; /// Add optional timezone: GMT vs. Local void enable_timestamp (void); void disable_timestamp (void); bool timestamp_enabled (void) const; /// 0 - GMT, 1 - LOCAL void set_timezone (int zone); void sign_on (const string& func_name_); void sign_off (void); /** Write log messages to standard output * @return 0 on success, -1 on error with errno set */ int log_open (u_long groups_); /** Write log messages to the logfile @param logfname_ Name of the logfile @param groups_ Logging masks enabled @param maxsize_ Maximum size of the logfile @return 0 on success, -1 on error with errno set */ int log_open (const char* logfname_, u_long groups_, u_long maxsize_); /** Write log messages to the log server assa-logd. @param logsvr_ Address of assa-logd (assalogd@@hostname) @param logfname_ Name of the logfile @param groups_ Logging masks enabled @param maxsize_ Maximum size of the logfile @param reactor_ Pointer to the Reactor to use for communication. @return: 0 on success; -1 on error with errno set */ int log_open (const std::string& logsvr_, const char* logfname_, u_long groups_, u_long maxsize_, Reactor* reactor_); void log_resync (void); int log_close (void); int log_msg (u_long g_, const char* fmt_, ...); int log_func (u_long g_, marker_t type_); private: Logger_Impl* m_impl; /// Logger implementation stack m_context; /// Stack of all contexts std::string m_app_name; /// Application name (+instance number) }; /** @def LOGGER * A shortcut to locate a singleton object of class Logger */ #define LOGGER ASSA::Logger::get_instance() /******************************************************************************* Inline functions *******************************************************************************/ inline void Logger:: enable_group (Group g_) { if (m_impl) { m_impl->enable_group (g_); } } inline void Logger:: disable_group (Group g_) { if (m_impl) { m_impl->disable_group (g_); } } inline void Logger:: enable_groups (u_long g_) { if (m_impl) { m_impl->enable_groups (g_); } } inline void Logger:: disable_groups (u_long g_) { if (m_impl) { m_impl->disable_groups (g_); } } inline bool Logger:: group_enabled (Group g_) const { return (m_impl) ? m_impl->group_enabled (g_) : false; } inline void Logger:: enable_all_groups (void) { if (m_impl) { m_impl->enable_all_groups (); } } inline void Logger:: disable_all_groups (void) { if (m_impl) { m_impl->disable_all_groups (); } } inline void Logger:: enable_timestamp (void) { if (m_impl) { m_impl->enable_timestamp (); } } inline void Logger:: disable_timestamp (void) { if (m_impl) { m_impl->disable_timestamp (); } } inline bool Logger:: timestamp_enabled (void) const { return (m_impl) ? m_impl->timestamp_enabled () : false; } inline void Logger:: set_timezone (int zone_) { if (m_impl) { m_impl->set_timezone (zone_); } } inline void Logger:: log_resync (void) { if (m_impl) { m_impl->log_resync (); } } inline void Logger:: sign_on (const string& func_name_) { m_context.push (func_name_); } inline void Logger:: sign_off (void) { if (!m_context.empty ()) { m_context.pop (); } } /******************************************************************************* Macro definition shortcuts *******************************************************************************/ /** @def DL(X) A macro for writing debug message to the Logger. */ #if defined (ASSA_NLOGGING) # define DL(X) do {} while (0) #else # define DL(X) \ do { \ LOGGER->log_msg X; \ } while (0) #endif /** @def EL(X) A macro for writing error message to the Logger. */ #if defined (ASSA_NLOGGING) # define EL(X) do {} while (0) #else # define EL(X) \ do { \ LOGGER->log_msg X; \ LOGGER->log_msg(ASSA::ASSAERR,"errno: %d \"%s\"\n", errno, strerror(errno)); \ } while (0) #endif /******************************************************************************* Namespace Log provides only the most plausable interface. Other public functions can be reached via LOGGER *******************************************************************************/ namespace Log { // @start namespace Log /** * Set application name. Call this function before any other * to have application name set properly. This is especially * important if you plan to call open_log_server() to send messages * to the log server, assa-logd. */ inline void set_app_name (const std::string& appname_) { LOGGER->set_app_name (appname_); } /** * Open log file. * * @param logfname_ File name * @param groups_ ORed bitmask of logging groups as defined in * assa/LogMask.h. Default is to log all groups. * @param maxsize_ Maximum size log file can reach before renamed to * logfilename_0. Default is 10 megabytes. */ inline int open_log_file (const char* logfname_, u_long groups_ = ALL, u_long maxsize_ = 10485760) { return LOGGER->log_open (logfname_, groups_, maxsize_); } /// Write log message to standard output inline int open_log_stdout (u_long groups_ = ALL) { return LOGGER->log_open (groups_); } /** * Open connection with and write log message to the log server. * * @param logsvraddr_ Address of the logserver, * assa-logd in the form port@@host * @param logfname_ Log file path * @param reactor_ Reactor to use for communications. * @param groups_ ORed bitmask of logging groups as defined in * LogMask.h. Default is to log all groups. * @param maxsize_ Maximum size log file can reach before renamed to * logfilename_0. Default is 10Mb. */ inline int open_log_server (const std::string& logsvraddr_, const char* logfname_, Reactor* reactor_, u_long groups_ = ASSA::ALL, u_long maxsize_ = 10485760) { int ret = LOGGER->log_open (logsvraddr_, logfname_, groups_, maxsize_, reactor_); return ret; } /// Resynchronize logging stream after Fork inline void log_resync (void) { LOGGER->log_resync (); } /// Close logging stream inline int log_close (void) { return LOGGER->log_close (); } /// Set timezone to GMT inline void set_gmt_timezone (void) { LOGGER->set_timezone (0); } /// Enable timestamp logging inline void enable_timestamp (void) { LOGGER->enable_timestamp (); } /// Disable timestamp logging inline void disable_timestamp (void) { LOGGER->disable_timestamp (); } } // @end namespace Log //------------------------------------------------------------------------------ // DiagnosticContext //------------------------------------------------------------------------------ /** Class DiagnosticContext tracks who deep a function is in the calling stack. */ class DiagnosticContext { public: DiagnosticContext (const char* fn_, u_long mask_ = TRACE); ~DiagnosticContext (); private: DiagnosticContext (const DiagnosticContext&); DiagnosticContext& operator= (const DiagnosticContext&); private: const char* m_fname; u_long m_mask; }; inline DiagnosticContext:: DiagnosticContext (const char* fn_, u_long mask_) : m_fname (fn_), m_mask (mask_) { if (LOGGER->group_enabled ((ASSA::Group) m_mask)) { LOGGER->sign_on (m_fname); LOGGER->log_func (m_mask, FUNC_ENTRY); } } inline DiagnosticContext:: ~DiagnosticContext () { if (LOGGER->group_enabled ((ASSA::Group) m_mask)) { LOGGER->log_func (m_mask, FUNC_EXIT); LOGGER->sign_off (); } } /** @def trace(s) trace() is used to trace function call chain in C++ program. trace() logs a message of type [function_name] --v-- with log level TRACE, where 'function_name' is the argument supplied. Upon exiting from the function, record [function_name] --^-- is written to the log file. Application user can easily turn trace on/off by supplying different debug mask with {'-m', '--mask'} command-line argument and masking out highest bit in debug mask: TRACE */ #define trace(s) ASSA::DiagnosticContext tRaCeR(s); /** @def trace_with_mask(s, m) trace_with_mask() is used to trace function call chain in C++ program. Mask is used to limit the scope of the messages. */ #define trace_with_mask(s, m) ASSA::DiagnosticContext tRaCeR(s, m); } // @end namespace ASSA #endif /* LOGGER_H */