Changes in uspace/lib/c/generic/io/log.c [bc0ccab:9d58539] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/log.c
rbc0ccab r9d58539 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 static sysarg_t default_log_id; 43 /** Serialization mutex for logging functions. */ 44 static FIBRIL_MUTEX_INITIALIZE(log_serializer); 46 45 47 /** 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 48 51 static const char *log_prog_name; 49 52 53 /** Prefixes for individual logging levels. */ 50 54 static const char *log_level_names[] = { 51 "fatal", 52 "error", 53 "warn", 54 "note", 55 "debug", 56 "debug2", 57 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" 58 61 }; 59 60 /** IPC session with the logger service. */61 static async_sess_t *logger_session;62 63 /** Maximum length of a single log message (in bytes). */64 #define MESSAGE_BUFFER_SIZE 409665 66 static int logger_message(async_sess_t *session, log_t log, log_level_t level, char *message)67 {68 async_exch_t *exchange = async_exchange_begin(session);69 if (exchange == NULL) {70 return ENOMEM;71 }72 if (log == LOG_DEFAULT)73 log = default_log_id;74 75 // FIXME: remove when all USB drivers use libc logging explicitly76 str_rtrim(message, '\n');77 78 aid_t reg_msg = async_send_2(exchange, LOGGER_WRITER_MESSAGE,79 log, level, NULL);80 int rc = async_data_write_start(exchange, message, str_size(message));81 sysarg_t reg_msg_rc;82 async_wait_for(reg_msg, ®_msg_rc);83 84 async_exchange_end(exchange);85 86 /*87 * Getting ENAK means no-one wants our message. That is not an88 * error at all.89 */90 if (rc == ENAK)91 rc = EOK;92 93 if (rc != EOK) {94 return rc;95 }96 97 return reg_msg_rc;98 }99 100 const char *log_level_str(log_level_t level)101 {102 if (level >= LVL_LIMIT)103 return "unknown";104 else105 return log_level_names[level];106 }107 108 int log_level_from_str(const char *name, log_level_t *level_out)109 {110 log_level_t level = LVL_FATAL;111 112 while (log_level_names[level] != NULL) {113 if (str_cmp(name, log_level_names[level]) == 0) {114 if (level_out != NULL)115 *level_out = level;116 return EOK;117 }118 level++;119 }120 121 /* Maybe user specified number directly. */122 char *end_ptr;123 int level_int = strtol(name, &end_ptr, 0);124 if ((end_ptr == name) || (str_length(end_ptr) != 0))125 return EINVAL;126 if (level_int < 0)127 return ERANGE;128 if (level_int >= (int) LVL_LIMIT)129 return ERANGE;130 131 if (level_out != NULL)132 *level_out = (log_level_t) level_int;133 134 return EOK;135 }136 62 137 63 /** Initialize the logging system. 138 64 * 139 65 * @param prog_name Program name, will be printed as part of message 66 * @param level Minimum message level to print 140 67 */ 141 int log_init(const char *prog_name )68 int log_init(const char *prog_name, log_level_t level) 142 69 { 70 assert(level < LVL_LIMIT); 71 log_level = level; 72 73 log_stream = stdout; 143 74 log_prog_name = str_dup(prog_name); 144 75 if (log_prog_name == NULL) 145 76 return ENOMEM; 146 77 147 logger_session = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOGGER, LOGGER_INTERFACE_WRITER, 0);148 if (logger_session == NULL) {149 return ENOMEM;150 }151 152 default_log_id = log_create(prog_name, LOG_NO_PARENT);153 154 78 return EOK; 155 }156 157 /** Create a new (sub-) log.158 *159 * This function always returns a valid log_t. In case of errors,160 * @c parent is returned and errors are silently ignored.161 *162 * @param name Log name under which message will be reported (appended to parents name).163 * @param parent Parent log.164 * @return Opaque identifier of the newly created log.165 */166 log_t log_create(const char *name, log_t parent)167 {168 async_exch_t *exchange = async_exchange_begin(logger_session);169 if (exchange == NULL)170 return parent;171 172 if (parent == LOG_DEFAULT)173 parent = default_log_id;174 175 ipc_call_t answer;176 aid_t reg_msg = async_send_1(exchange, LOGGER_WRITER_CREATE_LOG,177 parent, &answer);178 int rc = async_data_write_start(exchange, name, str_size(name));179 sysarg_t reg_msg_rc;180 async_wait_for(reg_msg, ®_msg_rc);181 182 async_exchange_end(exchange);183 184 if ((rc != EOK) || (reg_msg_rc != EOK))185 return parent;186 187 return IPC_GET_ARG1(answer);188 79 } 189 80 … … 195 86 * @param fmt Format string (no traling newline). 196 87 */ 197 void log_msg(log_ t ctx, log_level_t level, const char *fmt, ...)88 void log_msg(log_level_t level, const char *fmt, ...) 198 89 { 199 90 va_list args; 200 91 201 92 va_start(args, fmt); 202 log_msgv( ctx,level, fmt, args);93 log_msgv(level, fmt, args); 203 94 va_end(args); 204 95 } … … 211 102 * @param fmt Format string (no trailing newline) 212 103 */ 213 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) 214 105 { 215 106 assert(level < LVL_LIMIT); 216 107 217 char *message_buffer = malloc(MESSAGE_BUFFER_SIZE); 218 if (message_buffer == NULL) { 219 return; 108 /* Higher number means higher verbosity. */ 109 if (level <= log_level) { 110 fibril_mutex_lock(&log_serializer); 111 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); 220 119 } 221 222 vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args);223 logger_message(logger_session, ctx, level, message_buffer);224 120 } 225 121
Note:
See TracChangeset
for help on using the changeset viewer.