/* * @project The CERN Tape Archive (CTA) * @copyright Copyright © 2021-2022 CERN * @license This program is free software, distributed under the terms of the GNU General Public * Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can * redistribute it and/or modify it under the terms of the GPL Version 3, or (at your * option) any later version. * * 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 General Public License for more details. * * In applying this licence, CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization or * submit itself to any jurisdiction. */ #pragma once #include "common/log/Constants.hpp" #include "common/log/Param.hpp" // The header file for atomic was is actually called cstdatomic in gcc 4.4 #if __GNUC__ == 4 && (__GNUC_MINOR__ == 4) #include <cstdatomic> #else #include <atomic> #endif #include <list> #include <map> namespace cta::log { /** * Abstract class representing the API of the CTA logging system * * The intended way to use the CTA logging API is as follows: * * 1. Keep a reference to a Logger object, for example: * \code{.cpp} * * class MyClassThatWillLog { * protected: * Logger & m_log; * * public: * MyClassThatWillLog(Logger &log): m_log(log) { * .... * } * } * * \endcode * * 2. To log a message, use the reference to the Logger object like a function. * In other words the Logger object implements operator() and therefore * behaves like a functor: * \code{.cpp} * * void MyClassThatWillLog::aMethodThatWillLog() { * .... * m_log(cta::log::INFO, "My log message"); * .... * } * * \endcode * * The Logger object implements operator() in order to avoid the following long * winded syntax (which does not work by the way, so please do NOT copy and * paste the following example): * \code{.cpp} * * m_log.logMsg(cta::log::INFO, "My log message"); * * \endcode */ class Logger { public: /** * Constructor * * @param hostName The name of the host to be prepended to every log * @param programName The name of the program to be prepended to every log * @param logMask The log mask. * message. */ Logger(std::string_view hostName, std::string_view programName, const int logMask); /** * Destructor. */ virtual ~Logger() = 0; /** * Prepares the logger object for a call to fork(). * * No further calls to operator() should be made after calling this * method until the call to fork() has completed. */ virtual void prepareForFork() = 0; /** * Returns the name of the program. */ const std::string &getProgramName() const; /** * Writes a message into the CTA logging system. Note that no exception * will ever be thrown in case of failure. Failures will actually be * silently ignored in order to not impact the processing. * * Note that this version of operator() implicitly uses the current time as * the time stamp of the message. * * @param priority the priority of the message as defined by the syslog API. * @param msg the message. * @param params optional parameters of the message. */ virtual void operator() (int priority, std::string_view msg, const std::list<Param>& params = std::list<Param>()); /** * Sets the log mask. * * @param logMask The log mask. */ void setLogMask(std::string_view logMask); /** * Sets the log mask. * * @param logMask The log mask. */ void setLogMask(const int logMask); /** * Creates a clean version of the specified string ready for use with syslog. * * @param s The string to be cleaned. * @param replaceUnderscores Set to true if spaces should be replaced by * underscores. * @return A cleaned version of the string. */ static std::string cleanString(const std::string &s, const bool replaceUnderscores); protected: /** * The name of the host to be prepended to every log message. */ const std::string m_hostName; /** * The name of the program to be prepended to every log message. */ const std::string m_programName; /** * Writes the specified msg to the underlying logging system. * * This method is to be implemented by concrete sub-classes of the Logger * class. * * Please note it is the responsibility of a concrete sub-class to decide * whether or not to use the specified log message header. For example, the * SysLogLogger sub-class does not use the header. Instead it relies on * rsyslog to provide a header. * * @param header The header of the message to be logged. It is the * esponsibility of the concrete sub-class * @param body The body of the message to be logged. */ virtual void writeMsgToUnderlyingLoggingSystem(std::string_view header, std::string_view body) = 0; /** * The log mask. */ std::atomic<int> m_logMask; /** * Map from syslog integer priority to textual representation. */ const std::map<int, std::string> m_priorityToText; /** * Map from the possible string values of the LogMask parameters and * their equivalent syslog priorities. */ const std::map<std::string, int> m_configTextToPriority; /** * Generates and returns the mapping between syslog priorities and their * textual representations. */ static std::map<int, std::string> generatePriorityToTextMap(); /** * Generates and returns the mapping between the possible string values * of the LogMask parameters their equivalent syslog priorities. */ static std::map<std::string, int> generateConfigTextToPriorityMap(); private: /** * Creates and returns the header of a log message. * * Concrete subclasses of the Logger class can decide whether or not to use * message headers created by this method. The SysLogger sub-class for example * relies on rsyslog to provide message headers and therefore does not call * this method. * * @param timeStamp The time stamp of the message. * @param hostName The name of the host. * @param programName the program name of the log message. * @param pid The process ID of the process logging the message. * @return The message header. */ static std::string createMsgHeader( const struct timeval &timeStamp, std::string_view hostName, std::string_view programName, const int pid); /** * Creates and returns the body of a log message * * @param msg the message * @param params the parameters of the message * @param rawParams preprocessed parameters of the message * @param programName the program name of the log message * @param pid the pid of the log message * @return the message body */ static std::string createMsgBody(std::string_view priorityText, std::string_view msg, const std::list<Param> ¶ms, std::string_view rawParams, int pid); }; } // namespace cta::log