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

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

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