Changes in uspace/lib/c/generic/io/log.c [9d58539:6e596bd] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/log.c
r9d58539 r6e596bd 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 }; 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, const 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 aid_t reg_msg = async_send_2(exchange, LOGGER_WRITER_MESSAGE, 76 log, level, NULL); 77 int rc = async_data_write_start(exchange, message, str_size(message)); 78 sysarg_t reg_msg_rc; 79 async_wait_for(reg_msg, ®_msg_rc); 80 81 async_exchange_end(exchange); 82 83 /* 84 * Getting ENAK means no-one wants our message. That is not an 85 * error at all. 86 */ 87 if (rc == ENAK) 88 rc = EOK; 89 90 if (rc != EOK) { 91 return rc; 92 } 93 94 return reg_msg_rc; 95 } 96 97 const char *log_level_str(log_level_t level) 98 { 99 if (level >= LVL_LIMIT) 100 return "unknown"; 101 else 102 return log_level_names[level]; 103 } 104 105 int log_level_from_str(const char *name, log_level_t *level_out) 106 { 107 log_level_t level = LVL_FATAL; 108 109 while (log_level_names[level] != NULL) { 110 if (str_cmp(name, log_level_names[level]) == 0) { 111 if (level_out != NULL) 112 *level_out = level; 113 return EOK; 114 } 115 level++; 116 } 117 118 /* Maybe user specified number directly. */ 119 char *end_ptr; 120 int level_int = strtol(name, &end_ptr, 0); 121 if ((end_ptr == name) || (str_length(end_ptr) != 0)) 122 return EINVAL; 123 if (level_int < 0) 124 return ERANGE; 125 if (level_int >= (int) LVL_LIMIT) 126 return ERANGE; 127 128 if (level_out != NULL) 129 *level_out = (log_level_t) level_int; 130 131 return EOK; 132 } 62 133 63 134 /** Initialize the logging system. … … 69 140 { 70 141 assert(level < LVL_LIMIT); 71 log_level = level; 72 73 log_stream = stdout; 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_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_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_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.