Changes in uspace/lib/c/generic/io/log.c [9d58539:bc0ccab] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/log.c
r9d58539 rbc0ccab 38 38 #include <stdlib.h> 39 39 #include <stdio.h> 40 40 #include <async.h> 41 41 #include <io/log.h> 42 43 /** Serialization mutex for logging functions. */ 44 static FIBRIL_MUTEX_INITIALIZE(log_serializer); 45 46 /** Current log level. */ 47 static log_level_t log_level; 48 49 static FILE *log_stream; 50 42 #include <ipc/logger.h> 43 #include <ns.h> 44 45 static sysarg_t default_log_id; 46 47 /** Log messages are printed under this name. */ 51 48 static const char *log_prog_name; 52 49 53 /** Prefixes for individual logging levels. */54 50 static const char *log_level_names[] = { 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" 51 "fatal", 52 "error", 53 "warn", 54 "note", 55 "debug", 56 "debug2", 57 NULL 61 58 }; 62 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 4096 65 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 explicitly 76 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 an 88 * 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 else 105 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 63 137 /** Initialize the logging system. 64 138 * 65 139 * @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; 72 73 log_stream = stdout; 140 */ 141 int log_init(const char *prog_name) 142 { 74 143 log_prog_name = str_dup(prog_name); 75 144 if (log_prog_name == NULL) 76 145 return ENOMEM; 77 146 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 78 154 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); 79 188 } 80 189 … … 86 195 * @param fmt Format string (no traling newline). 87 196 */ 88 void log_msg(log_ level_t level, const char *fmt, ...)197 void log_msg(log_t ctx, log_level_t level, const char *fmt, ...) 89 198 { 90 199 va_list args; 91 200 92 201 va_start(args, fmt); 93 log_msgv( level, fmt, args);202 log_msgv(ctx, level, fmt, args); 94 203 va_end(args); 95 204 } … … 102 211 * @param fmt Format string (no trailing newline) 103 212 */ 104 void log_msgv(log_ level_t level, const char *fmt, va_list args)213 void log_msgv(log_t ctx, log_level_t level, const char *fmt, va_list args) 105 214 { 106 215 assert(level < LVL_LIMIT); 107 216 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); 119 } 217 char *message_buffer = malloc(MESSAGE_BUFFER_SIZE); 218 if (message_buffer == NULL) { 219 return; 220 } 221 222 vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args); 223 logger_message(logger_session, ctx, level, message_buffer); 120 224 } 121 225
Note:
See TracChangeset
for help on using the changeset viewer.