12 #include <sys/param.h> 13 #include <sys/types.h> 16 #include <sys/utsname.h> 31 #include <qb/qbdefs.h> 37 #ifdef QB_FEATURE_LOG_HIRES_TIMESTAMPS 38 #define TIMESTAMP_FORMAT_SPEC "%%T" 41 #define TIMESTAMP_FORMAT_SPEC "%%t" 49 static unsigned int crm_log_priority = LOG_NOTICE;
50 static GLogFunc glib_log_default = NULL;
52 static gboolean crm_tracing_enabled(
void);
55 crm_glib_handler(
const gchar * log_domain, GLogLevelFlags
flags,
const gchar * message,
58 int log_level = LOG_WARNING;
59 GLogLevelFlags msg_level = (
flags & G_LOG_LEVEL_MASK);
60 static struct qb_log_callsite *glib_cs = NULL;
62 if (glib_cs == NULL) {
63 glib_cs = qb_log_callsite_get(__func__, __FILE__,
"glib-handler",
69 case G_LOG_LEVEL_CRITICAL:
74 crm_abort(__FILE__, __func__, __LINE__, message, TRUE, TRUE);
78 case G_LOG_LEVEL_ERROR:
81 case G_LOG_LEVEL_MESSAGE:
82 log_level = LOG_NOTICE;
84 case G_LOG_LEVEL_INFO:
87 case G_LOG_LEVEL_DEBUG:
88 log_level = LOG_DEBUG;
91 case G_LOG_LEVEL_WARNING:
92 case G_LOG_FLAG_RECURSION:
93 case G_LOG_FLAG_FATAL:
94 case G_LOG_LEVEL_MASK:
95 log_level = LOG_WARNING;
99 do_crm_log(log_level,
"%s: %s", log_domain, message);
103 # define NAME_MAX 256 115 crm_trigger_blackbox(
int nsig)
117 if(nsig == SIGTRAP) {
127 if (glib_log_default != NULL) {
128 g_log_set_default_handler(glib_log_default, NULL);
147 set_format_string(
int method,
const char *
daemon, pid_t use_pid,
148 const char *use_nodename)
150 if (method == QB_LOG_SYSLOG) {
152 crm_extended_logging(method, QB_FALSE);
153 qb_log_format_set(method,
"%g %p: %b");
161 if (method > QB_LOG_STDERR) {
163 offset += snprintf(fmt + offset,
FMT_MAX - offset,
165 use_nodename,
daemon, (
unsigned long) use_pid);
169 offset += snprintf(fmt + offset,
FMT_MAX - offset,
"(%%n");
170 if (crm_tracing_enabled()) {
172 offset += snprintf(fmt + offset,
FMT_MAX - offset,
"@%%f:%%l");
174 offset += snprintf(fmt + offset,
FMT_MAX - offset,
")");
177 offset += snprintf(fmt + offset,
FMT_MAX - offset,
" %%g\t%%p: %%b");
180 qb_log_format_set(method, fmt);
184 #define DEFAULT_LOG_FILE CRM_LOG_DIR "/pacemaker.log" 187 logfile_disabled(
const char *filename)
203 chown_logfile(
const char *filename,
int logfd)
211 if (fstat(logfd, &
st) < 0) {
220 crm_warn(
"Not changing '%s' ownership because user information " 224 if ((
st.st_gid == pcmk_gid)
225 && ((
st.st_mode & S_IRWXG) == (S_IRGRP|S_IWGRP))) {
228 if (fchown(logfd, pcmk_uid, pcmk_gid) < 0) {
229 crm_warn(
"Couldn't change '%s' ownership to user %s gid %d: %s",
237 chmod_logfile(
const char *filename,
int logfd)
239 const char *modestr = getenv(
"PCMK_logfile_mode");
240 mode_t filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
242 if (modestr != NULL) {
243 long filemode_l = strtol(modestr, NULL, 8);
245 if ((filemode_l != LONG_MIN) && (filemode_l != LONG_MAX)) {
246 filemode = (mode_t) filemode_l;
249 if ((filemode != 0) && (fchmod(logfd, filemode) < 0)) {
250 crm_warn(
"Couldn't change '%s' mode to %04o: %s",
251 filename, filemode,
strerror(errno));
257 set_logfile_permissions(
const char *filename, FILE *logfile)
259 if (geteuid() == 0) {
260 int logfd = fileno(logfile);
261 int rc = chown_logfile(filename, logfd);
266 chmod_logfile(filename, logfd);
273 enable_logfile(
int fd)
275 qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
277 qb_log_ctl(fd, QB_LOG_CONF_FILE_SYNC, 1);
280 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN 282 qb_log_ctl(fd, QB_LOG_CONF_MAX_LINE_LEN, 800);
289 disable_logfile(
int fd)
291 qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_FALSE);
295 setenv_logfile(
const char *filename)
320 FILE *logfile = NULL;
321 bool is_default =
false;
323 static int default_fd = -1;
324 static bool have_logfile =
false;
327 if (filename == NULL) {
335 if (logfile_disabled(filename)) {
341 if (is_default && (default_fd >= 0)) {
346 logfile = fopen(filename,
"a");
347 if (logfile == NULL) {
349 crm_warn(
"Logging to '%s' is disabled: %s " CRM_XS " uid=%u gid=%u",
350 filename,
strerror(rc), geteuid(), getegid());
354 rc = set_logfile_permissions(filename, logfile);
356 crm_warn(
"Logging to '%s' is disabled: %s " CRM_XS " permissions",
364 fd = qb_log_file_open(filename);
366 crm_warn(
"Logging to '%s' is disabled: %s " CRM_XS " qb_log_file_open",
373 setenv_logfile(filename);
375 }
else if (default_fd >= 0) {
376 crm_notice(
"Switching logging to %s", filename);
377 disable_logfile(default_fd);
380 crm_notice(
"Additional logging available in %s", filename);
386 static int blackbox_trigger = 0;
387 static volatile char *blackbox_file_prefix = NULL;
390 blackbox_logger(int32_t t,
struct qb_log_callsite *cs,
log_time_t timestamp,
393 if(cs && cs->priority < LOG_ERR) {
401 crm_control_blackbox(
int nsig,
bool enable)
405 if (blackbox_file_prefix == NULL) {
406 pid_t
pid = getpid();
411 (
unsigned long)
pid);
414 if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
415 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024);
416 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
419 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
420 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
423 crm_notice(
"Initiated blackbox recorder: %s", blackbox_file_prefix);
434 blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
435 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
436 crm_trace(
"Trigger: %d is %d %d", blackbox_trigger,
437 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
441 }
else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
442 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
445 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
446 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_FALSE);
454 crm_control_blackbox(nsig, TRUE);
460 crm_control_blackbox(nsig, FALSE);
476 static volatile int counter = 1;
477 static volatile time_t last = 0;
480 time_t now = time(NULL);
482 if (blackbox_file_prefix == NULL) {
491 if (nsig == 0 && now == last) {
496 snprintf(buffer,
NAME_MAX,
"%s.%d", blackbox_file_prefix, counter++);
497 if (nsig == SIGTRAP) {
498 crm_notice(
"Blackbox dump requested, please see %s for contents", buffer);
502 "Problem detected at %s:%d (%s), please see %s for additional details",
503 cs->function, cs->lineno, cs->filename, buffer);
505 crm_notice(
"Problem detected, please see %s for additional details", buffer);
509 qb_log_blackbox_write_to_file(buffer);
514 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
515 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
523 qb_log_blackbox_write_to_file((
const char *)blackbox_file_prefix);
524 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
531 crm_quark_to_string(uint32_t tag)
533 const char *text = g_quark_to_string(tag);
542 crm_log_filter_source(
int source,
const char *trace_files,
const char *trace_fns,
543 const char *trace_fmts,
const char *trace_tags,
const char *trace_blackbox,
544 struct qb_log_callsite *cs)
546 if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
550 qb_bit_set(cs->targets, source);
552 }
else if (source == blackbox_trigger && blackbox_trigger > 0) {
554 if (cs->priority <= LOG_ERR) {
555 qb_bit_set(cs->targets, source);
557 }
else if (trace_blackbox) {
560 if (strstr(trace_blackbox, key) != NULL) {
561 qb_bit_set(cs->targets, source);
566 }
else if (source == QB_LOG_SYSLOG) {
567 if (cs->priority <= crm_log_priority && cs->priority <=
crm_log_level) {
568 qb_bit_set(cs->targets, source);
572 qb_bit_set(cs->targets, source);
573 }
else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
574 qb_bit_set(cs->targets, source);
575 }
else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
576 qb_bit_set(cs->targets, source);
577 }
else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
578 qb_bit_set(cs->targets, source);
579 }
else if (trace_tags
582 qb_bit_set(cs->targets, source);
587 crm_log_filter(
struct qb_log_callsite *cs)
590 static int need_init = 1;
591 static const char *trace_fns = NULL;
592 static const char *trace_tags = NULL;
593 static const char *trace_fmts = NULL;
594 static const char *trace_files = NULL;
595 static const char *trace_blackbox = NULL;
599 trace_fns = getenv(
"PCMK_trace_functions");
600 trace_fmts = getenv(
"PCMK_trace_formats");
601 trace_tags = getenv(
"PCMK_trace_tags");
602 trace_files = getenv(
"PCMK_trace_files");
603 trace_blackbox = getenv(
"PCMK_trace_blackbox");
605 if (trace_tags != NULL) {
608 const char *offset = NULL;
609 const char *next = trace_tags;
614 snprintf(token,
sizeof(token),
"%.*s", (
int)(next - offset), offset);
616 tag = g_quark_from_string(token);
617 crm_info(
"Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
623 }
while (next != NULL && next[0] != 0);
628 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
629 crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
637 gboolean refilter = FALSE;
643 if (cs->priority != level) {
644 cs->priority = level;
648 if (cs->tags != tags) {
657 if (cs->targets == 0) {
666 static gboolean log = TRUE;
671 (
"Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
672 crm_log_level, getenv(
"PCMK_trace_files"), getenv(
"PCMK_trace_functions"),
673 getenv(
"PCMK_trace_formats"), getenv(
"PCMK_trace_tags"));
675 qb_log_filter_fn_set(crm_log_filter);
679 crm_tracing_enabled(
void)
683 }
else if (getenv(
"PCMK_trace_files") || getenv(
"PCMK_trace_functions")
684 || getenv(
"PCMK_trace_formats") || getenv(
"PCMK_trace_tags")) {
691 crm_priority2int(
const char *
name)
693 struct syslog_names {
697 static struct syslog_names p_names[] = {
698 {
"emerg", LOG_EMERG},
699 {
"alert", LOG_ALERT},
702 {
"warning", LOG_WARNING},
703 {
"notice", LOG_NOTICE},
705 {
"debug", LOG_DEBUG},
710 for (lpc = 0;
name != NULL && p_names[lpc].name != NULL; lpc++) {
712 return p_names[lpc].priority;
715 return crm_log_priority;
736 set_identity(
const char *entity,
int argc,
char *
const *argv)
742 if (entity != NULL) {
745 }
else if ((argc > 0) && (argv != NULL)) {
746 char *
mutable = strdup(argv[0]);
747 char *modified = basename(
mutable);
749 if (strstr(modified,
"lt-") == modified) {
771 int32_t qb_facility = 0;
772 pid_t
pid = getpid();
773 const char *nodename =
"localhost";
774 static bool have_logging =
false;
785 crm_trace_nonlog = g_quark_from_static_string(
"Pacemaker non-logging tracepoint");
788 umask(S_IWGRP | S_IWOTH | S_IROTH);
791 glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL);
794 g_log_set_always_fatal((GLogLevelFlags) 0);
799 set_identity(entity, argc, argv);
801 qb_facility = qb_log_facility2int(
"local0");
806 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
807 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN 809 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_MAX_LINE_LEN, 256);
811 if (
uname(memset(&res, 0,
sizeof(res))) == 0 && *res.nodename !=
'\0') {
812 nodename = res.nodename;
818 qb_log_tags_stringify_fn_set(crm_quark_to_string);
819 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
820 qb_log_ctl(lpc, QB_LOG_CONF_THREADED, QB_FALSE);
821 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_ELLIPSIS 823 qb_log_ctl(lpc, QB_LOG_CONF_ELLIPSIS, QB_TRUE);
836 setlocale(LC_ALL,
"");
851 int argc,
char **argv, gboolean quiet)
853 const char *syslog_priority = NULL;
855 const char *f_copy = facility;
868 if (facility == NULL) {
882 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(facility));
892 if (syslog_priority) {
893 crm_log_priority = crm_priority2int(syslog_priority);
895 qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE,
"*",
900 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
927 crm_trace(
"Quiet: %d, facility %s", quiet, f_copy);
937 const char *user = getenv(
"USER");
940 crm_trace(
"Not switching to corefile directory for %s", user);
947 struct passwd *pwent = getpwuid(user);
950 crm_perror(LOG_ERR,
"Cannot get name for uid: %d", user);
953 crm_trace(
"Don't change active directory for regular user: %s", pwent->pw_name);
1000 if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
1001 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
1004 }
else if (enable == FALSE) {
1005 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
1021 if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0)
1022 != QB_LOG_STATE_ENABLED) {
1047 static bool logged =
false;
1048 gchar *arg_string = NULL;
1050 if ((argc == 0) || (argv == NULL) || logged) {
1054 arg_string = g_strjoinv(
" ", argv);
1063 const char *next = NULL;
1064 const char *offset = NULL;
1070 if (output == NULL) {
1074 output =
"-- empty --";
1082 (
int)(next - offset), offset);
1087 }
while (next != NULL && next[0] != 0);
1095 for (
int i = 0; i < verbosity; i++) {
void pcmk__cli_init_logging(const char *name, unsigned int verbosity)
#define crm_notice(fmt, args...)
#define PCMK__ENV_LOGFILE
gboolean mainloop_add_signal(int sig, void(*dispatch)(int sig))
void crm_enable_blackbox(int nsig)
unsigned int get_crm_log_level(void)
void crm_disable_blackbox(int nsig)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
int pcmk__add_logfile(const char *filename)
Add a file to be used as a Pacemaker detail log.
void crm_xml_init(void)
Initialize the CRM XML subsystem.
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
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 bindtextdomain(Domainname, Dirname)
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
#define bind_textdomain_codeset(Domainname, Codeset)
int pcmk_daemon_user(uid_t *uid, gid_t *gid)
Get user and group IDs of pacemaker daemon user.
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
char * strerror(int errnum)
const char * pcmk__env_option(const char *option)
Deprecated Pacemaker logging API.
Wrappers for and extensions to glib mainloop.
gboolean crm_add_logfile(const char *filename)
void crm_log_preinit(const char *entity, int argc, char *const *argv)
Initializes the logging system and defaults to the least verbose output level.
void crm_log_args(int argc, char **argv)
Log the command line (once)
#define textdomain(Domainname)
#define PCMK__ENV_BLACKBOX
#define crm_warn(fmt, args...)
gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr, int argc, char **argv, gboolean quiet)
int daemon(int nochdir, int noclose)
#define crm_debug(fmt, args...)
unsigned int crm_log_level
void crm_enable_stderr(int enable)
#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)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
unsigned int crm_trace_nonlog
sighandler_t crm_signal_handler(int sig, sighandler_t dispatch)
#define TIMESTAMP_FORMAT_SPEC
void crm_update_callsites(void)
#define PCMK__ENV_LOGPRIORITY
int pcmk_legacy2rc(int legacy_rc)
void crm_write_blackbox(int nsig, const struct qb_log_callsite *cs)
void crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix, const char *output)
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
gboolean crm_log_cli_init(const char *entity)
char * strchrnul(const char *s, int c_in)
unsigned int set_crm_log_level(unsigned int level)
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
void crm_bump_log_level(int argc, char **argv)
Make logging more verbose.
#define crm_info(fmt, args...)
void crm_log_deinit(void)
bool pcmk__env_option_enabled(const char *daemon, const char *option)
#define PCMK__ENV_LOGFACILITY