root/include/crm/common/logging.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. crm_extended_logging
  2. pcmk__clip_log_level

   1 /*
   2  * Copyright 2004-2023 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #ifndef PCMK__CRM_COMMON_LOGGING__H
  11 #  define PCMK__CRM_COMMON_LOGGING__H
  12 
  13 #  include <stdio.h>
  14 #  include <glib.h>
  15 #  include <qb/qblog.h>
  16 #  include <libxml/tree.h>
  17 
  18 #ifdef __cplusplus
  19 extern "C" {
  20 #endif
  21 
  22 /**
  23  * \file
  24  * \brief Wrappers for and extensions to libqb logging
  25  * \ingroup core
  26  */
  27 
  28 
  29 /* Define custom log priorities.
  30  *
  31  * syslog(3) uses int for priorities, but libqb's struct qb_log_callsite uses
  32  * uint8_t, so make sure they fit in the latter.
  33  */
  34 
  35 // Define something even less desired than debug
  36 #  ifndef LOG_TRACE
  37 #    define LOG_TRACE   (LOG_DEBUG+1)
  38 #  endif
  39 
  40 // Print message to stdout instead of logging it
  41 #  ifndef LOG_STDOUT
  42 #    define LOG_STDOUT  254
  43 #  endif
  44 
  45 // Don't send message anywhere
  46 #  ifndef LOG_NEVER
  47 #    define LOG_NEVER   255
  48 #  endif
  49 
  50 /* "Extended information" logging support */
  51 #ifdef QB_XS
  52 #  define CRM_XS QB_XS
  53 #  define crm_extended_logging(t, e) qb_log_ctl((t), QB_LOG_CONF_EXTENDED, (e))
  54 #else
  55 #  define CRM_XS "|"
  56 
  57 /* A caller might want to check the return value, so we can't define this as a
  58  * no-op, and we can't simply define it to be 0 because gcc will then complain
  59  * when the value isn't checked.
  60  */
  61 static inline int
  62 crm_extended_logging(int t, int e)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64     return 0;
  65 }
  66 #endif
  67 
  68 extern unsigned int crm_log_level;
  69 extern unsigned int crm_trace_nonlog;
  70 
  71 /*! \deprecated Pacemaker library functions set this when a configuration
  72  *              error is found, which turns on extra messages at the end of
  73  *              processing. It should not be used directly and will be removed
  74  *              from the public C API in a future release.
  75  */
  76 extern gboolean crm_config_error;
  77 
  78 /*! \deprecated Pacemaker library functions set this when a configuration
  79  *              warning is found, which turns on extra messages at the end of
  80  *              processing. It should not be used directly and will be removed
  81  *              from the public C API in a future release.
  82  */
  83 extern gboolean crm_config_warning;
  84 
  85 void crm_enable_blackbox(int nsig);
  86 void crm_disable_blackbox(int nsig);
  87 void crm_write_blackbox(int nsig, const struct qb_log_callsite *callsite);
  88 
  89 void crm_update_callsites(void);
  90 
  91 void crm_log_deinit(void);
  92 
  93 /*!
  94  * \brief Initializes the logging system and defaults to the least verbose output level
  95  *
  96  * \param[in] entity  If not NULL, will be used as the identity for logging purposes
  97  * \param[in] argc    The number of command line parameters
  98  * \param[in] argv    The command line parameter values
  99  */
 100 void crm_log_preinit(const char *entity, int argc, char *const *argv);
 101 gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon,
 102                       gboolean to_stderr, int argc, char **argv, gboolean quiet);
 103 
 104 void crm_log_args(int argc, char **argv);
 105 void crm_log_output_fn(const char *file, const char *function, int line, int level,
 106                        const char *prefix, const char *output);
 107 
 108 // Log a block of text line by line
 109 #define crm_log_output(level, prefix, output)   \
 110     crm_log_output_fn(__FILE__, __func__, __LINE__, level, prefix, output)
 111 
 112 void crm_bump_log_level(int argc, char **argv);
 113 
 114 void crm_enable_stderr(int enable);
 115 
 116 gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags);
 117 
 118 /* returns the old value */
 119 unsigned int set_crm_log_level(unsigned int level);
 120 
 121 unsigned int get_crm_log_level(void);
 122 
 123 void pcmk_log_xml_impl(uint8_t level, const char *text, const xmlNode *xml);
 124 
 125 /*
 126  * Throughout the macros below, note the leading, pre-comma, space in the
 127  * various ' , ##args' occurrences to aid portability across versions of 'gcc'.
 128  * https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros
 129  */
 130 #if defined(__clang__)
 131 #    define CRM_TRACE_INIT_DATA(name)
 132 #  else
 133 #    include <assert.h> // required by QB_LOG_INIT_DATA() macro
 134 #    define CRM_TRACE_INIT_DATA(name) QB_LOG_INIT_DATA(name)
 135 #endif
 136 
 137 /*!
 138  * \internal
 139  * \brief Clip log_level to \p uint8_t range
 140  *
 141  * \param[in] level  Log level to clip
 142  *
 143  * \return 0 if \p level is less than 0, \p UINT8_MAX if \p level is greater
 144  *         than \p UINT8_MAX, or \p level otherwise
 145  */
 146 /* @COMPAT: Make this function internal at a compatibility break. It's used in
 147  * public macros for now.
 148  */
 149 static inline uint8_t
 150 pcmk__clip_log_level(int level)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152     if (level <= 0) {
 153         return 0;
 154     }
 155     if (level >= UINT8_MAX) {
 156         return UINT8_MAX;
 157     }
 158     return level;
 159 }
 160 
 161 /* Using "switch" instead of "if" in these macro definitions keeps
 162  * static analysis from complaining about constant evaluations
 163  */
 164 
 165 /*!
 166  * \brief Log a message
 167  *
 168  * \param[in] level  Priority at which to log the message
 169  * \param[in] fmt    printf-style format string literal for message
 170  * \param[in] args   Any arguments needed by format string
 171  */
 172 #  define do_crm_log(level, fmt, args...) do {                              \
 173         uint8_t _level = pcmk__clip_log_level(level);                       \
 174                                                                             \
 175         switch (_level) {                                                   \
 176             case LOG_STDOUT:                                                \
 177                 printf(fmt "\n" , ##args);                                  \
 178                 break;                                                      \
 179             case LOG_NEVER:                                                 \
 180                 break;                                                      \
 181             default:                                                        \
 182                 qb_log_from_external_source(__func__, __FILE__, fmt,        \
 183                                             _level, __LINE__, 0 , ##args);  \
 184                 break;                                                      \
 185         }                                                                   \
 186     } while (0)
 187 
 188 /*!
 189  * \brief Log a message that is likely to be filtered out
 190  *
 191  * \param[in] level  Priority at which to log the message
 192  * \param[in] fmt    printf-style format string for message
 193  * \param[in] args   Any arguments needed by format string
 194  *
 195  * \note This does nothing when level is \p LOG_STDOUT.
 196  */
 197 #  define do_crm_log_unlikely(level, fmt, args...) do {                     \
 198         uint8_t _level = pcmk__clip_log_level(level);                       \
 199                                                                             \
 200         switch (_level) {                                                   \
 201             case LOG_STDOUT: case LOG_NEVER:                                \
 202                 break;                                                      \
 203             default: {                                                      \
 204                 static struct qb_log_callsite *trace_cs = NULL;             \
 205                 if (trace_cs == NULL) {                                     \
 206                     trace_cs = qb_log_callsite_get(__func__, __FILE__, fmt, \
 207                                                    _level, __LINE__, 0);    \
 208                 }                                                           \
 209                 if (crm_is_callsite_active(trace_cs, _level, 0)) {          \
 210                     qb_log_from_external_source(__func__, __FILE__, fmt,    \
 211                                                 _level, __LINE__, 0 ,       \
 212                                                 ##args);                    \
 213                 }                                                           \
 214             }                                                               \
 215             break;                                                          \
 216         }                                                                   \
 217     } while (0)
 218 
 219 #  define CRM_LOG_ASSERT(expr) do {                                     \
 220         if (!(expr)) {                                                  \
 221             static struct qb_log_callsite *core_cs = NULL;              \
 222             if(core_cs == NULL) {                                       \
 223                 core_cs = qb_log_callsite_get(__func__, __FILE__,       \
 224                                               "log-assert", LOG_TRACE,  \
 225                                               __LINE__, 0);             \
 226             }                                                           \
 227             crm_abort(__FILE__, __func__, __LINE__, #expr,              \
 228                       core_cs?core_cs->targets:FALSE, TRUE);            \
 229         }                                                               \
 230     } while(0)
 231 
 232 /* 'failure_action' MUST NOT be 'continue' as it will apply to the
 233  * macro's do-while loop
 234  */
 235 #  define CRM_CHECK(expr, failure_action) do {                                      \
 236         if (!(expr)) {                                                  \
 237             static struct qb_log_callsite *core_cs = NULL;              \
 238             if (core_cs == NULL) {                                      \
 239                 core_cs = qb_log_callsite_get(__func__, __FILE__,       \
 240                                               "check-assert",           \
 241                                               LOG_TRACE, __LINE__, 0);  \
 242             }                                                           \
 243                 crm_abort(__FILE__, __func__, __LINE__, #expr,              \
 244                         (core_cs? core_cs->targets: FALSE), TRUE);              \
 245                 failure_action;                                                                 \
 246             }                                                                                           \
 247     } while(0)
 248 
 249 /*!
 250  * \brief Log XML line-by-line in a formatted fashion
 251  *
 252  * \param[in] level  Priority at which to log the messages
 253  * \param[in] text   Prefix for each line
 254  * \param[in] xml    XML to log
 255  *
 256  * \note This does nothing when \p level is \p LOG_STDOUT.
 257  */
 258 #  define do_crm_log_xml(level, text, xml) do {                         \
 259         uint8_t _level = pcmk__clip_log_level(level);                   \
 260         static struct qb_log_callsite *xml_cs = NULL;                   \
 261                                                                         \
 262         switch (_level) {                                               \
 263             case LOG_STDOUT:                                            \
 264             case LOG_NEVER:                                             \
 265                 break;                                                  \
 266             default:                                                    \
 267                 if (xml_cs == NULL) {                                   \
 268                     xml_cs = qb_log_callsite_get(__func__, __FILE__,    \
 269                                                  "xml-blob", _level,    \
 270                                                  __LINE__, 0);          \
 271                 }                                                       \
 272                 if (crm_is_callsite_active(xml_cs, _level, 0)) {        \
 273                     pcmk_log_xml_impl(_level, text, xml);               \
 274                 }                                                       \
 275                 break;                                                  \
 276         }                                                               \
 277     } while(0)
 278 
 279 /*!
 280  * \brief Log a message as if it came from a different code location
 281  *
 282  * \param[in] level     Priority at which to log the message
 283  * \param[in] file      Source file name to use instead of __FILE__
 284  * \param[in] function  Source function name to use instead of __func__
 285  * \param[in] line      Source line number to use instead of __line__
 286  * \param[in] fmt       printf-style format string literal for message
 287  * \param[in] args      Any arguments needed by format string
 288  */
 289 #  define do_crm_log_alias(level, file, function, line, fmt, args...) do {  \
 290         uint8_t _level = pcmk__clip_log_level(level);                       \
 291                                                                             \
 292         switch (_level) {                                                   \
 293             case LOG_STDOUT:                                                \
 294                 printf(fmt "\n" , ##args);                                  \
 295                 break;                                                      \
 296             case LOG_NEVER:                                                 \
 297                 break;                                                      \
 298             default:                                                        \
 299                 qb_log_from_external_source(function, file, fmt, _level,    \
 300                                             line, 0 , ##args);              \
 301                 break;                                                      \
 302         }                                                                   \
 303     } while (0)
 304 
 305 /*!
 306  * \brief Send a system error message to both the log and stderr
 307  *
 308  * \param[in] level  Priority at which to log the message
 309  * \param[in] fmt    printf-style format string for message
 310  * \param[in] args   Any arguments needed by format string
 311  *
 312  * \deprecated One of the other logging functions should be used with
 313  *             pcmk_strerror() instead.
 314  * \note This is a macro, and \p level may be evaluated more than once.
 315  * \note Because crm_perror() adds the system error message and error number
 316  *       onto the end of fmt, that information will become extended information
 317  *       if CRM_XS is used inside fmt and will not show up in syslog.
 318  */
 319 #  define crm_perror(level, fmt, args...) do {                              \
 320         uint8_t _level = pcmk__clip_log_level(level);                       \
 321                                                                             \
 322         switch (_level) {                                                   \
 323             case LOG_NEVER:                                                 \
 324                 break;                                                      \
 325             default: {                                                      \
 326                 const char *err = strerror(errno);                          \
 327                 if (_level <= crm_log_level) {                              \
 328                     fprintf(stderr, fmt ": %s (%d)\n" , ##args, err,        \
 329                             errno);                                         \
 330                 }                                                           \
 331                 /* Pass original level arg since do_crm_log() also declares \
 332                  * _level                                                   \
 333                  */                                                         \
 334                 do_crm_log((level), fmt ": %s (%d)" , ##args, err, errno);  \
 335             }                                                               \
 336             break;                                                          \
 337         }                                                                   \
 338     } while (0)
 339 
 340 /*!
 341  * \brief Log a message with a tag (for use with PCMK_trace_tags)
 342  *
 343  * \param[in] level  Priority at which to log the message
 344  * \param[in] tag    String to tag message with
 345  * \param[in] fmt    printf-style format string for message
 346  * \param[in] args   Any arguments needed by format string
 347  *
 348  * \note This does nothing when level is LOG_STDOUT.
 349  */
 350 #  define crm_log_tag(level, tag, fmt, args...)    do {                     \
 351         uint8_t _level = pcmk__clip_log_level(level);                       \
 352                                                                             \
 353         switch (_level) {                                                   \
 354             case LOG_STDOUT: case LOG_NEVER:                                \
 355                 break;                                                      \
 356             default: {                                                      \
 357                 static struct qb_log_callsite *trace_tag_cs = NULL;         \
 358                 int converted_tag = g_quark_try_string(tag);                \
 359                 if (trace_tag_cs == NULL) {                                 \
 360                     trace_tag_cs = qb_log_callsite_get(__func__, __FILE__,  \
 361                                                        fmt, _level,         \
 362                                                        __LINE__,            \
 363                                                        converted_tag);      \
 364                 }                                                           \
 365                 if (crm_is_callsite_active(trace_tag_cs, _level,            \
 366                                            converted_tag)) {                \
 367                     qb_log_from_external_source(__func__, __FILE__, fmt,    \
 368                                                 _level, __LINE__,           \
 369                                                 converted_tag , ##args);    \
 370                 }                                                           \
 371             }                                                               \
 372         }                                                                   \
 373     } while (0)
 374 
 375 #  define crm_emerg(fmt, args...)   qb_log(LOG_EMERG,       fmt , ##args)
 376 #  define crm_crit(fmt, args...)    qb_logt(LOG_CRIT,    0, fmt , ##args)
 377 #  define crm_err(fmt, args...)     qb_logt(LOG_ERR,     0, fmt , ##args)
 378 #  define crm_warn(fmt, args...)    qb_logt(LOG_WARNING, 0, fmt , ##args)
 379 #  define crm_notice(fmt, args...)  qb_logt(LOG_NOTICE,  0, fmt , ##args)
 380 #  define crm_info(fmt, args...)    qb_logt(LOG_INFO,    0, fmt , ##args)
 381 
 382 #  define crm_debug(fmt, args...)   do_crm_log_unlikely(LOG_DEBUG, fmt , ##args)
 383 #  define crm_trace(fmt, args...)   do_crm_log_unlikely(LOG_TRACE, fmt , ##args)
 384 
 385 #  define crm_log_xml_crit(xml, text)    do_crm_log_xml(LOG_CRIT,    text, xml)
 386 #  define crm_log_xml_err(xml, text)     do_crm_log_xml(LOG_ERR,     text, xml)
 387 #  define crm_log_xml_warn(xml, text)    do_crm_log_xml(LOG_WARNING, text, xml)
 388 #  define crm_log_xml_notice(xml, text)  do_crm_log_xml(LOG_NOTICE,  text, xml)
 389 #  define crm_log_xml_info(xml, text)    do_crm_log_xml(LOG_INFO,    text, xml)
 390 #  define crm_log_xml_debug(xml, text)   do_crm_log_xml(LOG_DEBUG,   text, xml)
 391 #  define crm_log_xml_trace(xml, text)   do_crm_log_xml(LOG_TRACE,   text, xml)
 392 
 393 #  define crm_log_xml_explicit(xml, text)  do {                 \
 394         static struct qb_log_callsite *digest_cs = NULL;        \
 395         digest_cs = qb_log_callsite_get(                        \
 396             __func__, __FILE__, text, LOG_TRACE, __LINE__,      \
 397             crm_trace_nonlog);                                  \
 398         if (digest_cs && digest_cs->targets) {                  \
 399             do_crm_log_xml(LOG_TRACE,   text, xml);             \
 400         }                                                       \
 401     } while(0)
 402 
 403 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 404 #include <crm/common/logging_compat.h>
 405 #endif
 406 
 407 #ifdef __cplusplus
 408 }
 409 #endif
 410 
 411 #endif

/* [previous][next][first][last][top][bottom][index][help] */