pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
logging.h
Go to the documentation of this file.
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 <stdint.h> // uint8_t, uint32_t
15 # include <glib.h>
16 # include <qb/qblog.h>
17 # include <libxml/tree.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
30 /* Define custom log priorities.
31  *
32  * syslog(3) uses int for priorities, but libqb's struct qb_log_callsite uses
33  * uint8_t, so make sure they fit in the latter.
34  */
35 
36 // Define something even less desired than debug
37 # ifndef LOG_TRACE
38 # define LOG_TRACE (LOG_DEBUG+1)
39 # endif
40 
41 // Print message to stdout instead of logging it
42 # ifndef LOG_STDOUT
43 # define LOG_STDOUT 254
44 # endif
45 
46 // Don't send message anywhere
47 # ifndef LOG_NEVER
48 # define LOG_NEVER 255
49 # endif
50 
51 /* "Extended information" logging support */
52 #ifdef QB_XS
53 # define CRM_XS QB_XS
54 # define crm_extended_logging(t, e) qb_log_ctl((t), QB_LOG_CONF_EXTENDED, (e))
55 #else
56 # define CRM_XS "|"
57 
58 /* A caller might want to check the return value, so we can't define this as a
59  * no-op, and we can't simply define it to be 0 because gcc will then complain
60  * when the value isn't checked.
61  */
62 static inline int
63 crm_extended_logging(int t, int e)
64 {
65  return 0;
66 }
67 #endif
68 
69 extern unsigned int crm_log_level;
70 extern unsigned int crm_trace_nonlog;
71 
77 extern gboolean crm_config_error;
78 
84 extern gboolean crm_config_warning;
85 
86 void crm_enable_blackbox(int nsig);
87 void crm_disable_blackbox(int nsig);
88 void crm_write_blackbox(int nsig, const struct qb_log_callsite *callsite);
89 
90 void crm_update_callsites(void);
91 
92 void crm_log_deinit(void);
93 
101 void crm_log_preinit(const char *entity, int argc, char *const *argv);
102 gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon,
103  gboolean to_stderr, int argc, char **argv, gboolean quiet);
104 
105 void crm_log_args(int argc, char **argv);
106 void crm_log_output_fn(const char *file, const char *function, int line, int level,
107  const char *prefix, const char *output);
108 
109 // Log a block of text line by line
110 #define crm_log_output(level, prefix, output) \
111  crm_log_output_fn(__FILE__, __func__, __LINE__, level, prefix, output)
112 
113 void crm_bump_log_level(int argc, char **argv);
114 
115 void crm_enable_stderr(int enable);
116 
117 gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags);
118 
119 /* returns the old value */
120 unsigned int set_crm_log_level(unsigned int level);
121 
122 unsigned int get_crm_log_level(void);
123 
124 void pcmk_log_xml_as(const char *file, const char *function, uint32_t line,
125  uint32_t tags, uint8_t level, const char *text,
126  const xmlNode *xml);
127 
128 /*
129  * Throughout the macros below, note the leading, pre-comma, space in the
130  * various ' , ##args' occurrences to aid portability across versions of 'gcc'.
131  * https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros
132  */
133 #if defined(__clang__)
134 # define CRM_TRACE_INIT_DATA(name)
135 # else
136 # include <assert.h> // required by QB_LOG_INIT_DATA() macro
137 # define CRM_TRACE_INIT_DATA(name) QB_LOG_INIT_DATA(name)
138 #endif
139 
149 /* @COMPAT: Make this function internal at a compatibility break. It's used in
150  * public macros for now.
151  */
152 static inline uint8_t
153 pcmk__clip_log_level(int level)
154 {
155  if (level <= 0) {
156  return 0;
157  }
158  if (level >= UINT8_MAX) {
159  return UINT8_MAX;
160  }
161  return level;
162 }
163 
164 /* Using "switch" instead of "if" in these macro definitions keeps
165  * static analysis from complaining about constant evaluations
166  */
167 
175 # define do_crm_log(level, fmt, args...) do { \
176  uint8_t _level = pcmk__clip_log_level(level); \
177  \
178  switch (_level) { \
179  case LOG_STDOUT: \
180  printf(fmt "\n" , ##args); \
181  break; \
182  case LOG_NEVER: \
183  break; \
184  default: \
185  qb_log_from_external_source(__func__, __FILE__, fmt, \
186  _level, __LINE__, 0 , ##args); \
187  break; \
188  } \
189  } while (0)
190 
200 # define do_crm_log_unlikely(level, fmt, args...) do { \
201  uint8_t _level = pcmk__clip_log_level(level); \
202  \
203  switch (_level) { \
204  case LOG_STDOUT: case LOG_NEVER: \
205  break; \
206  default: { \
207  static struct qb_log_callsite *trace_cs = NULL; \
208  if (trace_cs == NULL) { \
209  trace_cs = qb_log_callsite_get(__func__, __FILE__, fmt, \
210  _level, __LINE__, 0); \
211  } \
212  if (crm_is_callsite_active(trace_cs, _level, 0)) { \
213  qb_log_from_external_source(__func__, __FILE__, fmt, \
214  _level, __LINE__, 0 , \
215  ##args); \
216  } \
217  } \
218  break; \
219  } \
220  } while (0)
221 
222 # define CRM_LOG_ASSERT(expr) do { \
223  if (!(expr)) { \
224  static struct qb_log_callsite *core_cs = NULL; \
225  if(core_cs == NULL) { \
226  core_cs = qb_log_callsite_get(__func__, __FILE__, \
227  "log-assert", LOG_TRACE, \
228  __LINE__, 0); \
229  } \
230  crm_abort(__FILE__, __func__, __LINE__, #expr, \
231  core_cs?core_cs->targets:FALSE, TRUE); \
232  } \
233  } while(0)
234 
235 /* 'failure_action' MUST NOT be 'continue' as it will apply to the
236  * macro's do-while loop
237  */
238 # define CRM_CHECK(expr, failure_action) do { \
239  if (!(expr)) { \
240  static struct qb_log_callsite *core_cs = NULL; \
241  if (core_cs == NULL) { \
242  core_cs = qb_log_callsite_get(__func__, __FILE__, \
243  "check-assert", \
244  LOG_TRACE, __LINE__, 0); \
245  } \
246  crm_abort(__FILE__, __func__, __LINE__, #expr, \
247  (core_cs? core_cs->targets: FALSE), TRUE); \
248  failure_action; \
249  } \
250  } while(0)
251 
261 # define do_crm_log_xml(level, text, xml) do { \
262  uint8_t _level = pcmk__clip_log_level(level); \
263  static struct qb_log_callsite *xml_cs = NULL; \
264  \
265  switch (_level) { \
266  case LOG_STDOUT: \
267  case LOG_NEVER: \
268  break; \
269  default: \
270  if (xml_cs == NULL) { \
271  xml_cs = qb_log_callsite_get(__func__, __FILE__, \
272  "xml-blob", _level, \
273  __LINE__, 0); \
274  } \
275  if (crm_is_callsite_active(xml_cs, _level, 0)) { \
276  pcmk_log_xml_as(__FILE__, __func__, __LINE__, 0, \
277  _level, text, (xml)); \
278  } \
279  break; \
280  } \
281  } while(0)
282 
293 # define do_crm_log_alias(level, file, function, line, fmt, args...) do { \
294  uint8_t _level = pcmk__clip_log_level(level); \
295  \
296  switch (_level) { \
297  case LOG_STDOUT: \
298  printf(fmt "\n" , ##args); \
299  break; \
300  case LOG_NEVER: \
301  break; \
302  default: \
303  qb_log_from_external_source(function, file, fmt, _level, \
304  line, 0 , ##args); \
305  break; \
306  } \
307  } while (0)
308 
323 # define crm_perror(level, fmt, args...) do { \
324  uint8_t _level = pcmk__clip_log_level(level); \
325  \
326  switch (_level) { \
327  case LOG_NEVER: \
328  break; \
329  default: { \
330  const char *err = strerror(errno); \
331  if (_level <= crm_log_level) { \
332  fprintf(stderr, fmt ": %s (%d)\n" , ##args, err, \
333  errno); \
334  } \
335  /* Pass original level arg since do_crm_log() also declares \
336  * _level \
337  */ \
338  do_crm_log((level), fmt ": %s (%d)" , ##args, err, errno); \
339  } \
340  break; \
341  } \
342  } while (0)
343 
354 # define crm_log_tag(level, tag, fmt, args...) do { \
355  uint8_t _level = pcmk__clip_log_level(level); \
356  \
357  switch (_level) { \
358  case LOG_STDOUT: case LOG_NEVER: \
359  break; \
360  default: { \
361  static struct qb_log_callsite *trace_tag_cs = NULL; \
362  int converted_tag = g_quark_try_string(tag); \
363  if (trace_tag_cs == NULL) { \
364  trace_tag_cs = qb_log_callsite_get(__func__, __FILE__, \
365  fmt, _level, \
366  __LINE__, \
367  converted_tag); \
368  } \
369  if (crm_is_callsite_active(trace_tag_cs, _level, \
370  converted_tag)) { \
371  qb_log_from_external_source(__func__, __FILE__, fmt, \
372  _level, __LINE__, \
373  converted_tag , ##args); \
374  } \
375  } \
376  } \
377  } while (0)
378 
379 # define crm_emerg(fmt, args...) qb_log(LOG_EMERG, fmt , ##args)
380 # define crm_crit(fmt, args...) qb_logt(LOG_CRIT, 0, fmt , ##args)
381 # define crm_err(fmt, args...) qb_logt(LOG_ERR, 0, fmt , ##args)
382 # define crm_warn(fmt, args...) qb_logt(LOG_WARNING, 0, fmt , ##args)
383 # define crm_notice(fmt, args...) qb_logt(LOG_NOTICE, 0, fmt , ##args)
384 # define crm_info(fmt, args...) qb_logt(LOG_INFO, 0, fmt , ##args)
385 
386 # define crm_debug(fmt, args...) do_crm_log_unlikely(LOG_DEBUG, fmt , ##args)
387 # define crm_trace(fmt, args...) do_crm_log_unlikely(LOG_TRACE, fmt , ##args)
388 
389 # define crm_log_xml_crit(xml, text) do_crm_log_xml(LOG_CRIT, text, xml)
390 # define crm_log_xml_err(xml, text) do_crm_log_xml(LOG_ERR, text, xml)
391 # define crm_log_xml_warn(xml, text) do_crm_log_xml(LOG_WARNING, text, xml)
392 # define crm_log_xml_notice(xml, text) do_crm_log_xml(LOG_NOTICE, text, xml)
393 # define crm_log_xml_info(xml, text) do_crm_log_xml(LOG_INFO, text, xml)
394 # define crm_log_xml_debug(xml, text) do_crm_log_xml(LOG_DEBUG, text, xml)
395 # define crm_log_xml_trace(xml, text) do_crm_log_xml(LOG_TRACE, text, xml)
396 
397 # define crm_log_xml_explicit(xml, text) do { \
398  static struct qb_log_callsite *digest_cs = NULL; \
399  digest_cs = qb_log_callsite_get( \
400  __func__, __FILE__, text, LOG_TRACE, __LINE__, \
401  crm_trace_nonlog); \
402  if (digest_cs && digest_cs->targets) { \
403  do_crm_log_xml(LOG_TRACE, text, xml); \
404  } \
405  } while(0)
406 
407 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
409 #endif
410 
411 #ifdef __cplusplus
412 }
413 #endif
414 
415 #endif
void crm_enable_stderr(int enable)
Definition: logging.c:1044
void pcmk_log_xml_as(const char *file, const char *function, uint32_t line, uint32_t tags, uint8_t level, const char *text, const xmlNode *xml)
Log XML line-by-line in a formatted fashion.
Definition: logging.c:1163
gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr, int argc, char **argv, gboolean quiet)
Definition: logging.c:896
unsigned int crm_trace_nonlog
Definition: logging.c:46
Deprecated Pacemaker logging API.
void crm_bump_log_level(int argc, char **argv)
Make logging more verbose.
Definition: logging.c:1065
void crm_log_deinit(void)
Definition: logging.c:131
gboolean crm_config_error
Definition: utils.c:49
void crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix, const char *output)
Definition: logging.c:1106
void crm_enable_blackbox(int nsig)
Definition: logging.c:483
void crm_log_args(int argc, char **argv)
Log the command line (once)
Definition: logging.c:1091
void crm_write_blackbox(int nsig, const struct qb_log_callsite *callsite)
Definition: logging.c:505
unsigned int set_crm_log_level(unsigned int level)
Definition: logging.c:1030
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
Definition: logging.c:680
unsigned int get_crm_log_level(void)
Definition: logging.c:1076
unsigned int crm_log_level
Definition: logging.c:45
void crm_disable_blackbox(int nsig)
Definition: logging.c:489
void crm_log_preinit(const char *entity, int argc, char *const *argv)
Initializes the logging system and defaults to the least verbose output level.
Definition: logging.c:811
gboolean crm_config_warning
Definition: utils.c:50
void crm_update_callsites(void)
Definition: logging.c:709