2 * Copyright (c) 2011 Vojtech Horky
3 * Copyright (c) 2011 Jiri Svoboda
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <fibril_synch.h>
42 #include <ipc/logger.h>
45 static sysarg_t default_log_id
;
47 /** Log messages are printed under this name. */
48 static const char *log_prog_name
;
50 static const char *log_level_names
[] = {
60 /** IPC session with the logger service. */
61 static async_sess_t
*logger_session
;
63 /** Maximum length of a single log message (in bytes). */
64 #define MESSAGE_BUFFER_SIZE 4096
66 static int logger_message(async_sess_t
*session
, log_t log
, log_level_t level
, const char *message
)
68 async_exch_t
*exchange
= async_exchange_begin(session
);
69 if (exchange
== NULL
) {
72 if (log
== LOG_DEFAULT
)
75 aid_t reg_msg
= async_send_2(exchange
, LOGGER_WRITER_MESSAGE
,
77 int rc
= async_data_write_start(exchange
, message
, str_size(message
));
79 async_wait_for(reg_msg
, ®_msg_rc
);
81 async_exchange_end(exchange
);
84 * Getting ENAK means no-one wants our message. That is not an
97 const char *log_level_str(log_level_t level
)
99 if (level
>= LVL_LIMIT
)
102 return log_level_names
[level
];
105 int log_level_from_str(const char *name
, log_level_t
*level_out
)
107 log_level_t level
= LVL_FATAL
;
109 while (log_level_names
[level
] != NULL
) {
110 if (str_cmp(name
, log_level_names
[level
]) == 0) {
111 if (level_out
!= NULL
)
118 /* Maybe user specified number directly. */
120 int level_int
= strtol(name
, &end_ptr
, 0);
121 if ((end_ptr
== name
) || (str_length(end_ptr
) != 0))
125 if (level_int
>= (int) LVL_LIMIT
)
128 if (level_out
!= NULL
)
129 *level_out
= (log_level_t
) level_int
;
134 /** Initialize the logging system.
136 * @param prog_name Program name, will be printed as part of message
138 int log_init(const char *prog_name
)
140 log_prog_name
= str_dup(prog_name
);
141 if (log_prog_name
== NULL
)
144 logger_session
= service_connect_blocking(EXCHANGE_SERIALIZE
, SERVICE_LOGGER
, LOGGER_INTERFACE_WRITER
, 0);
145 if (logger_session
== NULL
) {
149 default_log_id
= log_create(prog_name
, LOG_NO_PARENT
);
154 /** Create a new (sub-) log.
156 * This function always returns a valid log_t. In case of errors,
157 * @c parent is returned and errors are silently ignored.
159 * @param name Log name under which message will be reported (appended to parents name).
160 * @param parent Parent log.
161 * @return Opaque identifier of the newly created log.
163 log_t
log_create(const char *name
, log_t parent
)
165 async_exch_t
*exchange
= async_exchange_begin(logger_session
);
166 if (exchange
== NULL
)
169 if (parent
== LOG_DEFAULT
)
170 parent
= default_log_id
;
173 aid_t reg_msg
= async_send_1(exchange
, LOGGER_WRITER_CREATE_LOG
,
175 int rc
= async_data_write_start(exchange
, name
, str_size(name
));
177 async_wait_for(reg_msg
, ®_msg_rc
);
179 async_exchange_end(exchange
);
181 if ((rc
!= EOK
) || (reg_msg_rc
!= EOK
))
184 return IPC_GET_ARG1(answer
);
187 /** Write an entry to the log.
189 * @param level Message verbosity level. Message is only printed
190 * if verbosity is less than or equal to current
192 * @param fmt Format string (no traling newline).
194 void log_msg(log_t ctx
, log_level_t level
, const char *fmt
, ...)
199 log_msgv(ctx
, level
, fmt
, args
);
203 /** Write an entry to the log (va_list variant).
205 * @param level Message verbosity level. Message is only printed
206 * if verbosity is less than or equal to current
208 * @param fmt Format string (no trailing newline)
210 void log_msgv(log_t ctx
, log_level_t level
, const char *fmt
, va_list args
)
212 assert(level
< LVL_LIMIT
);
214 char *message_buffer
= malloc(MESSAGE_BUFFER_SIZE
);
215 if (message_buffer
== NULL
) {
219 vsnprintf(message_buffer
, MESSAGE_BUFFER_SIZE
, fmt
, args
);
220 logger_message(logger_session
, ctx
, level
, message_buffer
);