1 /*****************************************************************************\ 2 * log.h - configurable logging for slurm: log to file, stderr and/or syslog. 3 ***************************************************************************** 4 * Copyright (C) 2002-2007 The Regents of the University of California. 5 * Copyright (C) 2008-2010 Lawrence Livermore National Security. 6 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 7 * Written by Mark Grondona <mgrondona@llnl.gov> 8 * CODE-OCEC-09-009. All rights reserved. 9 * 10 * Much of this code was derived or adapted from the log.c component of 11 * openssh which contains the following notices: 12 ***************************************************************************** 13 * Author: Tatu Ylonen <ylo@cs.hut.fi> 14 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 15 * All rights reserved 16 * 17 * As far as I am concerned, the code I have written for this software 18 * can be used freely for any purpose. Any derived versions of this 19 * software must be clearly marked as such, and if the derived work is 20 * incompatible with the protocol description in the RFC file, it must be 21 * called by a name other than "ssh" or "Secure Shell". 22 ***************************************************************************** 23 * Copyright (c) 2000 Markus Friedl. All rights reserved. 24 * 25 * Redistribution and use in source and binary forms, with or without 26 * modification, are permitted provided that the following conditions 27 * are met: 28 * 1. Redistributions of source code must retain the above copyright 29 * notice, this list of conditions and the following disclaimer. 30 * 2. Redistributions in binary form must reproduce the above copyright 31 * notice, this list of conditions and the following disclaimer in the 32 * documentation and/or other materials provided with the distribution. 33 * 34 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 35 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 36 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 37 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 39 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 40 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 41 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 42 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 43 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 \*****************************************************************************/ 45 46 #ifndef _LOG_H 47 #define _LOG_H 48 49 #include <syslog.h> 50 #include <stdio.h> 51 52 #include "src/common/macros.h" 53 #include "src/common/cbuf.h" 54 55 /* supported syslog facilities and levels */ 56 typedef enum { 57 SYSLOG_FACILITY_DAEMON = LOG_DAEMON, 58 SYSLOG_FACILITY_USER = LOG_USER, 59 SYSLOG_FACILITY_AUTH = LOG_AUTH, 60 #ifdef LOG_AUTHPRIV 61 SYSLOG_FACILITY_AUTHPRIV = LOG_AUTHPRIV, 62 #endif 63 SYSLOG_FACILITY_LOCAL0 = LOG_LOCAL0, 64 SYSLOG_FACILITY_LOCAL1 = LOG_LOCAL1, 65 SYSLOG_FACILITY_LOCAL2 = LOG_LOCAL2, 66 SYSLOG_FACILITY_LOCAL3 = LOG_LOCAL3, 67 SYSLOG_FACILITY_LOCAL4 = LOG_LOCAL4, 68 SYSLOG_FACILITY_LOCAL5 = LOG_LOCAL5, 69 SYSLOG_FACILITY_LOCAL6 = LOG_LOCAL6, 70 SYSLOG_FACILITY_LOCAL7 = LOG_LOCAL7 71 } log_facility_t; 72 73 /* 74 * log levels, logging will occur at or below the selected level 75 * QUIET disable logging completely. 76 */ 77 typedef enum { 78 LOG_LEVEL_QUIET = 0, 79 LOG_LEVEL_FATAL, 80 LOG_LEVEL_ERROR, 81 LOG_LEVEL_INFO, 82 LOG_LEVEL_VERBOSE, 83 LOG_LEVEL_DEBUG, 84 LOG_LEVEL_DEBUG2, 85 LOG_LEVEL_DEBUG3, 86 LOG_LEVEL_DEBUG4, 87 LOG_LEVEL_DEBUG5, 88 LOG_LEVEL_END 89 } log_level_t; 90 91 92 /* 93 * log options: Each of stderr, syslog, and logfile can have a different level 94 */ 95 typedef struct { 96 log_level_t stderr_level; /* max level to log to stderr */ 97 log_level_t syslog_level; /* max level to log to syslog */ 98 log_level_t logfile_level; /* max level to log to logfile */ 99 bool prefix_level; /* prefix level (e.g. "debug: ") if true */ 100 bool buffered; /* use internal buffer to never block */ 101 } log_options_t; 102 103 extern char *slurm_prog_name; 104 105 /* some useful initializers for log_options_t 106 */ 107 #define LOG_OPTS_INITIALIZER \ 108 { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_INFO, 1, 0 } 109 110 #define LOG_OPTS_SYSLOG_DEFAULT \ 111 { LOG_LEVEL_QUIET, LOG_LEVEL_INFO, LOG_LEVEL_QUIET, 1, 0 } 112 113 #define LOG_OPTS_STDERR_ONLY \ 114 { LOG_LEVEL_INFO, LOG_LEVEL_QUIET, LOG_LEVEL_QUIET, 1, 0 } 115 116 #define SCHEDLOG_OPTS_INITIALIZER \ 117 { LOG_LEVEL_QUIET, LOG_LEVEL_QUIET, LOG_LEVEL_QUIET, 0, 1 } 118 119 120 /* Functions for filling in a char buffer with a timestamp. */ 121 size_t rfc2822_timestamp(char *, size_t); 122 size_t log_timestamp(char *, size_t); 123 124 125 /* 126 * initialize log module (called only once) 127 * 128 * example: 129 * 130 * To initialize log module to print fatal messages to stderr, and 131 * all messages up to and including info() to syslog: 132 * 133 * log_options_t logopts = LOG_OPTS_INITIALIZER; 134 * logopts.stderr_level = LOG_LEVEL_FATAL; 135 * logopts.syslog_level = LOG_LEVEL_INFO; 136 * 137 * rc = log_init(argv[0], logopts, SYSLOG_FACILITY_DAEMON, NULL); 138 * 139 * log function automatically takes the basename() of argv0. 140 */ 141 int log_init(char *argv0, log_options_t opts, 142 log_facility_t fac, char *logfile); 143 144 /* 145 * initialize scheduler log module (called only once) 146 */ 147 int sched_log_init(char *argv0, log_options_t opts, log_facility_t fac, 148 char *logfile); 149 150 /* reinitialize log module. 151 * Keep same log options as previously initialized log, but reinit mutex 152 * that protects the log. This call is needed after a fork() in a threaded 153 * program 154 */ 155 void log_reinit(void); 156 157 /* 158 * Close log and free associated memory 159 */ 160 void log_fini(void); 161 162 /* 163 * Close scheduler log and free associated memory 164 */ 165 void sched_log_fini(void); 166 167 /* Alter log facility, options are like log_init() above, except that 168 * an argv0 argument is not passed. 169 * 170 * This function may be called multiple times. 171 */ 172 int log_alter(log_options_t opts, log_facility_t fac, char *logfile); 173 174 /* Alter log facility, options are like log_alter() above, except that 175 * an the file pointer is sent in instead of a filename. 176 * 177 * This function may only be called once. 178 */ 179 int log_alter_with_fp(log_options_t opt, log_facility_t fac, FILE *fp_in); 180 181 /* Sched alter log facility, options are like sched_log_init() above, 182 * except that an argv0 argument is not passed. 183 * 184 * This function may be called multiple times. 185 */ 186 int sched_log_alter(log_options_t opts, log_facility_t fac, char *logfile); 187 188 /* Set prefix for log file entries 189 * (really only useful for slurmd at this point). 190 * Note: will store pfx internally, do not use after this call. 191 */ 192 void log_set_fpfx(char **pfx); 193 194 /* 195 * (re)set argv0 string prepended to all log messages 196 */ 197 void log_set_argv0(char *pfx); 198 199 /* Return the FILE * of the current logfile (or stderr if not logging to 200 * a file, but NOT both). Also see log_oom() below. */ 201 FILE *log_fp(void); 202 203 /* Log out of memory without message buffering */ 204 void log_oom(const char *file, int line, const char *func); 205 206 /* Set the log timestamp format */ 207 void log_set_timefmt(unsigned); 208 209 /* 210 * Buffered log functions: 211 * 212 * log_has_data() returns true if there is data in the 213 * internal log buffer 214 */ 215 bool log_has_data(void); 216 217 /* 218 * log_flush() attempts to flush all data in the internal 219 * log buffer to the appropriate output stream. 220 */ 221 void log_flush(void); 222 223 /* log_set_debug_flags() 224 * Set or reset the debug flags based on the configuration 225 * file or the scontrol command. 226 */ 227 extern void log_set_debug_flags(void); 228 229 /* Return the highest LOG_LEVEL_* used for any logging mechanism. 230 * For example, if LOG_LEVEL_INFO is returned, we know that all verbose and 231 * debug type messages will be ignored. */ 232 extern int get_log_level(void); 233 234 /* 235 * Returns the greater of the sched_log_level or the log_level. 236 */ 237 extern int get_sched_log_level(void); 238 239 /* 240 * the following log a message to the log facility at the appropriate level: 241 * 242 * Messages do not need a newline! 243 * 244 * args are printf style with the following exceptions: 245 * %m expands to strerror(errno) 246 * %M expand to time stamp, format is configuration dependent 247 * %pJ expands to "JobId=XXXX" for the given job_ptr, with the appropriate 248 * format for job arrays and hetjob components. 249 * %pS expands to "JobId=XXXX StepId=YYYY" for a given step_ptr. 250 * %t expands to strftime("%x %X") [ locally preferred short date/time ] 251 * %T expands to rfc2822 date time [ "dd, Mon yyyy hh:mm:ss GMT offset" ] 252 */ 253 254 /* 255 * fatal() exits program 256 * error() returns SLURM_ERROR 257 */ 258 void log_var(const log_level_t, const char *, ...) 259 __attribute__ ((format (printf, 2, 3))); 260 void sched_log_var(const log_level_t, const char *, ...) 261 __attribute__ ((format (printf, 2, 3))); 262 extern void fatal_abort(const char *, ...) 263 __attribute__((format (printf, 1, 2))) __attribute__((noreturn)); 264 extern void fatal(const char *, ...) 265 __attribute__((format (printf, 1, 2))) __attribute__((noreturn)); 266 int error(const char *, ...) __attribute__ ((format (printf, 1, 2))); 267 void info(const char *, ...) __attribute__ ((format (printf, 1, 2))); 268 void verbose(const char *, ...) __attribute__ ((format (printf, 1, 2))); 269 #define debug(fmt, ...) \ 270 do { \ 271 if (get_log_level() >= LOG_LEVEL_DEBUG) \ 272 log_var(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__); \ 273 } while (0) 274 #define debug2(fmt, ...) \ 275 do { \ 276 if (get_log_level() >= LOG_LEVEL_DEBUG2) \ 277 log_var(LOG_LEVEL_DEBUG2, fmt, ##__VA_ARGS__); \ 278 } while (0) 279 /* 280 * Debug levels higher than debug3 are not written to stderr in the 281 * slurmstepd process after stderr is connected back to the client (srun). 282 */ 283 #define debug3(fmt, ...) \ 284 do { \ 285 if (get_log_level() >= LOG_LEVEL_DEBUG3) \ 286 log_var(LOG_LEVEL_DEBUG3, fmt, ##__VA_ARGS__); \ 287 } while (0) 288 #define debug4(fmt, ...) \ 289 do { \ 290 if (get_log_level() >= LOG_LEVEL_DEBUG4) \ 291 log_var(LOG_LEVEL_DEBUG4, fmt, ##__VA_ARGS__); \ 292 } while (0) 293 #define debug5(fmt, ...) \ 294 do { \ 295 if (get_log_level() >= LOG_LEVEL_DEBUG5) \ 296 log_var(LOG_LEVEL_DEBUG5, fmt, ##__VA_ARGS__); \ 297 } while (0) 298 /* 299 * Like above logging messages, but prepend "sched: " to the log entry 300 * and route the message into the sched_log if enabled. 301 */ 302 int sched_error(const char *, ...) __attribute__ ((format (printf, 1, 2))); 303 void sched_info(const char *, ...) __attribute__ ((format (printf, 1, 2))); 304 void sched_verbose(const char *, ...) __attribute__ ((format (printf, 1, 2))); 305 #define sched_debug(fmt, ...) \ 306 do { \ 307 if (get_sched_log_level() >= LOG_LEVEL_DEBUG) \ 308 sched_log_var(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__); \ 309 } while (0) 310 #define sched_debug2(fmt, ...) \ 311 do { \ 312 if (get_sched_log_level() >= LOG_LEVEL_DEBUG2) \ 313 sched_log_var(LOG_LEVEL_DEBUG2, fmt, ##__VA_ARGS__); \ 314 } while (0) 315 #define sched_debug3(fmt, ...) \ 316 do { \ 317 if (get_sched_log_level() >= LOG_LEVEL_DEBUG3) \ 318 sched_log_var(LOG_LEVEL_DEBUG3, fmt, ##__VA_ARGS__); \ 319 } while (0) 320 321 /* 322 * Print at the same log level as error(), but without prefixing the message 323 * with "error: ". Useful to report back to srun commands from SPANK plugins, 324 * as info() will only go to the logs. 325 */ 326 void spank_log(const char *, ...) __attribute__ ((format (printf, 1, 2))); 327 328 329 /* 330 * Used to print log messages only when a specific DEBUG_FLAG_* option has 331 * been enabled. Automatically prepends 'DEBUG_FLAG_' to the flag option name 332 * to save space. E.g., to print a message only when DEBUG_FLAG_STEPS is 333 * enabled, call `log_flag(STEPS, "%s: my important message", __func__);`. 334 * 335 * As this is implemented in a macro, this is no slower than the equivalent 336 * conditional check. 337 */ 338 #define log_flag(flag, fmt, ...) \ 339 do { \ 340 if (slurmctld_conf.debug_flags & DEBUG_FLAG_##flag) \ 341 log_var(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__); \ 342 } while (0) 343 344 #endif /* !_LOG_H */ 345