12 #include <sys/param.h> 13 #include <sys/types.h> 16 #include <sys/utsname.h> 31 #include <qb/qbdefs.h> 40 static unsigned int crm_log_priority = LOG_NOTICE;
41 static GLogFunc glib_log_default = NULL;
43 static gboolean crm_tracing_enabled(
void);
46 crm_glib_handler(
const gchar * log_domain, GLogLevelFlags
flags,
const gchar * message,
49 int log_level = LOG_WARNING;
50 GLogLevelFlags msg_level = (
flags & G_LOG_LEVEL_MASK);
51 static struct qb_log_callsite *glib_cs = NULL;
53 if (glib_cs == NULL) {
54 glib_cs = qb_log_callsite_get(__func__, __FILE__,
"glib-handler",
60 case G_LOG_LEVEL_CRITICAL:
65 crm_abort(__FILE__, __func__, __LINE__, message, TRUE, TRUE);
69 case G_LOG_LEVEL_ERROR:
72 case G_LOG_LEVEL_MESSAGE:
73 log_level = LOG_NOTICE;
75 case G_LOG_LEVEL_INFO:
78 case G_LOG_LEVEL_DEBUG:
79 log_level = LOG_DEBUG;
82 case G_LOG_LEVEL_WARNING:
83 case G_LOG_FLAG_RECURSION:
84 case G_LOG_FLAG_FATAL:
85 case G_LOG_LEVEL_MASK:
86 log_level = LOG_WARNING;
90 do_crm_log(log_level,
"%s: %s", log_domain, message);
106 crm_trigger_blackbox(
int nsig)
108 if(nsig == SIGTRAP) {
118 if (glib_log_default != NULL) {
119 g_log_set_default_handler(glib_log_default, NULL);
126 set_format_string(
int method,
const char *
daemon)
128 if (method == QB_LOG_SYSLOG) {
130 crm_extended_logging(method, QB_FALSE);
131 qb_log_format_set(method,
"%g %p: %b");
139 if (method > QB_LOG_STDERR) {
141 const char *nodename =
"localhost";
143 if (
uname(&res) == 0) {
144 nodename = res.nodename;
148 offset += snprintf(fmt + offset,
FMT_MAX - offset,
149 "%%t %s %-20s[%lu] ",
150 nodename,
daemon, (
unsigned long) getpid());
154 offset += snprintf(fmt + offset,
FMT_MAX - offset,
"(%%n");
155 if (crm_tracing_enabled()) {
157 offset += snprintf(fmt + offset,
FMT_MAX - offset,
"@%%f:%%l");
159 offset += snprintf(fmt + offset,
FMT_MAX - offset,
")");
162 offset += snprintf(fmt + offset,
FMT_MAX - offset,
" %%g\t%%p: %%b");
165 qb_log_format_set(method, fmt);
169 #define DEFAULT_LOG_FILE CRM_LOG_DIR "/pacemaker.log" 174 bool is_default =
false;
175 static int default_fd = -1;
176 static gboolean have_logfile = FALSE;
180 FILE *logfile = NULL;
181 char *parent_dir = NULL;
184 if (filename == NULL && have_logfile == FALSE) {
188 if ((filename == NULL)
197 if(is_default && default_fd >= 0) {
202 filename_cp = strdup(filename);
203 parent_dir = dirname(filename_cp);
204 rc = stat(parent_dir, &parent);
207 crm_err(
"Directory '%s' does not exist: logging to '%s' is disabled", parent_dir, filename);
214 logfile = fopen(filename,
"a");
215 if(logfile == NULL) {
216 crm_err(
"%s (%d): Logging to '%s' as uid=%u, gid=%u is disabled",
217 pcmk_strerror(errno), errno, filename, geteuid(), getegid());
222 if (geteuid() == 0) {
226 gboolean fix = FALSE;
227 int logfd = fileno(logfile);
229 mode_t filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
231 rc = fstat(logfd, &
st);
233 crm_perror(LOG_WARNING,
"Cannot stat %s", filename);
239 if (
st.st_gid != pcmk_gid) {
242 }
else if ((
st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
248 modestr = getenv(
"PCMK_logfile_mode");
250 long filemode_l = strtol(modestr, NULL, 8);
251 if (filemode_l != LONG_MIN && filemode_l != LONG_MAX) {
252 filemode = (mode_t)filemode_l;
257 rc = fchown(logfd, pcmk_uid, pcmk_gid);
259 crm_warn(
"Cannot change the ownership of %s to user %s and gid %d",
265 rc = fchmod(logfd, filemode);
267 crm_warn(
"Cannot change the mode of %s to %o", filename, filemode);
270 fprintf(logfile,
"Set r/w permissions for uid=%d, gid=%d on %s\n",
271 pcmk_uid, pcmk_gid, filename);
272 if (fflush(logfile) < 0 || fsync(logfd) < 0) {
273 crm_err(
"Couldn't write out logfile: %s", filename);
280 fd = qb_log_file_open(filename);
283 crm_perror(LOG_WARNING,
"Couldn't send additional logging to %s", filename);
295 }
else if(default_fd >= 0) {
297 qb_log_ctl(default_fd, QB_LOG_CONF_ENABLED, QB_FALSE);
300 crm_notice(
"Additional logging available in %s", filename);
301 qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
304 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN 306 qb_log_ctl(fd, QB_LOG_CONF_MAX_LINE_LEN, 800);
316 static int blackbox_trigger = 0;
317 static volatile char *blackbox_file_prefix = NULL;
319 #ifdef QB_FEATURE_LOG_HIRES_TIMESTAMPS 326 blackbox_logger(int32_t t,
struct qb_log_callsite *cs,
log_time_t timestamp,
329 if(cs && cs->priority < LOG_ERR) {
337 crm_control_blackbox(
int nsig,
bool enable)
341 if (blackbox_file_prefix == NULL) {
342 pid_t
pid = getpid();
347 (
unsigned long)
pid);
350 if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
351 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024);
352 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
355 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
356 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
359 crm_notice(
"Initiated blackbox recorder: %s", blackbox_file_prefix);
370 blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
371 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
372 crm_trace(
"Trigger: %d is %d %d", blackbox_trigger,
373 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
377 }
else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
378 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
381 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
382 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_FALSE);
390 crm_control_blackbox(nsig, TRUE);
396 crm_control_blackbox(nsig, FALSE);
412 static volatile int counter = 1;
413 static volatile time_t last = 0;
416 time_t now = time(NULL);
418 if (blackbox_file_prefix == NULL) {
427 if (nsig == 0 && now == last) {
432 snprintf(buffer,
NAME_MAX,
"%s.%d", blackbox_file_prefix, counter++);
433 if (nsig == SIGTRAP) {
434 crm_notice(
"Blackbox dump requested, please see %s for contents", buffer);
438 "Problem detected at %s:%d (%s), please see %s for additional details",
439 cs->function, cs->lineno, cs->filename, buffer);
441 crm_notice(
"Problem detected, please see %s for additional details", buffer);
445 qb_log_blackbox_write_to_file(buffer);
450 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
451 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
459 qb_log_blackbox_write_to_file((
const char *)blackbox_file_prefix);
460 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
469 return crm_log_init(entity, LOG_ERR, FALSE, FALSE, 0, NULL, TRUE);
473 crm_quark_to_string(uint32_t tag)
475 const char *text = g_quark_to_string(tag);
484 crm_log_filter_source(
int source,
const char *trace_files,
const char *trace_fns,
485 const char *trace_fmts,
const char *trace_tags,
const char *trace_blackbox,
486 struct qb_log_callsite *cs)
488 if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
492 qb_bit_set(cs->targets, source);
494 }
else if (source == blackbox_trigger && blackbox_trigger > 0) {
496 if (cs->priority <= LOG_ERR) {
497 qb_bit_set(cs->targets, source);
499 }
else if (trace_blackbox) {
502 if (strstr(trace_blackbox, key) != NULL) {
503 qb_bit_set(cs->targets, source);
508 }
else if (source == QB_LOG_SYSLOG) {
509 if (cs->priority <= crm_log_priority && cs->priority <=
crm_log_level) {
510 qb_bit_set(cs->targets, source);
514 qb_bit_set(cs->targets, source);
515 }
else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
516 qb_bit_set(cs->targets, source);
517 }
else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
518 qb_bit_set(cs->targets, source);
519 }
else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
520 qb_bit_set(cs->targets, source);
521 }
else if (trace_tags
524 qb_bit_set(cs->targets, source);
529 crm_log_filter(
struct qb_log_callsite *cs)
532 static int need_init = 1;
533 static const char *trace_fns = NULL;
534 static const char *trace_tags = NULL;
535 static const char *trace_fmts = NULL;
536 static const char *trace_files = NULL;
537 static const char *trace_blackbox = NULL;
541 trace_fns = getenv(
"PCMK_trace_functions");
542 trace_fmts = getenv(
"PCMK_trace_formats");
543 trace_tags = getenv(
"PCMK_trace_tags");
544 trace_files = getenv(
"PCMK_trace_files");
545 trace_blackbox = getenv(
"PCMK_trace_blackbox");
547 if (trace_tags != NULL) {
550 const char *offset = NULL;
551 const char *next = trace_tags;
556 snprintf(token,
sizeof(token),
"%.*s", (
int)(next - offset), offset);
558 tag = g_quark_from_string(token);
559 crm_info(
"Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
565 }
while (next != NULL && next[0] != 0);
570 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
571 crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
579 gboolean refilter = FALSE;
585 if (cs->priority != level) {
586 cs->priority = level;
590 if (cs->tags != tags) {
599 if (cs->targets == 0) {
608 static gboolean log = TRUE;
613 (
"Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
614 crm_log_level, getenv(
"PCMK_trace_files"), getenv(
"PCMK_trace_functions"),
615 getenv(
"PCMK_trace_formats"), getenv(
"PCMK_trace_tags"));
617 qb_log_filter_fn_set(crm_log_filter);
621 crm_tracing_enabled(
void)
625 }
else if (getenv(
"PCMK_trace_files") || getenv(
"PCMK_trace_functions")
626 || getenv(
"PCMK_trace_formats") || getenv(
"PCMK_trace_tags")) {
633 crm_priority2int(
const char *
name)
635 struct syslog_names {
639 static struct syslog_names p_names[] = {
640 {
"emerg", LOG_EMERG},
641 {
"alert", LOG_ALERT},
644 {
"warning", LOG_WARNING},
645 {
"notice", LOG_NOTICE},
647 {
"debug", LOG_DEBUG},
652 for (lpc = 0;
name != NULL && p_names[lpc].name != NULL; lpc++) {
654 return p_names[lpc].priority;
657 return crm_log_priority;
662 crm_identity(
const char *entity,
int argc,
char **argv)
671 }
else if (argc > 0 && argv != NULL) {
672 char *
mutable = strdup(argv[0]);
673 char *modified = basename(
mutable);
675 if (strstr(modified,
"lt-") == modified) {
696 int32_t qb_facility = 0;
698 static bool have_logging = FALSE;
700 if(have_logging == FALSE) {
706 crm_trace_nonlog = g_quark_from_static_string(
"Pacemaker non-logging tracepoint");
709 umask(S_IWGRP | S_IWOTH | S_IROTH);
712 glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL);
715 g_log_set_always_fatal((GLogLevelFlags) 0);
718 crm_identity(entity, argc, argv);
720 qb_facility = qb_log_facility2int(
"local0");
725 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
726 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN 728 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_MAX_LINE_LEN, 256);
734 qb_log_tags_stringify_fn_set(crm_quark_to_string);
735 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
736 qb_log_ctl(lpc, QB_LOG_CONF_THREADED, QB_FALSE);
737 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_ELLIPSIS 739 qb_log_ctl(lpc, QB_LOG_CONF_ELLIPSIS, QB_TRUE);
748 int argc,
char **argv, gboolean quiet)
750 const char *syslog_priority = NULL;
752 const char *f_copy = facility;
765 if (facility == NULL) {
779 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(facility));
789 if (syslog_priority) {
790 crm_log_priority = crm_priority2int(syslog_priority);
792 qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE,
"*",
797 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
824 crm_trace(
"Quiet: %d, facility %s", quiet, f_copy);
834 const char *user = getenv(
"USER");
837 crm_trace(
"Not switching to corefile directory for %s", user);
845 struct passwd *pwent = getpwuid(user);
848 crm_perror(LOG_ERR,
"Cannot get name for uid: %d", user);
851 crm_trace(
"Don't change active directory for regular user: %s", pwent->pw_name);
853 }
else if (chdir(base) < 0) {
854 crm_perror(LOG_INFO,
"Cannot change active directory to %s", base);
857 crm_info(
"Changed active directory to %s", base);
862 snprintf(path, 512,
"%s-%lu",
crm_system_name, (
unsigned long) getpid());
865 crm_info(
"Changed active directory to %s/%s/%s", base, pwent->pw_name, path);
908 if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
909 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
912 }
else if (enable == FALSE) {
913 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
929 if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0)
930 != QB_LOG_STATE_ENABLED) {
955 static bool logged =
false;
956 gchar *arg_string = NULL;
958 if ((argc == 0) || (argv == NULL) || logged) {
962 arg_string = g_strjoinv(
" ", argv);
968 crm_log_output_fn(
const char *file,
const char *
function,
int line,
int level,
const char *prefix,
971 const char *next = NULL;
972 const char *offset = NULL;
978 if (output == NULL) {
982 output =
"-- empty --";
990 (
int)(next - offset), offset);
995 }
while (next != NULL && next[0] != 0);
#define crm_notice(fmt, args...)
const char * pcmk_strerror(int rc)
void crm_log_preinit(const char *entity, int argc, char **argv)
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
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)
void crm_write_blackbox(int nsig, struct qb_log_callsite *cs)
#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.
const char * pcmk__env_option(const char *option)
Wrappers for and extensions to glib mainloop.
gboolean crm_add_logfile(const char *filename)
void crm_log_args(int argc, char **argv)
Log the command line (once)
#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)
unsigned int crm_trace_nonlog
sighandler_t crm_signal_handler(int sig, sighandler_t dispatch)
void crm_update_callsites(void)
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)
#define crm_err(fmt, args...)
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)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
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)