LCOV - code coverage report
Current view: top level - snaplogger - logger.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 38.5 % 390 150
Test Date: 2025-07-26 11:53:05 Functions: 37.0 % 54 20
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2013-2025  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              : 
      20              : /** \file
      21              :  * \brief Appenders are used to append data to somewhere.
      22              :  *
      23              :  * This file declares the base appender class.
      24              :  */
      25              : 
      26              : // self
      27              : //
      28              : #include    "snaplogger/logger.h"
      29              : 
      30              : #include    "snaplogger/console_appender.h"
      31              : #include    "snaplogger/exception.h"
      32              : #include    "snaplogger/file_appender.h"
      33              : #include    "snaplogger/guard.h"
      34              : #include    "snaplogger/private_logger.h"
      35              : #include    "snaplogger/syslog_appender.h"
      36              : 
      37              : 
      38              : // serverplugins
      39              : //
      40              : #include    <serverplugins/paths.h>
      41              : 
      42              : 
      43              : // last include
      44              : //
      45              : #include    <snapdev/poison.h>
      46              : 
      47              : 
      48              : 
      49              : namespace snaplogger
      50              : {
      51              : 
      52              : 
      53              : namespace
      54              : {
      55              : 
      56              : 
      57              : 
      58              : bool                        g_first_instance = true;
      59              : logger::pointer_t *         g_instance = nullptr;
      60              : std::string                 g_default_plugin_paths = std::string("/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
      61              : 
      62              : 
      63              : struct auto_delete_logger
      64              : {
      65            2 :     ~auto_delete_logger()
      66              :     {
      67            2 :         logger::pointer_t * ptr(nullptr);
      68              :         {
      69            2 :             guard g;
      70            2 :             swap(ptr, g_instance);
      71            2 :         }
      72            2 :         if(ptr != nullptr)
      73              :         {
      74            2 :             (*ptr)->shutdown();
      75            2 :             delete ptr;
      76              :         }
      77            2 :     }
      78              : };
      79              : 
      80              : auto_delete_logger          g_logger_deleter = auto_delete_logger();
      81              : 
      82              : 
      83              : 
      84              : }
      85              : // no name namespace
      86              : 
      87              : 
      88              : 
      89            2 : logger::logger()
      90           10 :     : server(serverplugins::get_id("logger"))
      91              : {
      92            2 : }
      93              : 
      94              : 
      95            1 : logger::~logger()
      96              : {
      97            1 : }
      98              : 
      99              : 
     100       274764 : logger::pointer_t logger::get_instance()
     101              : {
     102       274764 :     guard g;
     103              : 
     104       274764 :     if(g_instance == nullptr)
     105              :     {
     106            2 :         if(!g_first_instance)
     107              :         {
     108            0 :             throw duplicate_error("preventing an attempt of re-creating the snap logger.");
     109              :         }
     110              : 
     111            2 :         g_first_instance = false;
     112              : 
     113              :         // note that we create a `private_logger` object
     114              :         //
     115            2 :         g_instance = new logger::pointer_t();
     116            2 :         g_instance->reset(new private_logger());
     117              :     }
     118              : 
     119       549528 :     return *g_instance;
     120       274764 : }
     121              : 
     122              : 
     123              : /** \brief Reset the logger to its startup state.
     124              :  *
     125              :  * This function resets the logger to non-asynchronous and no appenders.
     126              :  *
     127              :  * This is mainly used in our unit tests so we do not have to run the
     128              :  * tests one at a time. It should nearly never be useful in your environment
     129              :  * except if you do a fork() and wanted the child to have its own special
     130              :  * log environment.
     131              :  */
     132           16 : void logger::reset()
     133              : {
     134           16 :     guard g;
     135              : 
     136           16 :     set_asynchronous(false);
     137           16 :     f_appenders.clear();
     138           16 :     f_lowest_severity = severity_t::SEVERITY_OFF;
     139           32 : }
     140              : 
     141              : 
     142            0 : void logger::shutdown()
     143              : {
     144            0 : }
     145              : 
     146              : 
     147            1 : std::string const & logger::default_plugin_paths()
     148              : {
     149            1 :     return g_default_plugin_paths;
     150              : }
     151              : 
     152              : 
     153            1 : void logger::load_plugins(std::string const & plugin_paths)
     154              : {
     155            1 :     guard g;
     156              : 
     157              :     // we can load plugins only once, further calls must be ignored
     158              :     // (it happens in our tests)
     159              :     //
     160            1 :     if(f_plugins == nullptr)
     161              :     {
     162            1 :         serverplugins::paths paths;
     163            1 :         paths.add(plugin_paths);
     164              : 
     165            1 :         serverplugins::names names(paths);
     166            3 :         names.find_plugins("snaplogger_");
     167              : 
     168            1 :         f_plugins = std::make_shared<serverplugins::collection>(names);
     169            1 :         f_plugins->load_plugins(shared_from_this());
     170            1 :     }
     171            2 : }
     172              : 
     173              : 
     174            0 : bool logger::is_configured() const
     175              : {
     176            0 :     guard g;
     177              : 
     178            0 :     return !f_appenders.empty();
     179            0 : }
     180              : 
     181              : 
     182            0 : bool logger::has_appender(std::string const & type) const
     183              : {
     184            0 :     return std::find_if(
     185              :           f_appenders.begin()
     186              :         , f_appenders.end()
     187            0 :         , [&type](auto a)
     188              :         {
     189            0 :             return type == a->get_type();
     190            0 :         }) != f_appenders.end();
     191              : }
     192              : 
     193              : 
     194            2 : appender::pointer_t logger::get_appender(std::string const & name) const
     195              : {
     196            2 :     auto it(std::find_if(
     197              :           f_appenders.begin()
     198              :         , f_appenders.end()
     199            1 :         , [&name](auto a)
     200              :         {
     201            1 :             return name == a->get_name();
     202              :         }));
     203            2 :     if(it == f_appenders.end())
     204              :     {
     205            1 :         return appender::pointer_t();
     206              :     }
     207              : 
     208            1 :     return *it;
     209              : }
     210              : 
     211              : 
     212            0 : appender::vector_t logger::get_appenders() const
     213              : {
     214            0 :     return f_appenders;
     215              : }
     216              : 
     217              : 
     218            2 : void logger::set_config(advgetopt::getopt const & params)
     219              : {
     220              :     // The asynchronous flag can cause problems unless the programmer
     221              :     // specifically planned for it so we do not allow it in configuration
     222              :     // files at the moment. Later we may have two flags. If both are true
     223              :     // then we allow asynchronous logging.
     224              :     //
     225              :     //if(params.is_defined("asynchronous"))
     226              :     //{
     227              :     //    set_asynchronous(advgetopt::is_true(params.get_string("asynchronous")));
     228              :     //}
     229              : 
     230            6 :     auto const & sections(params.get_option(advgetopt::CONFIGURATION_SECTIONS));
     231            2 :     if(sections != nullptr)
     232              :     {
     233            0 :         size_t const max(sections->size());
     234            0 :         for(size_t idx(0); idx < max; ++idx)
     235              :         {
     236            0 :             std::string const section_name(sections->get_value(idx));
     237            0 :             std::string const section_type(section_name + "::type");
     238            0 :             std::string type;
     239            0 :             if(params.is_defined(section_type))
     240              :             {
     241            0 :                 type = params.get_string(section_type);
     242              :             }
     243              :             else
     244              :             {
     245              :                 // try with the name of the section if no type is defined
     246              :                 //
     247            0 :                 type = section_name;
     248              :             }
     249            0 :             if(!type.empty())
     250              :             {
     251            0 :                 appender::pointer_t a(create_appender(type, section_name));
     252            0 :                 if(a != nullptr)
     253              :                 {
     254            0 :                     add_appender(a);
     255              :                 }
     256              :                 // else -- this may be a section which does not represent an appender
     257            0 :             }
     258            0 :         }
     259              :     }
     260              : 
     261            2 :     guard g;
     262              : 
     263            6 :     for(auto a : f_appenders)
     264              :     {
     265            4 :         a->set_config(params);
     266            4 :     }
     267            4 : }
     268              : 
     269              : 
     270            0 : void logger::reopen()
     271              : {
     272            0 :     guard g;
     273              : 
     274            0 :     for(auto a : f_appenders)
     275              :     {
     276            0 :         a->reopen();
     277            0 :     }
     278            0 : }
     279              : 
     280              : 
     281           23 : void logger::add_appender(appender::pointer_t a)
     282              : {
     283           23 :     guard g;
     284              : 
     285           23 :     if(a->unique())
     286              :     {
     287            0 :         std::string const type(a->get_type());
     288            0 :         auto it(std::find_if(
     289              :                   f_appenders.begin()
     290              :                 , f_appenders.end()
     291            0 :                 , [&type](auto app)
     292              :                 {
     293            0 :                     return type == app->get_type();
     294              :                 }));
     295            0 :         if(it != f_appenders.end())
     296              :         {
     297              :             // the console is a pretty special type because it can't be
     298              :             // added twice but it may get added early because an error
     299              :             // occurs and forces initialization of the logger "too soon"
     300              :             //
     301            0 :             if(type == "console")
     302              :             {
     303            0 :                 if(a->get_name() != "console"
     304            0 :                 && (*it)->get_name() == "console")
     305              :                 {
     306            0 :                     (*it)->set_name(a->get_name());
     307              :                 }
     308            0 :                 return;
     309              :             }
     310            0 :             if(type == "syslog")
     311              :             {
     312            0 :                 if(a->get_name() != "syslog"
     313            0 :                 && (*it)->get_name() == "syslog")
     314              :                 {
     315            0 :                     (*it)->set_name(a->get_name());
     316              :                 }
     317            0 :                 return;
     318              :             }
     319              :             throw duplicate_error(
     320              :                           "an appender of type \""
     321            0 :                         + type
     322            0 :                         + "\" can only be added once.");
     323              :         }
     324            0 :     }
     325              : 
     326           23 :     f_appenders.push_back(a);
     327              : 
     328           23 :     severity_changed(a->get_severity());
     329           23 : }
     330              : 
     331              : 
     332            0 : void logger::add_config(std::string const & config_filename)
     333              : {
     334            0 :     advgetopt::options_environment opt_env;
     335              : 
     336            0 :     char const * configuration_files[] =
     337              :     {
     338            0 :           config_filename.c_str()
     339              :         , nullptr
     340            0 :     };
     341              : 
     342            0 :     opt_env.f_project_name = "snaplogger";
     343            0 :     opt_env.f_environment_variable_name = "SNAPLOGGER";
     344            0 :     opt_env.f_configuration_files = configuration_files;
     345            0 :     opt_env.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_DYNAMIC_PARAMETERS;
     346              : 
     347            0 :     advgetopt::getopt opts(opt_env);
     348              : 
     349            0 :     opts.parse_configuration_files();
     350            0 :     opts.parse_environment_variable();
     351              : 
     352            0 :     set_config(opts);
     353            0 : }
     354              : 
     355              : 
     356            0 : appender::pointer_t logger::add_console_appender()
     357              : {
     358            0 :     appender::pointer_t a(std::make_shared<console_appender>("console"));
     359              : 
     360            0 :     advgetopt::options_environment opt_env;
     361            0 :     opt_env.f_project_name = "snaplogger";
     362            0 :     opt_env.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_AUTO_DONE;
     363            0 :     advgetopt::getopt opts(opt_env);
     364            0 :     a->set_config(opts);
     365              : 
     366            0 :     guard g;
     367              : 
     368            0 :     add_appender(a);
     369              : 
     370            0 :     return a;
     371            0 : }
     372              : 
     373              : 
     374            0 : appender::pointer_t logger::add_syslog_appender(std::string const & identity)
     375              : {
     376            0 :     appender::pointer_t a(std::make_shared<syslog_appender>("syslog"));
     377              : 
     378            0 :     advgetopt::option options[] =
     379              :     {
     380              :         advgetopt::define_option(
     381              :               advgetopt::Name("syslog::identity")
     382              :             , advgetopt::Flags(advgetopt::command_flags<advgetopt::GETOPT_FLAG_REQUIRED>())
     383              :         ),
     384              :         advgetopt::end_options()
     385              :     };
     386              : 
     387            0 :     advgetopt::options_environment opt_env;
     388            0 :     opt_env.f_project_name = "snaplogger";
     389            0 :     opt_env.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_AUTO_DONE;
     390            0 :     opt_env.f_options = options;
     391            0 :     advgetopt::getopt opts(opt_env);
     392            0 :     if(!identity.empty())
     393              :     {
     394            0 :         opts.get_option("syslog::identity")->set_value(0, identity);
     395              :     }
     396            0 :     a->set_config(opts);
     397              : 
     398            0 :     guard g;
     399              : 
     400            0 :     add_appender(a);
     401              : 
     402            0 :     return a;
     403            0 : }
     404              : 
     405              : 
     406            0 : appender::pointer_t logger::add_file_appender(std::string const & filename)
     407              : {
     408            0 :     file_appender::pointer_t a(std::make_shared<file_appender>("file"));
     409              : 
     410            0 :     advgetopt::option options[] =
     411              :     {
     412              :         advgetopt::define_option(
     413              :               advgetopt::Name("file::filename")
     414              :             , advgetopt::Flags(advgetopt::command_flags<advgetopt::GETOPT_FLAG_REQUIRED>())
     415              :         ),
     416              :         advgetopt::end_options()
     417              :     };
     418              : 
     419            0 :     advgetopt::options_environment opt_env;
     420            0 :     opt_env.f_project_name = "snaplogger";
     421            0 :     opt_env.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_AUTO_DONE;
     422            0 :     opt_env.f_options = options;
     423            0 :     advgetopt::getopt opts(opt_env);
     424            0 :     if(!filename.empty())
     425              :     {
     426            0 :         opts.get_option("file::filename")->set_value(0, filename);
     427              :     }
     428            0 :     a->set_config(opts);
     429              : 
     430            0 :     guard g;
     431              : 
     432            0 :     add_appender(a);
     433              : 
     434            0 :     return a;
     435            0 : }
     436              : 
     437              : 
     438        91296 : severity_t logger::get_lowest_severity() const
     439              : {
     440        91296 :     guard g;
     441              : 
     442        91296 :     if(f_appenders.empty())
     443              :     {
     444              :         // we do not know the level yet, we do not have the appenders
     445              :         // yet... so accept anything at this point
     446              :         //
     447            1 :         return severity_t::SEVERITY_ALL;
     448              :     }
     449              : 
     450        91295 :     if(f_lowest_replacements.empty())
     451              :     {
     452        91295 :         return f_lowest_severity;
     453              :     }
     454              : 
     455              :     // there is not need to build messages that no appenders is going
     456              :     // to handle, so return the max. between the lowest of all appenders
     457              :     // and the lowest from the replacements
     458              :     //
     459            0 :     return std::max(f_lowest_severity, f_lowest_replacements.back());
     460        91296 : }
     461              : 
     462              : 
     463              : /** \brief Override the lowest severity.
     464              :  *
     465              :  * After this call, and until you call the restore_lowest_severity() function,
     466              :  * the get_lowest_severity() function will return \p severity_level. This
     467              :  * new security level may be lower or higher than the expected level.
     468              :  *
     469              :  * Setting this level to a level lower than the current lowest level is
     470              :  * not useful. The get_lowest_severity() will still return the
     471              :  * f_lowest_severiry value in that case. Since it can change dynamically,
     472              :  * this lowest replacement is still saved as is.
     473              :  *
     474              :  * \param[in] severity_level  The severity level to use in
     475              :  * get_lowest_severity() until restore_lower_severity().
     476              :  */
     477            0 : void logger::override_lowest_severity(severity_t severity_level)
     478              : {
     479            0 :     f_lowest_replacements.push_back(severity_level);
     480            0 : }
     481              : 
     482              : 
     483              : /** \brief Cancel one call to the override_lowest_severity().
     484              :  *
     485              :  * Each time you call the override_lowest_severity() function, you are
     486              :  * expected to call restore_lowest_severity() once to cancel the effect.
     487              :  *
     488              :  * Call the restore_lowest_severity() too many times is safe. However,
     489              :  * to make it safe, you are expected to use the override_lowest_severity_level
     490              :  * class. Create an object of that type. When the object is detroyed, the
     491              :  * lowest level added gets removed automatically.
     492              :  */
     493            0 : void logger::restore_lowest_severity()
     494              : {
     495            0 :     if(!f_lowest_replacements.empty())
     496              :     {
     497            0 :         f_lowest_replacements.pop_back();
     498              :     }
     499            0 : }
     500              : 
     501              : 
     502            1 : void logger::set_severity(severity_t severity_level)
     503              : {
     504            1 :     guard g;
     505              : 
     506            1 :     f_lowest_severity = severity_level;
     507            6 :     for(auto a : f_appenders)
     508              :     {
     509            5 :         a->set_severity(severity_level);
     510            5 :     }
     511            2 : }
     512              : 
     513              : 
     514            1 : void logger::reduce_severity(severity_t severity_level)
     515              : {
     516            3 :     for(auto a : f_appenders)
     517              :     {
     518            2 :         a->reduce_severity(severity_level);
     519            2 :     }
     520            1 : }
     521              : 
     522              : 
     523          317 : void logger::severity_changed(severity_t severity_level)
     524              : {
     525          317 :     guard g;
     526              : 
     527          317 :     if(severity_level < f_lowest_severity)
     528              :     {
     529           21 :         f_lowest_severity = severity_level;
     530              :     }
     531          296 :     else if(severity_level > f_lowest_severity)
     532              :     {
     533              :         // if the severity level grew we have to search for the new lowest;
     534              :         // this happens very rarely while running, it's likely to happen
     535              :         // up to once per appender on initialization.
     536              :         //
     537          285 :         auto const min(std::min_element(f_appenders.begin(), f_appenders.end()));
     538          285 :         if(min == f_appenders.end())
     539              :         {
     540              :             // I don't think this is possible because if there are no appenders
     541              :             // then we should not even get called; also the new level should
     542              :             // not be higher if the list is empty
     543              :             //
     544            0 :             f_lowest_severity = severity_t::SEVERITY_ALL;
     545              :         }
     546              :         else
     547              :         {
     548          285 :             f_lowest_severity = (*min)->get_severity();
     549              :         }
     550              :     }
     551          634 : }
     552              : 
     553              : 
     554            0 : severity_t logger::get_default_severity() const
     555              : {
     556            0 :     private_logger const * l(dynamic_cast<private_logger const *>(this));
     557            0 :     severity::pointer_t sev(l->get_default_severity());
     558            0 :     return sev == nullptr ? severity_t::SEVERITY_DEFAULT : sev->get_severity();
     559            0 : }
     560              : 
     561              : 
     562            0 : bool logger::set_default_severity(severity_t severity_level)
     563              : {
     564            0 :     private_logger * l(dynamic_cast<private_logger *>(this));
     565            0 :     if(severity_level == severity_t::SEVERITY_ALL)
     566              :     {
     567              :         // reset to default
     568            0 :         l->set_default_severity(severity::pointer_t());
     569              :     }
     570              :     else
     571              :     {
     572            0 :         severity::pointer_t sev(l->get_severity(severity_level));
     573            0 :         if(sev == nullptr)
     574              :         {
     575            0 :             return false;
     576              :         }
     577            0 :         l->set_default_severity(sev);
     578            0 :     }
     579            0 :     return true;
     580              : }
     581              : 
     582              : 
     583            0 : void logger::add_component_to_include(component::pointer_t comp)
     584              : {
     585            0 :     guard g;
     586              : 
     587            0 :     f_components_to_include.insert(comp);
     588            0 : }
     589              : 
     590              : 
     591            0 : void logger::remove_component_to_include(component::pointer_t comp)
     592              : {
     593            0 :     guard g;
     594              : 
     595            0 :     f_components_to_include.erase(comp);
     596            0 : }
     597              : 
     598              : 
     599            1 : void logger::add_component_to_ignore(component::pointer_t comp)
     600              : {
     601            1 :     guard g;
     602              : 
     603            1 :     f_components_to_ignore.insert(comp);
     604            2 : }
     605              : 
     606              : 
     607            0 : void logger::remove_component_to_ignore(component::pointer_t comp)
     608              : {
     609            0 :     guard g;
     610              : 
     611            0 :     f_components_to_ignore.erase(comp);
     612            0 : }
     613              : 
     614              : 
     615            0 : component::map_t logger::get_component_list() const
     616              : {
     617            0 :     guard g;
     618              : 
     619            0 :     private_logger const * l(dynamic_cast<private_logger const *>(this));
     620            0 :     return l->get_component_list();
     621            0 : }
     622              : 
     623              : 
     624            0 : void logger::add_default_field(std::string const & name, std::string const & value)
     625              : {
     626            0 :     if(!name.empty())
     627              :     {
     628            0 :         if(name[0] == '_')
     629              :         {
     630              :             throw invalid_parameter(
     631              :                   "field name \""
     632            0 :                 + name
     633            0 :                 + "\" is a system name (whether reserved or already defined) and as such is read-only."
     634            0 :                   " Do not start your field names with an underscore (_).");
     635              :         }
     636            0 :         if(name == "id")
     637              :         {
     638              :             throw invalid_parameter(
     639              :                   "field name \"id\" is automatically set by the message class,"
     640            0 :                   " it cannot be set as a default field.");
     641              :         }
     642              : 
     643            0 :         guard g;
     644              : 
     645            0 :         f_default_fields[name] = value;
     646            0 :     }
     647            0 : }
     648              : 
     649              : 
     650            0 : std::string logger::get_default_field(std::string const & name) const
     651              : {
     652            0 :     guard g;
     653              : 
     654            0 :     auto it(f_default_fields.find(name));
     655            0 :     if(it != f_default_fields.end())
     656              :     {
     657            0 :         return it->second;
     658              :     }
     659            0 :     return std::string();
     660            0 : }
     661              : 
     662              : 
     663        91296 : field_map_t logger::get_default_fields() const
     664              : {
     665        91296 :     guard g;
     666              : 
     667       182592 :     return f_default_fields;
     668        91296 : }
     669              : 
     670              : 
     671            0 : void logger::remove_default_field(std::string const & name)
     672              : {
     673            0 :     guard g;
     674              : 
     675            0 :     auto it(f_default_fields.find(name));
     676            0 :     if(it != f_default_fields.end())
     677              :     {
     678            0 :         f_default_fields.erase(it);
     679              :     }
     680            0 : }
     681              : 
     682              : 
     683            0 : bool logger::is_asynchronous() const
     684              : {
     685            0 :     guard g;
     686              : 
     687            0 :     return f_asynchronous;
     688            0 : }
     689              : 
     690              : 
     691           18 : void logger::set_asynchronous(bool status)
     692              : {
     693           18 :     status = status != false;
     694              : 
     695           18 :     bool do_delete(false);
     696              :     {
     697           18 :         guard g;
     698              : 
     699           18 :         if(f_asynchronous != status)
     700              :         {
     701            2 :             f_asynchronous = status;
     702            2 :             if(!f_asynchronous)
     703              :             {
     704            1 :                 do_delete = true;
     705              :             }
     706              :         }
     707           18 :     }
     708              : 
     709           18 :     if(do_delete)
     710              :     {
     711            1 :         private_logger * l(dynamic_cast<private_logger *>(this));
     712            1 :         l->delete_thread();
     713              :     }
     714           18 : }
     715              : 
     716              : 
     717        91295 : void logger::log_message(message const & msg)
     718              : {
     719        91295 :     if(const_cast<message &>(msg).tellp() > 0)
     720              :     {
     721        45747 :         bool asynchronous(false);
     722              :         {
     723        45747 :             guard g;
     724              : 
     725        45747 :             if(f_asynchronous)
     726              :             {
     727            1 :                 message::pointer_t m(std::make_shared<message>(msg, msg));
     728            1 :                 private_logger * l(dynamic_cast<private_logger *>(this));
     729            1 :                 l->send_message_to_thread(m);
     730            1 :                 asynchronous = true;
     731            1 :             }
     732        45747 :         }
     733              : 
     734        45747 :         if(!asynchronous)
     735              :         {
     736        45746 :             process_message(msg);
     737              :         }
     738              :     }
     739              : 
     740       182578 :     if(f_fatal_severity != severity_t::SEVERITY_OFF
     741        91289 :     && msg.get_severity() >= f_fatal_severity)
     742              :     {
     743            0 :         call_fatal_error_callback();
     744            0 :         throw fatal_error("A fatal error occurred.");
     745              :     }
     746        91289 : }
     747              : 
     748              : 
     749        45747 : void logger::process_message(message const & msg)
     750              : {
     751        45747 :     appender::vector_t appenders;
     752              : 
     753              :     {
     754        45747 :         guard g;
     755              : 
     756        45747 :         bool include(f_components_to_include.empty());
     757        45747 :         component::set_t const & components(msg.get_components());
     758        45747 :         if(components.empty())
     759              :         {
     760        45738 :             if(f_components_to_ignore.find(f_normal_component) != f_components_to_ignore.end())
     761              :             {
     762            0 :                 return;
     763              :             }
     764        45738 :             if(!include)
     765              :             {
     766            0 :                 if(f_components_to_include.find(f_normal_component) != f_components_to_include.end())
     767              :                 {
     768            0 :                     include = true;
     769              :                 }
     770              :             }
     771              :         }
     772              :         else
     773              :         {
     774           22 :             for(auto c : components)
     775              :             {
     776           15 :                 if(f_components_to_ignore.find(c) != f_components_to_ignore.end())
     777              :                 {
     778            2 :                     return;
     779              :                 }
     780           13 :                 if(!include)
     781              :                 {
     782            0 :                     if(f_components_to_include.find(c) != f_components_to_include.end())
     783              :                     {
     784            0 :                         include = true;
     785              :                     }
     786              :                 }
     787           15 :             }
     788              :         }
     789        45745 :         if(!include)
     790              :         {
     791            0 :             return;
     792              :         }
     793              : 
     794        45745 :         if(f_appenders.empty())
     795              :         {
     796            0 :             if(isatty(fileno(stdout)))
     797              :             {
     798            0 :                 add_console_appender();
     799              :             }
     800              :             else
     801              :             {
     802            0 :                 add_syslog_appender(std::string());
     803              :             }
     804              :         }
     805              : 
     806        45745 :         ++f_severity_stats[static_cast<std::size_t>(msg.get_severity())];
     807              : 
     808        45745 :         appenders = f_appenders;
     809        45747 :     }
     810              : 
     811        91532 :     for(auto a : appenders)
     812              :     {
     813        45793 :         a->send_message(msg);
     814        45793 :     }
     815        45747 : }
     816              : 
     817              : 
     818            0 : void logger::set_fatal_error_severity(severity_t sev)
     819              : {
     820            0 :     f_fatal_severity = sev;
     821            0 : }
     822              : 
     823              : 
     824            0 : void logger::set_fatal_error_callback(std::function<void(void)> & f)
     825              : {
     826            0 :     f_fatal_error_callback = f;
     827            0 : }
     828              : 
     829              : 
     830            0 : void logger::call_fatal_error_callback()
     831              : {
     832            0 :     if(f_fatal_error_callback != nullptr)
     833              :     {
     834            0 :         f_fatal_error_callback();
     835              :     }
     836            0 : }
     837              : 
     838              : 
     839              : /** \brief Return statistics about log severities.
     840              :  *
     841              :  * This function returns the statistics counting each message sent per
     842              :  * severity.
     843              :  *
     844              :  * If you enabled the asynchronous functionality of the snaplogger,
     845              :  * then this statistics may not reflect the current state as the
     846              :  * logger thread may still not have processed all the messages.
     847              :  *
     848              :  * \note
     849              :  * The severity_stats_t type is a vector that includes all possible
     850              :  * severity levels (0 to 255), including severity levels that are not
     851              :  * currently declared. It is done that way so the access is as fast
     852              :  * as possible when we want to increment one of the stats. Using a
     853              :  * map would have a much greater impact on the process_message()
     854              :  * function.
     855              :  *
     856              :  * \return a copy of the severity statistics at the time of the call.
     857              :  */
     858            0 : severity_stats_t logger::get_severity_stats() const
     859              : {
     860            0 :     guard g;
     861              : 
     862            0 :     return f_severity_stats;
     863            0 : }
     864              : 
     865              : 
     866            0 : bool is_configured()
     867              : {
     868            0 :     guard g;
     869              : 
     870            0 :     if(g_instance == nullptr)
     871              :     {
     872            0 :         return false;
     873              :     }
     874              : 
     875            0 :     return (*g_instance)->is_configured();
     876            0 : }
     877              : 
     878              : 
     879            0 : bool has_appender(std::string const & type)
     880              : {
     881            0 :     guard g;
     882              : 
     883            0 :     if(g_instance == nullptr)
     884              :     {
     885            0 :         return false;
     886              :     }
     887              : 
     888            0 :     return (*g_instance)->has_appender(type);
     889            0 : }
     890              : 
     891              : 
     892            0 : void reopen()
     893              : {
     894            0 :     guard g;
     895              : 
     896            0 :     if(g_instance == nullptr)
     897              :     {
     898            0 :         return;
     899              :     }
     900              : 
     901            0 :     (*g_instance)->reopen();
     902            0 : }
     903              : 
     904              : 
     905            0 : bool configure_console(bool force)
     906              : {
     907            0 :     bool result(!is_configured() || (force && !has_appender("console")));
     908            0 :     if(result)
     909              :     {
     910            0 :         logger::get_instance()->add_console_appender();
     911              :     }
     912              : 
     913            0 :     return result;
     914              : }
     915              : 
     916              : 
     917            0 : bool configure_syslog(std::string const & identity)
     918              : {
     919            0 :     bool result(!is_configured());
     920            0 :     if(result)
     921              :     {
     922            0 :         logger::get_instance()->add_syslog_appender(identity);
     923              :     }
     924              : 
     925            0 :     return result;
     926              : }
     927              : 
     928              : 
     929            0 : bool configure_file(std::string const & filename)
     930              : {
     931            0 :     bool result(!is_configured());
     932            0 :     if(result)
     933              :     {
     934            0 :         logger::get_instance()->add_file_appender(filename);
     935              :     }
     936              : 
     937            0 :     return result;
     938              : }
     939              : 
     940              : 
     941            0 : bool configure_config(std::string const & config_filename)
     942              : {
     943            0 :     bool result(!is_configured());
     944            0 :     if(result)
     945              :     {
     946            0 :         logger::get_instance()->add_config(config_filename);
     947              :     }
     948              : 
     949            0 :     return result;
     950              : }
     951              : 
     952              : 
     953              : 
     954              : 
     955              : } // snaplogger namespace
     956              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions