LCOV - code coverage report
Current view: top level - snaplogger - message.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 41 41 100.0 %
Date: 2022-07-01 22:43:09 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2013-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/snaplogger
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             : #pragma once
      20             : 
      21             : /** \file
      22             :  * \brief Handle the message generator.
      23             :  *
      24             :  * This file declares the base message class which is derived from an
      25             :  * std::stringstram. This allows you to use our logger with `<<`
      26             :  * to send anything that the `<<` operator understands to the logs.
      27             :  */
      28             : 
      29             : 
      30             : // self
      31             : //
      32             : #include    "snaplogger/component.h"
      33             : #include    "snaplogger/environment.h"
      34             : #include    "snaplogger/severity.h"
      35             : 
      36             : 
      37             : // libexcept
      38             : //
      39             : #include    <libexcept/exception.h>
      40             : 
      41             : 
      42             : // snapdev
      43             : //
      44             : #include    <snapdev/join_strings.h>
      45             : 
      46             : 
      47             : // C++
      48             : //
      49             : #include    <sstream>
      50             : #include    <streambuf>
      51             : 
      52             : 
      53             : // C
      54             : //
      55             : #include    <sys/time.h>
      56             : 
      57             : 
      58             : 
      59             : namespace snaplogger
      60             : {
      61             : 
      62             : 
      63             : class logger;
      64             : 
      65             : 
      66             : 
      67      152757 : class null_buffer
      68             :     : public std::streambuf
      69             : {
      70             : public:
      71             :     typedef std::unique_ptr<null_buffer>    pointer_t;
      72             : 
      73             :     virtual int         overflow(int c) override;
      74             : };
      75             : 
      76             : 
      77             : enum class system_field_t
      78             : {
      79             :     SYSTEM_FIELD_UNDEFINED = -1,     // used for still undefined system fields
      80             : 
      81             :     SYSTEM_FIELD_MESSAGE,
      82             :     SYSTEM_FIELD_TIMESTAMP,
      83             :     SYSTEM_FIELD_SEVERITY,
      84             :     SYSTEM_FIELD_FILENAME,
      85             :     SYSTEM_FIELD_FUNCTION_NAME,
      86             :     SYSTEM_FIELD_LINE,
      87             : 
      88             :     SYSTEM_FIELD_max
      89             : };
      90             : 
      91             : 
      92             : typedef std::map<std::string, std::string>      field_map_t;
      93             : 
      94             : 
      95             : // the message class is final because the destructor does tricks which
      96             : // would not work right if derived further
      97             : //
      98             : // also we do not offer a shared pointer because we expect the message
      99             : // object to be created and immediately destroyed from the stack
     100             : //
     101             : class message final
     102             :     : public std::basic_stringstream<char>
     103             : {
     104             : public:
     105             :     typedef std::shared_ptr<message>            pointer_t;
     106             : 
     107             :                                 message(
     108             :                                           severity_t sev = default_severity()
     109             :                                         , char const * file = nullptr
     110             :                                         , char const * func = nullptr
     111             :                                         , int line = -1);
     112             :                                 message(std::basic_stringstream<char> const & m, message const & msg);
     113             :                                 message(message const & rhs) = delete;
     114             :     virtual                     ~message();
     115             : 
     116             :     message &                   operator = (message const & rhs) = delete;
     117             : 
     118             :     static severity_t           default_severity();
     119             : 
     120             :     void                        set_severity(severity_t severity);
     121             :     void                        set_filename(std::string const & filename);
     122             :     void                        set_function(std::string const & funcname);
     123             :     void                        set_line(int line);
     124             :     void                        set_recursive_message(bool state) const;
     125             :     void                        set_precise_time();
     126             :     void                        set_timestamp(timespec const & timestamp);
     127             :     bool                        can_add_component(component::pointer_t c) const;
     128             :     void                        add_component(component::pointer_t c);
     129             :     void                        add_field(std::string const & name, std::string const & value);
     130             : 
     131             :     std::shared_ptr<logger>     get_logger() const;
     132             :     severity_t                  get_severity() const;
     133             :     timespec const &            get_timestamp() const;
     134             :     std::string const &         get_filename() const;
     135             :     std::string const &         get_function() const;
     136             :     int                         get_line() const;
     137             :     bool                        get_recursive_message() const;
     138             :     bool                        has_component(component::pointer_t c) const;
     139             :     component::set_t const &    get_components() const;
     140             :     environment::pointer_t      get_environment() const;
     141             :     std::string                 get_message() const;
     142             :     static char const *         get_system_field_name(system_field_t field);
     143             :     static system_field_t       get_system_field_from_name(std::string const & name);
     144             :     std::string                 get_field(std::string const & name) const;
     145             :     field_map_t                 get_fields() const;
     146             : 
     147             : private:
     148             :     std::shared_ptr<logger>     f_logger = std::shared_ptr<logger>(); // make sure it does not go away under our feet
     149             :     timespec                    f_timestamp = timespec();
     150             :     severity_t                  f_severity = severity_t::SEVERITY_INFORMATION;
     151             :     std::string                 f_filename = std::string();
     152             :     std::string                 f_funcname = std::string();
     153             :     int                         f_line = 0;
     154             :     mutable bool                f_recursive_message = false;
     155             :     environment::pointer_t      f_environment = environment::pointer_t();
     156             :     component::set_t            f_components = component::set_t();
     157             :     field_map_t                 f_fields = field_map_t();
     158             :     null_buffer::pointer_t      f_null = null_buffer::pointer_t();
     159             :     std::streambuf *            f_saved_buffer = nullptr;
     160             :     bool                        f_copy = false;
     161             : };
     162             : 
     163             : 
     164             : template<typename CharT, typename Traits>
     165             : inline std::basic_ostream<CharT, Traits> &
     166          14 : operator << (std::basic_ostream<CharT, Traits> & os, section_ptr sec)
     167             : {
     168          14 :     message * m(dynamic_cast<message *>(&os));
     169          14 :     if(m == nullptr)
     170             :     {
     171           7 :         os << "(section:"
     172           7 :            << sec.f_component->get_name()
     173          14 :            << ")";
     174             :     }
     175             :     else
     176             :     {
     177           7 :         m->add_component(sec.f_component);
     178             :     }
     179          14 :     return os;
     180             : }
     181             : 
     182             : 
     183             : template<typename CharT, typename Traits>
     184             : inline std::basic_ostream<CharT, Traits> &
     185           5 : secure(std::basic_ostream<CharT, Traits> & os)
     186             : {
     187           5 :     message * m(dynamic_cast<message *>(&os));
     188           5 :     if(m == nullptr)
     189             :     {
     190           1 :         os << "(section:secure)";
     191             :     }
     192             :     else
     193             :     {
     194           4 :         m->add_component(g_secure_component);
     195             :     }
     196           5 :     return os;
     197             : }
     198             : 
     199             : 
     200             : template<typename CharT, typename Traits>
     201             : inline std::basic_ostream<CharT, Traits> &
     202           1 : precise_time(std::basic_ostream<CharT, Traits> & os)
     203             : {
     204           1 :     message * m(dynamic_cast<message *>(&os));
     205           1 :     if(m != nullptr)
     206             :     {
     207           1 :         m->set_precise_time();
     208             :     }
     209           1 :     return os;
     210             : }
     211             : 
     212             : 
     213             : 
     214           3 : struct field_t
     215             : {
     216             :     std::string             f_name;
     217             :     std::string             f_value;
     218             : };
     219             : 
     220           3 : inline field_t field(std::string const & name, std::string const & value)
     221             : {
     222           3 :     return { name, value };
     223             : }
     224             : 
     225             : template<typename CharT, typename Traits>
     226             : inline std::basic_ostream<CharT, Traits> &
     227           3 : operator << (std::basic_ostream<CharT, Traits> & os, field_t const & f)
     228             : {
     229           3 :     message * m(dynamic_cast<message *>(&os));
     230           3 :     if(m != nullptr)
     231             :     {
     232           3 :         m->add_field(f.f_name, f.f_value);
     233             :     }
     234           3 :     return os;
     235             : }
     236             : 
     237             : 
     238             : 
     239             : 
     240             : 
     241             : message::pointer_t create_message(
     242             :               severity_t sev = ::snaplogger::message::default_severity()
     243             :             , char const * file = nullptr
     244             :             , char const * func = nullptr
     245             :             , int line = -1);
     246             : 
     247             : void send_message(std::basic_ostream<char> & msg);
     248             : 
     249             : void send_stack_trace(libexcept::exception_base_t const & e);
     250             : 
     251             : 
     252             : // TODO: with C++20, change the __FILE__, __LINE__, __func__ with
     253             : //       std::location::current()
     254             : //
     255             : #define SNAP_LOG_FATAL              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_FATAL,             __FILE__, __func__, __LINE__))
     256             : #define SNAP_LOG_EMERG              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_EMERGENCY,         __FILE__, __func__, __LINE__))
     257             : #define SNAP_LOG_EMERGENCY          ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_EMERGENCY,         __FILE__, __func__, __LINE__))
     258             : #define SNAP_LOG_ALERT              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_ALERT,             __FILE__, __func__, __LINE__))
     259             : #define SNAP_LOG_CRIT               ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_CRITICAL,          __FILE__, __func__, __LINE__))
     260             : #define SNAP_LOG_CRITICAL           ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_CRITICAL,          __FILE__, __func__, __LINE__))
     261             : #define SNAP_LOG_EXCEPTION          ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_EXCEPTION,         __FILE__, __func__, __LINE__))
     262             : #define SNAP_LOG_SEVERE             ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_SEVERE,            __FILE__, __func__, __LINE__))
     263             : #define SNAP_LOG_ERR                ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_ERROR,             __FILE__, __func__, __LINE__))
     264             : #define SNAP_LOG_ERROR              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_ERROR,             __FILE__, __func__, __LINE__))
     265             : #define SNAP_LOG_RECOVERABLE_ERROR  ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_RECOVERABLE_ERROR, __FILE__, __func__, __LINE__))
     266             : #define SNAP_LOG_MAJOR              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_MAJOR,             __FILE__, __func__, __LINE__))
     267             : #define SNAP_LOG_WARN               ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_WARNING,           __FILE__, __func__, __LINE__))
     268             : #define SNAP_LOG_WARNING            ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_WARNING,           __FILE__, __func__, __LINE__))
     269             : #define SNAP_LOG_DEPRECATED         ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_DEPRECATED,        __FILE__, __func__, __LINE__))
     270             : #define SNAP_LOG_TODO               ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_TODO,              __FILE__, __func__, __LINE__))
     271             : #define SNAP_LOG_MINOR              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_MINOR,             __FILE__, __func__, __LINE__))
     272             : #define SNAP_LOG_IMPORTANT          ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_IMPORTANT,         __FILE__, __func__, __LINE__))
     273             : #define SNAP_LOG_INFO               ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_INFORMATION,       __FILE__, __func__, __LINE__))
     274             : #define SNAP_LOG_INFORMATION        ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_INFORMATION,       __FILE__, __func__, __LINE__))
     275             : #define SNAP_LOG_CONFIGURATION      ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_CONFIGURATION,     __FILE__, __func__, __LINE__))
     276             : #define SNAP_LOG_CONFIG             ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_CONFIGURATION,     __FILE__, __func__, __LINE__))
     277             : #define SNAP_LOG_VERBOSE            ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_VERBOSE,           __FILE__, __func__, __LINE__))
     278             : #define SNAP_LOG_UNIMPORTANT        ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_UNIMPORTANT,       __FILE__, __func__, __LINE__))
     279             : #define SNAP_LOG_NOTICE             ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_NOTICE,            __FILE__, __func__, __LINE__))
     280             : #define SNAP_LOG_DEBUG              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_DEBUG,             __FILE__, __func__, __LINE__))
     281             : #define SNAP_LOG_NOISY              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_NOISY,             __FILE__, __func__, __LINE__))
     282             : #define SNAP_LOG_TRACE              ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::severity_t::SEVERITY_TRACE,             __FILE__, __func__, __LINE__))
     283             :                                                                                                                                                                                   
     284             : #define SNAP_LOG_DEFAULT            ::snaplogger::send_message(((*::snaplogger::create_message(::snaplogger::message::default_severity(),            __FILE__, __func__, __LINE__))
     285             : 
     286             : #define SNAP_LOG_FIELD(name, value) ::snaplogger::field((name), (value))
     287             : 
     288             : // The (( are in the opening macros
     289             : //
     290             : #define SNAP_LOG_SEND               ""))
     291             : #define SNAP_LOG_SEND_SECURELY      ::snaplogger::secure))
     292             : #define SNAP_LOG_SEND_WITH_STACK_TRACE(e) \
     293             :                                     "")); ::snaplogger::send_stack_trace(e)
     294             : 
     295             : 
     296             : 
     297             : } // snaplogger namespace
     298             : 
     299             : 
     300             : 
     301             : template<typename CharT, typename Traits>
     302             : inline std::basic_ostream<CharT, Traits> &
     303           1 : operator << (std::basic_ostream<CharT, Traits> & os, std::stringstream const & ss)
     304             : {
     305           1 :     return os << ss.str();
     306             : }
     307             : 
     308             : 
     309             : 
     310             : template<typename CharT, typename Traits>
     311             : inline std::basic_ostream<CharT, Traits> &
     312           1 : operator << (std::basic_ostream<CharT, Traits> & os, std::exception const & e)
     313             : {
     314           1 :     snaplogger::message * m(dynamic_cast<snaplogger::message *>(&os));
     315           1 :     if(m != nullptr)
     316             :     {
     317           1 :         m->add_field("exception_message", e.what());
     318             : 
     319           1 :         libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&e));
     320           1 :         if(b != nullptr)
     321             :         {
     322           1 :             m->add_field("exception_stacktrace", snapdev::join_strings(b->get_stack_trace(), "\n") + "\n");
     323             : 
     324           1 :             libexcept::parameter_t const & params(b->get_parameters());
     325           2 :             for(auto const & p : params)
     326             :             {
     327           1 :                 m->add_field("exception_" + p.first, p.second);
     328             :             }
     329             :         }
     330             :     }
     331             : 
     332           1 :     return os << e.what();
     333             : }
     334             : 
     335             : 
     336             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13