Changes in uspace/lib/c/generic/io/log.c [849bebe4:ebcb05a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/log.c
r849bebe4 rebcb05a 38 38 #include <stdlib.h> 39 39 #include <stdio.h> 40 #include <async.h> 40 41 41 #include <io/log.h> 42 #include <ipc/logger.h>43 #include <ns.h>44 42 45 /** Id of the first log we create at logger. */46 static sysarg_t default_log_id;43 /** Serialization mutex for logging functions. */ 44 static FIBRIL_MUTEX_INITIALIZE(log_serializer); 47 45 48 /** Log messages are printed under this name. */ 46 /** Current log level. */ 47 static log_level_t log_level; 48 49 static FILE *log_stream; 50 49 51 static const char *log_prog_name; 50 52 51 /** Names of individual log levels. */53 /** Prefixes for individual logging levels. */ 52 54 static const char *log_level_names[] = { 53 "fatal", 54 "error", 55 "warn", 56 "note", 57 "debug", 58 "debug2", 59 NULL 55 [LVL_FATAL] = "Fatal error", 56 [LVL_ERROR] = "Error", 57 [LVL_WARN] = "Warning", 58 [LVL_NOTE] = "Note", 59 [LVL_DEBUG] = "Debug", 60 [LVL_DEBUG2] = "Debug2" 60 61 }; 61 62 62 /** IPC session with the logger service. */ 63 static async_sess_t *logger_session; 63 /** Initialize the logging system. 64 * 65 * @param prog_name Program name, will be printed as part of message 66 * @param level Minimum message level to print 67 */ 68 int log_init(const char *prog_name, log_level_t level) 69 { 70 assert(level < LVL_LIMIT); 71 log_level = level; 64 72 65 /** Maximum length of a single log message (in bytes). */ 66 #define MESSAGE_BUFFER_SIZE 4096 67 68 /** Send formatted message to the logger service. 69 * 70 * @param session Initialized IPC session with the logger. 71 * @param log Log to use. 72 * @param level Verbosity level of the message. 73 * @param message The actual message. 74 * @return Error code of the conversion or EOK on success. 75 */ 76 static int logger_message(async_sess_t *session, log_t log, log_level_t level, char *message) 77 { 78 async_exch_t *exchange = async_exchange_begin(session); 79 if (exchange == NULL) { 73 log_stream = stdout; 74 log_prog_name = str_dup(prog_name); 75 if (log_prog_name == NULL) 80 76 return ENOMEM; 81 }82 if (log == LOG_DEFAULT)83 log = default_log_id;84 85 // FIXME: remove when all USB drivers use libc logging explicitly86 str_rtrim(message, '\n');87 88 aid_t reg_msg = async_send_2(exchange, LOGGER_WRITER_MESSAGE,89 log, level, NULL);90 int rc = async_data_write_start(exchange, message, str_size(message));91 sysarg_t reg_msg_rc;92 async_wait_for(reg_msg, ®_msg_rc);93 94 async_exchange_end(exchange);95 96 /*97 * Getting ENAK means no-one wants our message. That is not an98 * error at all.99 */100 if (rc == ENAK)101 rc = EOK;102 103 if (rc != EOK) {104 return rc;105 }106 107 return reg_msg_rc;108 }109 110 /** Get name of the log level.111 *112 * @param level The log level.113 * @return String name or "unknown".114 */115 const char *log_level_str(log_level_t level)116 {117 if (level >= LVL_LIMIT)118 return "unknown";119 else120 return log_level_names[level];121 }122 123 /** Convert log level name to the enum.124 *125 * @param[in] name Log level name or log level number.126 * @param[out] level_out Where to store the result (set to NULL to ignore).127 * @return Error code of the conversion or EOK on success.128 */129 int log_level_from_str(const char *name, log_level_t *level_out)130 {131 log_level_t level = LVL_FATAL;132 133 while (log_level_names[level] != NULL) {134 if (str_cmp(name, log_level_names[level]) == 0) {135 if (level_out != NULL)136 *level_out = level;137 return EOK;138 }139 level++;140 }141 142 /* Maybe user specified number directly. */143 char *end_ptr;144 int level_int = strtol(name, &end_ptr, 0);145 if ((end_ptr == name) || (str_length(end_ptr) != 0))146 return EINVAL;147 if (level_int < 0)148 return ERANGE;149 if (level_int >= (int) LVL_LIMIT)150 return ERANGE;151 152 if (level_out != NULL)153 *level_out = (log_level_t) level_int;154 77 155 78 return EOK; 156 79 } 157 80 158 /** Initialize the logging system.159 *160 * @param prog_name Program name, will be printed as part of message161 */162 int log_init(const char *prog_name)163 {164 log_prog_name = str_dup(prog_name);165 if (log_prog_name == NULL)166 return ENOMEM;167 168 logger_session = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOGGER, LOGGER_INTERFACE_WRITER, 0);169 if (logger_session == NULL) {170 return ENOMEM;171 }172 173 default_log_id = log_create(prog_name, LOG_NO_PARENT);174 175 return EOK;176 }177 178 /** Create a new (sub-) log.179 *180 * This function always returns a valid log_t. In case of errors,181 * @c parent is returned and errors are silently ignored.182 *183 * @param name Log name under which message will be reported (appended to parents name).184 * @param parent Parent log.185 * @return Opaque identifier of the newly created log.186 */187 log_t log_create(const char *name, log_t parent)188 {189 async_exch_t *exchange = async_exchange_begin(logger_session);190 if (exchange == NULL)191 return parent;192 193 if (parent == LOG_DEFAULT)194 parent = default_log_id;195 196 ipc_call_t answer;197 aid_t reg_msg = async_send_1(exchange, LOGGER_WRITER_CREATE_LOG,198 parent, &answer);199 int rc = async_data_write_start(exchange, name, str_size(name));200 sysarg_t reg_msg_rc;201 async_wait_for(reg_msg, ®_msg_rc);202 203 async_exchange_end(exchange);204 205 if ((rc != EOK) || (reg_msg_rc != EOK))206 return parent;207 208 return IPC_GET_ARG1(answer);209 }210 211 81 /** Write an entry to the log. 212 82 * 213 * The message is printed only if the verbosity level is less than or 214 * equal to currently set reporting level of the log. 215 * 216 * @param ctx Log to use (use LOG_DEFAULT if you have no idea what it means). 217 * @param level Severity level of the message. 218 * @param fmt Format string in printf-like format (without trailing newline). 83 * @param level Message verbosity level. Message is only printed 84 * if verbosity is less than or equal to current 85 * reporting level. 86 * @param fmt Format string (no traling newline). 219 87 */ 220 void log_msg(log_ t ctx, log_level_t level, const char *fmt, ...)88 void log_msg(log_level_t level, const char *fmt, ...) 221 89 { 222 90 va_list args; 223 91 224 92 va_start(args, fmt); 225 log_msgv( ctx,level, fmt, args);93 log_msgv(level, fmt, args); 226 94 va_end(args); 227 95 } … … 229 97 /** Write an entry to the log (va_list variant). 230 98 * 231 * @param ctx Log to use (use LOG_DEFAULT if you have no idea what it means).232 * @param level Severity level of the message.233 * @param fmt Format string in printf-like format (without trailing newline).234 * @param args Arguments.99 * @param level Message verbosity level. Message is only printed 100 * if verbosity is less than or equal to current 101 * reporting level. 102 * @param fmt Format string (no trailing newline) 235 103 */ 236 void log_msgv(log_ t ctx, log_level_t level, const char *fmt, va_list args)104 void log_msgv(log_level_t level, const char *fmt, va_list args) 237 105 { 238 106 assert(level < LVL_LIMIT); 239 107 240 char *message_buffer = malloc(MESSAGE_BUFFER_SIZE);241 if ( message_buffer == NULL)242 return;108 /* Higher number means higher verbosity. */ 109 if (level <= log_level) { 110 fibril_mutex_lock(&log_serializer); 243 111 244 vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args); 245 logger_message(logger_session, ctx, level, message_buffer); 246 free(message_buffer); 112 fprintf(log_stream, "%s: %s: ", log_prog_name, 113 log_level_names[level]); 114 vfprintf(log_stream, fmt, args); 115 fputc('\n', log_stream); 116 fflush(log_stream); 117 118 fibril_mutex_unlock(&log_serializer); 119 } 247 120 } 248 121
Note:
See TracChangeset
for help on using the changeset viewer.