123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- /*
- * Copyright 2005 - 2016 Zarafa and its licensors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- // -*- Mode: c++ -*-
- #ifndef ECLOGGER_H
- #define ECLOGGER_H
- #include <kopano/zcdefs.h>
- #include <kopano/platform.h>
- #include <list>
- #include <mutex>
- #include <pthread.h>
- #include <csignal>
- #include <cstdarg>
- #include <cstdio>
- #include <string>
- #include <kopano/lockhelper.hpp>
- #ifndef __LIKE_PRINTF
- #define __LIKE_PRINTF(_fmt, _va)
- #endif
- namespace KC {
- class ECConfig;
- class ECLogger;
- static const unsigned int EC_LOGLEVEL_NONE = 0;
- static const unsigned int EC_LOGLEVEL_FATAL = 1;
- static const unsigned int EC_LOGLEVEL_CRIT = 1;
- static const unsigned int EC_LOGLEVEL_ERROR = 2;
- static const unsigned int EC_LOGLEVEL_WARNING = 3;
- static const unsigned int EC_LOGLEVEL_NOTICE = 4;
- static const unsigned int EC_LOGLEVEL_INFO = 5;
- static const unsigned int EC_LOGLEVEL_DEBUG = 6;
- static const unsigned int EC_LOGLEVEL_ALWAYS = 0xf;
- static const unsigned int EC_LOGLEVEL_MASK = 0xF;
- // extended log options
- static const unsigned int EC_LOGLEVEL_SQL = 0x00010000;
- static const unsigned int EC_LOGLEVEL_PLUGIN = 0x00020000;
- static const unsigned int EC_LOGLEVEL_CACHE = 0x00040000;
- static const unsigned int EC_LOGLEVEL_USERCACHE = 0x00080000;
- static const unsigned int EC_LOGLEVEL_SOAP = 0x00100000;
- static const unsigned int EC_LOGLEVEL_ICS = 0x00200000;
- static const unsigned int EC_LOGLEVEL_SEARCH = 0x00400000;
- static const unsigned int EC_LOGLEVEL_EXTENDED_MASK = 0xFFFF0000;
- #define _LOG_BUFSIZE 10240
- #define _LOG_TSSIZE 64
- #define ZLOG_DEBUG(_plog, ...) \
- do { \
- if ((_plog)->Log(EC_LOGLEVEL_DEBUG)) \
- (_plog)->Log(EC_LOGLEVEL_DEBUG, __VA_ARGS__); \
- } while (false)
- #define ZLOG_AUDIT(_plog, ...) \
- do { \
- if ((_plog) != NULL) \
- (_plog)->Log(EC_LOGLEVEL_FATAL, __VA_ARGS__); \
- } while (false)
- #ifdef UNICODE
- #define TSTRING_PRINTF "%ls"
- #else
- #define TSTRING_PRINTF "%s"
- #endif
- /**
- * Prefixes in log message in different process models.
- *
- * LP_NONE: No prefix in log message (default)
- * LP_TID: Add thread id as prefix
- * LP_PID: Add linux process id as prefix
- */
- enum logprefix { LP_NONE, LP_TID, LP_PID };
- /**
- * ECLogger object logs messages to a specific
- * destination. Destinations are created in derived classes.
- */
- class _kc_export ECLogger {
- private:
- std::mutex m_mutex;
- unsigned m_ulRef;
- protected:
- /**
- * Returns string with timestamp in current locale.
- */
- _kc_hidden std::string MakeTimestamp(void);
- unsigned int max_loglevel;
- locale_t timelocale;
- locale_t datalocale;
- logprefix prefix;
- /**
- * Constructor of ECLogger. Implementations should open the log they're writing to.
- *
- * @param[in] max_ll Max loglevel allowed to enter in the log. Messages with higher loglevel will be skipped.
- */
- ECLogger(int max_ll);
- /**
- * Destructor of ECLogger. Implementations should close the log they're writing to.
- */
- virtual ~ECLogger();
- public:
- /**
- * Query if a message would be logged under this loglevel
- *
- * @param[in] loglevel Loglevel you want to know if it enters the log.
- * @return bool
- * @retval true Logging with 'loglevel' will enter log
- * @retval false Logging with 'loglevel' will be dropped
- */
- virtual bool Log(unsigned int loglevel);
- /**
- * Set new loglevel for log object
- *
- * @param[in] max_ll The new maximum loglevel
- */
- void SetLoglevel(unsigned int max_ll);
- /**
- * Set new prefix for log
- *
- * @param[in] lp New logprefix LP_TID or LP_PID. Disable prefix with LP_NONE.
- */
- void SetLogprefix(logprefix lp);
- /**
- * Adds reference to this object
- */
- unsigned AddRef();
- /**
- * Removes a reference from this object, and deletes it if all
- * references are removed.
- */
- unsigned Release();
- /**
- * Like the CRT snprintf, but uses the datalocale used by the current
- * ECLogger instance.
- */
- int snprintf(char *str, size_t size, const char *format, ...) __LIKE_PRINTF(4, 5);
- /**
- * Used for log rotation. Implementations should prepare to log in a new log.
- *
- * @param[in] lp New logprefix LP_TID or LP_PID. Disable prefix with LP_NONE.
- */
- virtual void Reset() = 0;
- /**
- * Used to get a direct file descriptor of the log file. Returns
- * -1 if not available.
- *
- * @return int The file descriptor of the logfile being written to.
- */
- _kc_hidden virtual int GetFileDescriptor(void) { return -1; }
- /**
- * Log a message on a specified loglevel using std::string
- *
- * @param loglevel Loglevel to log message under
- * @param message std::string logmessage. Expected charset is current locale.
- */
- _kc_hidden virtual void Log(unsigned int level, const std::string &msg) = 0;
- /**
- * Log a message on a specified loglevel using char* format
- *
- * @param loglevel Loglevel to log message under
- * @param format formatted string for the parameter list
- */
- _kc_hidden virtual void Log(unsigned int level, const char *fmt, ...) __LIKE_PRINTF(3, 4) = 0;
- /**
- * Log a message on a specified loglevel using char* format
- *
- * @param loglevel Loglevel to log message under
- * @param format formatted string for the parameter list
- * @param va va_list converted from ... parameters
- */
- _kc_hidden virtual void LogVA(unsigned int level, const char *fmt, va_list &) = 0;
- };
- /**
- * Dummy null logger, drops every log message.
- */
- class _kc_export ECLogger_Null _kc_final : public ECLogger {
- public:
- ECLogger_Null(void);
- _kc_hidden virtual void Reset(void) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const std::string &msg) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const char *fmt, ...) _kc_override __LIKE_PRINTF(3, 4);
- _kc_hidden virtual void LogVA(unsigned int level, const char *fmt, va_list &) _kc_override;
- };
- /**
- * File logger. Use "-" for stderr logging. Output is in system locale set in LC_CTYPE.
- */
- class _kc_export_dycast ECLogger_File _kc_final : public ECLogger {
- private:
- typedef void* handle_type;
- typedef handle_type(*open_func)(const char*, const char*);
- typedef int(*close_func)(handle_type);
- typedef int(*printf_func)(handle_type, const char*, ...);
- typedef int(*fileno_func)(handle_type);
- typedef int(*flush_func)(handle_type);
- KC::shared_mutex handle_lock, dupfilter_lock;
- handle_type log;
- std::string logname;
- bool timestamp;
- size_t buffer_size;
- open_func fnOpen;
- close_func fnClose;
- printf_func fnPrintf;
- fileno_func fnFileno;
- const char *szMode;
- int prevcount;
- std::string prevmsg;
- unsigned int prevloglevel;
- _kc_hidden bool DupFilter(unsigned int level, const std::string &msg);
- _kc_hidden std::string DoPrefix(void);
- public:
- ECLogger_File(const unsigned int max_ll, const bool add_timestamp, const char *const filename, const bool compress);
- ~ECLogger_File(void);
- _kc_hidden std::string EmitLevel(unsigned int level);
- _kc_hidden void reinit_buffer(size_t size);
- _kc_hidden virtual void Reset(void) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const std::string &msg) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const char *fmt, ...) _kc_override __LIKE_PRINTF(3, 4);
- _kc_hidden virtual void LogVA(unsigned int level, const char *fmt, va_list &) _kc_override;
- _kc_hidden int GetFileDescriptor(void) _kc_override;
- bool IsStdErr();
- private:
- _kc_hidden void init_for_stderr(void);
- _kc_hidden void init_for_file(void);
- _kc_hidden void init_for_gzfile(void);
- };
- /**
- * Linux syslog logger. Output is whatever syslog does, probably LC_CTYPE.
- */
- class _kc_export_dycast ECLogger_Syslog _kc_final : public ECLogger {
- private:
- char *m_ident;
- static const int levelmap[16]; /* converts to syslog levels */
- public:
- ECLogger_Syslog(unsigned int max_ll, const char *ident, int facility);
- ~ECLogger_Syslog(void);
- _kc_hidden virtual void Reset(void) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const std::string &msg) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const char *fmt, ...) _kc_override __LIKE_PRINTF(3, 4);
- _kc_hidden virtual void LogVA(unsigned int level, const char *fmt, va_list &) _kc_override;
- };
- /**
- * Pipe Logger, only used by forked model processes. Redirects every
- * log message to an ECLogger_File object. This ECLogger_Pipe object
- * can be created by StartLoggerProcess function.
- */
- class _kc_export_dycast ECLogger_Pipe _kc_final : public ECLogger {
- private:
- int m_fd;
- pid_t m_childpid;
- public:
- ECLogger_Pipe(int fd, pid_t childpid, int loglevel);
- _kc_hidden ~ECLogger_Pipe(void);
- _kc_hidden virtual void Reset(void) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const std::string &msg) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const char *fmt, ...) _kc_override __LIKE_PRINTF(3, 4);
- _kc_hidden virtual void LogVA(unsigned int level, const char *fmt, va_list &) _kc_override;
- _kc_hidden int GetFileDescriptor(void) _kc_override { return m_fd; }
- void Disown();
- };
- extern _kc_export ECLogger *StartLoggerProcess(ECConfig *, ECLogger *file_logger);
- /**
- * This class can be used if log messages need to go to
- * multiple destinations. It basically distributes
- * the messages to one or more attached ECLogger objects.
- *
- * Each attached logger can have its own loglevel.
- */
- class _kc_export ECLogger_Tee _kc_final : public ECLogger {
- private:
- typedef std::list<ECLogger*> LoggerList;
- LoggerList m_loggers;
- public:
- ECLogger_Tee();
- _kc_hidden ~ECLogger_Tee(void);
- _kc_hidden virtual void Reset(void) _kc_override;
- _kc_hidden virtual bool Log(unsigned int level) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const std::string &msg) _kc_override;
- _kc_hidden virtual void Log(unsigned int level, const char *fmt, ...) _kc_override __LIKE_PRINTF(3, 4);
- _kc_hidden virtual void LogVA(unsigned int level, const char *fmt, va_list &) _kc_override;
- void AddLogger(ECLogger *lpLogger);
- };
- extern _kc_export bool ec_log_has_target(void);
- extern _kc_export ECLogger *ec_log_get(void);
- extern _kc_export void ec_log_set(ECLogger *);
- extern _kc_export void ec_log(unsigned int level, const char *msg, ...) __LIKE_PRINTF(2, 3);
- extern _kc_export void ec_log(unsigned int level, const std::string &msg);
- #define ec_log_always(...) ec_log(EC_LOGLEVEL_ALWAYS, __VA_ARGS__)
- #define ec_log_fatal(...) ec_log(EC_LOGLEVEL_CRIT, __VA_ARGS__)
- #define ec_log_crit(...) ec_log(EC_LOGLEVEL_CRIT, __VA_ARGS__)
- #define ec_log_err(...) ec_log(EC_LOGLEVEL_ERROR, __VA_ARGS__)
- #define ec_log_warn(...) ec_log(EC_LOGLEVEL_WARNING, __VA_ARGS__)
- #define ec_log_notice(...) ec_log(EC_LOGLEVEL_NOTICE, __VA_ARGS__)
- #define ec_log_info(...) ec_log(EC_LOGLEVEL_INFO, __VA_ARGS__)
- #define ec_log_debug(...) ec_log(EC_LOGLEVEL_DEBUG, __VA_ARGS__)
- extern _kc_export ECLogger *CreateLogger(ECConfig *, const char *argv0, const char *service, bool audit = false);
- extern _kc_export int DeleteLogger(ECLogger *);
- extern _kc_export void LogConfigErrors(ECConfig *);
- extern _kc_export void generic_sigsegv_handler(ECLogger *, const char *app, const char *vers, int sig, const siginfo_t *, const void *uctx);
- void ec_log_bt(unsigned int, const char *, ...);
- } /* namespace */
- #endif /* ECLOGGER_H */
|