12 #include <sys/param.h>
13 #include <sys/types.h>
16 #include <sys/utsname.h>
31 #include <qb/qbdefs.h>
38 static gboolean crm_tracing_enabled(
void);
45 crm_glib_handler(
const gchar * log_domain, GLogLevelFlags
flags,
const gchar * message,
48 int log_level = LOG_WARNING;
49 GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK);
50 static struct qb_log_callsite *glib_cs = NULL;
52 if (glib_cs == NULL) {
53 glib_cs = qb_log_callsite_get(__FUNCTION__, __FILE__,
"glib-handler", LOG_DEBUG, __LINE__,
crm_trace_nonlog);
58 case G_LOG_LEVEL_CRITICAL:
63 crm_abort(__FILE__, __FUNCTION__, __LINE__, message, TRUE, TRUE);
67 case G_LOG_LEVEL_ERROR:
70 case G_LOG_LEVEL_MESSAGE:
71 log_level = LOG_NOTICE;
73 case G_LOG_LEVEL_INFO:
76 case G_LOG_LEVEL_DEBUG:
77 log_level = LOG_DEBUG;
80 case G_LOG_LEVEL_WARNING:
81 case G_LOG_FLAG_RECURSION:
82 case G_LOG_FLAG_FATAL:
83 case G_LOG_LEVEL_MASK:
84 log_level = LOG_WARNING;
88 do_crm_log(log_level,
"%s: %s", log_domain, message);
104 crm_trigger_blackbox(
int nsig)
106 if(nsig == SIGTRAP) {
122 set_format_string(
int method,
const char *
daemon)
124 if (method == QB_LOG_SYSLOG) {
126 crm_extended_logging(method, QB_FALSE);
127 qb_log_format_set(method,
"%g %p: %b");
135 if (method > QB_LOG_STDERR) {
137 const char *nodename =
"localhost";
139 if (
uname(&res) == 0) {
140 nodename = res.nodename;
144 offset += snprintf(fmt + offset,
FMT_MAX - offset,
145 "%%t %s %-20s[%lu] ",
146 nodename, daemon, (
unsigned long) getpid());
150 offset += snprintf(fmt + offset,
FMT_MAX - offset,
"(%%n");
151 if (crm_tracing_enabled()) {
153 offset += snprintf(fmt + offset,
FMT_MAX - offset,
"@%%f:%%l");
155 offset += snprintf(fmt + offset,
FMT_MAX - offset,
")");
158 offset += snprintf(fmt + offset,
FMT_MAX - offset,
" %%g\t%%p: %%b");
161 qb_log_format_set(method, fmt);
168 bool is_default =
false;
169 static int default_fd = -1;
170 static gboolean have_logfile = FALSE;
171 const char *default_logfile =
CRM_LOG_DIR "/pacemaker.log";
175 FILE *logfile = NULL;
176 char *parent_dir = NULL;
179 if (filename == NULL && have_logfile == FALSE) {
180 filename = default_logfile;
183 if (filename == NULL) {
189 }
else if(
safe_str_eq(filename, default_logfile)) {
193 if(is_default && default_fd >= 0) {
198 filename_cp = strdup(filename);
199 parent_dir = dirname(filename_cp);
200 rc = stat(parent_dir, &parent);
203 crm_err(
"Directory '%s' does not exist: logging to '%s' is disabled", parent_dir, filename);
210 logfile = fopen(filename,
"a");
211 if(logfile == NULL) {
212 crm_err(
"%s (%d): Logging to '%s' as uid=%u, gid=%u is disabled",
213 pcmk_strerror(errno), errno, filename, geteuid(), getegid());
218 if (geteuid() == 0) {
222 gboolean fix = FALSE;
223 int logfd = fileno(logfile);
225 rc = fstat(logfd, &st);
227 crm_perror(LOG_WARNING,
"Cannot stat %s", filename);
233 if (st.st_gid != pcmk_gid) {
236 }
else if ((st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
243 rc = fchown(logfd, pcmk_uid, pcmk_gid);
245 crm_warn(
"Cannot change the ownership of %s to user %s and gid %d",
249 rc = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
251 crm_warn(
"Cannot change the mode of %s to rw-rw----", filename);
254 fprintf(logfile,
"Set r/w permissions for uid=%d, gid=%d on %s\n",
255 pcmk_uid, pcmk_gid, filename);
256 if (fflush(logfile) < 0 || fsync(logfd) < 0) {
257 crm_err(
"Couldn't write out logfile: %s", filename);
264 fd = qb_log_file_open(filename);
267 crm_perror(LOG_WARNING,
"Couldn't send additional logging to %s", filename);
279 }
else if(default_fd >= 0) {
281 qb_log_ctl(default_fd, QB_LOG_CONF_ENABLED, QB_FALSE);
284 crm_notice(
"Additional logging available in %s", filename);
285 qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
288 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN
290 qb_log_ctl(fd, QB_LOG_CONF_MAX_LINE_LEN, 800);
300 static int blackbox_trigger = 0;
301 static volatile char *blackbox_file_prefix = NULL;
303 #ifdef QB_FEATURE_LOG_HIRES_TIMESTAMPS
310 blackbox_logger(int32_t t,
struct qb_log_callsite *cs,
log_time_t timestamp,
313 if(cs && cs->priority < LOG_ERR) {
321 crm_control_blackbox(
int nsig,
bool enable)
325 if (blackbox_file_prefix == NULL) {
326 pid_t
pid = getpid();
331 (
unsigned long) pid);
334 if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
335 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024);
336 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
339 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
340 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
343 crm_notice(
"Initiated blackbox recorder: %s", blackbox_file_prefix);
354 blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
355 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
356 crm_trace(
"Trigger: %d is %d %d", blackbox_trigger,
357 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
361 }
else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
362 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
365 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
366 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_FALSE);
374 crm_control_blackbox(nsig, TRUE);
380 crm_control_blackbox(nsig, FALSE);
396 static volatile int counter = 1;
397 static volatile time_t last = 0;
400 time_t now = time(NULL);
402 if (blackbox_file_prefix == NULL) {
411 if (nsig == 0 && now == last) {
416 snprintf(buffer,
NAME_MAX,
"%s.%d", blackbox_file_prefix, counter++);
417 if (nsig == SIGTRAP) {
418 crm_notice(
"Blackbox dump requested, please see %s for contents", buffer);
422 "Problem detected at %s:%d (%s), please see %s for additional details",
423 cs->function, cs->lineno, cs->filename, buffer);
425 crm_notice(
"Problem detected, please see %s for additional details", buffer);
429 qb_log_blackbox_write_to_file(buffer);
434 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
435 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
443 qb_log_blackbox_write_to_file((
const char *)blackbox_file_prefix);
444 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
453 return crm_log_init(entity, LOG_ERR, FALSE, FALSE, 0, NULL, TRUE);
457 crm_quark_to_string(uint32_t tag)
459 const char *text = g_quark_to_string(tag);
468 crm_log_filter_source(
int source,
const char *trace_files,
const char *trace_fns,
469 const char *trace_fmts,
const char *trace_tags,
const char *trace_blackbox,
470 struct qb_log_callsite *cs)
472 if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
476 qb_bit_set(cs->targets, source);
478 }
else if (source == blackbox_trigger && blackbox_trigger > 0) {
480 if (cs->priority <= LOG_ERR) {
481 qb_bit_set(cs->targets, source);
483 }
else if (trace_blackbox) {
486 if (strstr(trace_blackbox, key) != NULL) {
487 qb_bit_set(cs->targets, source);
492 }
else if (source == QB_LOG_SYSLOG) {
494 qb_bit_set(cs->targets, source);
498 qb_bit_set(cs->targets, source);
499 }
else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
500 qb_bit_set(cs->targets, source);
501 }
else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
502 qb_bit_set(cs->targets, source);
503 }
else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
504 qb_bit_set(cs->targets, source);
505 }
else if (trace_tags
508 qb_bit_set(cs->targets, source);
513 crm_log_filter(
struct qb_log_callsite *cs)
516 static int need_init = 1;
517 static const char *trace_fns = NULL;
518 static const char *trace_tags = NULL;
519 static const char *trace_fmts = NULL;
520 static const char *trace_files = NULL;
521 static const char *trace_blackbox = NULL;
525 trace_fns = getenv(
"PCMK_trace_functions");
526 trace_fmts = getenv(
"PCMK_trace_formats");
527 trace_tags = getenv(
"PCMK_trace_tags");
528 trace_files = getenv(
"PCMK_trace_files");
529 trace_blackbox = getenv(
"PCMK_trace_blackbox");
531 if (trace_tags != NULL) {
534 const char *offset = NULL;
535 const char *next = trace_tags;
540 snprintf(token,
sizeof(token),
"%.*s", (
int)(next - offset), offset);
542 tag = g_quark_from_string(token);
543 crm_info(
"Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
549 }
while (next != NULL && next[0] != 0);
554 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
555 crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
563 gboolean refilter = FALSE;
569 if (cs->priority != level) {
570 cs->priority = level;
574 if (cs->tags != tags) {
583 if (cs->targets == 0) {
592 static gboolean log = TRUE;
597 (
"Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
598 crm_log_level, getenv(
"PCMK_trace_files"), getenv(
"PCMK_trace_functions"),
599 getenv(
"PCMK_trace_formats"), getenv(
"PCMK_trace_tags"));
601 qb_log_filter_fn_set(crm_log_filter);
605 crm_tracing_enabled(
void)
609 }
else if (getenv(
"PCMK_trace_files") || getenv(
"PCMK_trace_functions")
610 || getenv(
"PCMK_trace_formats") || getenv(
"PCMK_trace_tags")) {
617 crm_priority2int(
const char *
name)
619 struct syslog_names {
623 static struct syslog_names p_names[] = {
624 {
"emerg", LOG_EMERG},
625 {
"alert", LOG_ALERT},
628 {
"warning", LOG_WARNING},
629 {
"notice", LOG_NOTICE},
631 {
"debug", LOG_DEBUG},
636 for (lpc = 0; name != NULL && p_names[lpc].name != NULL; lpc++) {
637 if (
crm_str_eq(p_names[lpc].name, name, TRUE)) {
638 return p_names[lpc].priority;
646 crm_identity(
const char *entity,
int argc,
char **argv)
655 }
else if (argc > 0 && argv != NULL) {
656 char *
mutable = strdup(argv[0]);
657 char *modified = basename(
mutable);
659 if (strstr(modified,
"lt-") == modified) {
681 int32_t qb_facility = 0;
683 static bool have_logging = FALSE;
685 if(have_logging == FALSE) {
691 crm_trace_nonlog = g_quark_from_static_string(
"Pacemaker non-logging tracepoint");
694 umask(S_IWGRP | S_IWOTH | S_IROTH);
700 g_log_set_always_fatal((GLogLevelFlags) 0);
703 crm_identity(entity, argc, argv);
705 qb_facility = qb_log_facility2int(
"local0");
710 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
711 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN
713 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_MAX_LINE_LEN, 256);
719 qb_log_tags_stringify_fn_set(crm_quark_to_string);
720 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
721 qb_log_ctl(lpc, QB_LOG_CONF_THREADED, QB_FALSE);
722 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_ELLIPSIS
724 qb_log_ctl(lpc, QB_LOG_CONF_ELLIPSIS, QB_TRUE);
733 int argc,
char **argv, gboolean quiet)
735 const char *syslog_priority = NULL;
738 const char *f_copy = facility;
751 if (facility == NULL) {
765 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(facility));
775 if(syslog_priority) {
776 int priority = crm_priority2int(syslog_priority);
778 qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE,
"*", priority);
780 qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE,
"*", LOG_NOTICE);
785 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
810 crm_trace(
"Quiet: %d, facility %s", quiet, f_copy);
822 const char *user = getenv(
"USER");
825 crm_trace(
"Not switching to corefile directory for %s", user);
833 struct passwd *pwent = getpwuid(user);
836 crm_perror(LOG_ERR,
"Cannot get name for uid: %d", user);
840 crm_trace(
"Don't change active directory for regular user: %s", pwent->pw_name);
842 }
else if (chdir(base) < 0) {
843 crm_perror(LOG_INFO,
"Cannot change active directory to %s", base);
846 crm_info(
"Changed active directory to %s", base);
851 snprintf(path, 512,
"%s-%lu",
crm_system_name, (
unsigned long) getpid());
854 crm_info(
"Changed active directory to %s/%s/%s", base, pwent->pw_name, path);
894 if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
895 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
898 }
else if (enable == FALSE) {
899 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
906 static int args = TRUE;
909 if (args && argc > 1) {
913 if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
927 #define ARGS_FMT "Invoked: %s"
933 int existing_len = 0;
935 static int logged = 0;
937 char *arg_string = NULL;
939 if (argc == 0 || argv == NULL || logged) {
947 for (; lpc < argc; lpc++) {
948 if (argv[lpc] == NULL) {
952 len = 2 + strlen(argv[lpc]);
953 arg_string = realloc_safe(arg_string, len + existing_len);
954 existing_len += sprintf(arg_string + existing_len,
"%s ", argv[lpc]);
957 qb_log_from_external_source(__func__, __FILE__,
ARGS_FMT, LOG_NOTICE, line, 0, arg_string);
963 crm_log_output_fn(
const char *file,
const char *
function,
int line,
int level,
const char *prefix,
966 const char *next = NULL;
967 const char *offset = NULL;
973 if (output == NULL) {
977 output =
"-- empty --";
985 (
int)(next - offset), offset);
990 }
while (next != NULL && next[0] != 0);
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
#define crm_notice(fmt, args...)
const char * pcmk_strerror(int rc)
void crm_enable_stderr(int enable)
gboolean safe_str_neq(const char *a, const char *b)
gboolean mainloop_add_signal(int sig, void(*dispatch)(int sig))
gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr, int argc, char **argv, gboolean quiet)
GLogFunc glib_log_default
void pcmk__set_env_option(const char *option, const char *value)
Set or unset a Pacemaker environment variable option.
#define CRM_LOG_ASSERT(expr)
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
int pcmk_daemon_user(uid_t *uid, gid_t *gid)
Get user and group IDs of pacemaker daemon user.
unsigned int crm_trace_nonlog
const char * pcmk__env_option(const char *option)
Wrappers for and extensions to glib mainloop.
gboolean crm_log_cli_init(const char *entity)
void crm_bump_log_level(int argc, char **argv)
void crm_log_deinit(void)
#define crm_warn(fmt, args...)
int daemon(int nochdir, int noclose)
#define crm_debug(fmt, args...)
void crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix, const char *output)
#define crm_trace(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
int setenv(const char *name, const char *value, int why)
void crm_enable_blackbox(int nsig)
sighandler_t crm_signal_handler(int sig, sighandler_t dispatch)
void crm_log_args(int argc, char **argv)
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
unsigned int set_crm_log_level(unsigned int level)
void crm_log_preinit(const char *entity, int argc, char **argv)
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
unsigned int get_crm_log_level(void)
unsigned int crm_log_level
void crm_disable_blackbox(int nsig)
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
#define crm_err(fmt, args...)
char * strchrnul(const char *s, int c_in)
unsigned int crm_log_priority
#define safe_str_eq(a, b)
gboolean crm_add_logfile(const char *filename)
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
void crm_update_callsites(void)
#define crm_info(fmt, args...)
bool pcmk__env_option_enabled(const char *daemon, const char *option)