Contiki-NG
log.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, Inria.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Header file for the logging system
36  * \author
37  * Simon Duquennoy <simon.duquennoy@inria.fr>
38  */
39 
40 /** \addtogroup sys
41  * @{ */
42 
43 /**
44  * \defgroup log Per-module, per-level logging
45  * @{
46  *
47  * The log module performs per-module, per-level logging
48  *
49  */
50 
51 #ifndef __LOG_H__
52 #define __LOG_H__
53 
54 #include <stdio.h>
55 #include "net/linkaddr.h"
56 #include "sys/log-conf.h"
57 #if NETSTACK_CONF_WITH_IPV6
58 #include "net/ipv6/uip.h"
59 #endif /* NETSTACK_CONF_WITH_IPV6 */
60 
61 /* The different log levels available */
62 #define LOG_LEVEL_NONE 0 /* No log */
63 #define LOG_LEVEL_ERR 1 /* Errors */
64 #define LOG_LEVEL_WARN 2 /* Warnings */
65 #define LOG_LEVEL_INFO 3 /* Basic info */
66 #define LOG_LEVEL_DBG 4 /* Detailled debug */
67 
68 /* Log coloring */
69 #define TC_RESET "\033[0m"
70 #define TC_BLACK "\033[0;30m"
71 #define TC_RED "\033[0;31m"
72 #define TC_GREEN "\033[0;32m"
73 #define TC_YELLOW "\033[0;33m"
74 #define TC_BLUE "\033[0;34m"
75 #define TC_MAGENTA "\033[0;35m"
76 #define TC_CYAN "\033[0;36m"
77 #define TC_WHITE "\033[0;37m"
78 
79 #define LOG_COLOR_RESET TC_RESET
80 
81 #ifndef LOG_COLOR_ERR
82 #define LOG_COLOR_ERR TC_RED
83 #endif
84 
85 #ifndef LOG_COLOR_WARN
86 #define LOG_COLOR_WARN TC_YELLOW
87 #endif
88 
89 #ifndef LOG_COLOR_INFO
90 #define LOG_COLOR_INFO TC_BLUE
91 #endif
92 
93 #ifndef LOG_COLOR_DBG
94 #define LOG_COLOR_DBG TC_WHITE
95 #endif
96 
97 #ifndef LOG_COLOR_PRI
98 #define LOG_COLOR_PRI TC_CYAN
99 #endif
100 
101 /* Per-module log level */
102 
103 struct log_module {
104  const char *name;
105  int *curr_log_level;
106  int max_log_level;
107 };
108 
109 extern int curr_log_level_rpl;
110 extern int curr_log_level_tcpip;
111 extern int curr_log_level_ipv6;
112 extern int curr_log_level_6lowpan;
113 extern int curr_log_level_nullnet;
114 extern int curr_log_level_mac;
115 extern int curr_log_level_framer;
116 extern int curr_log_level_6top;
117 extern int curr_log_level_coap;
118 extern int curr_log_level_snmp;
119 extern int curr_log_level_lwm2m;
120 extern int curr_log_level_main;
121 
122 extern struct log_module all_modules[];
123 
124 #define LOG_LEVEL_RPL MIN((LOG_CONF_LEVEL_RPL), curr_log_level_rpl)
125 #define LOG_LEVEL_TCPIP MIN((LOG_CONF_LEVEL_TCPIP), curr_log_level_tcpip)
126 #define LOG_LEVEL_IPV6 MIN((LOG_CONF_LEVEL_IPV6), curr_log_level_ipv6)
127 #define LOG_LEVEL_6LOWPAN MIN((LOG_CONF_LEVEL_6LOWPAN), curr_log_level_6lowpan)
128 #define LOG_LEVEL_NULLNET MIN((LOG_CONF_LEVEL_NULLNET), curr_log_level_nullnet)
129 #define LOG_LEVEL_MAC MIN((LOG_CONF_LEVEL_MAC), curr_log_level_mac)
130 #define LOG_LEVEL_FRAMER MIN((LOG_CONF_LEVEL_FRAMER), curr_log_level_framer)
131 #define LOG_LEVEL_6TOP MIN((LOG_CONF_LEVEL_6TOP), curr_log_level_6top)
132 #define LOG_LEVEL_COAP MIN((LOG_CONF_LEVEL_COAP), curr_log_level_coap)
133 #define LOG_LEVEL_SNMP MIN((LOG_CONF_LEVEL_SNMP), curr_log_level_snmp)
134 #define LOG_LEVEL_LWM2M MIN((LOG_CONF_LEVEL_LWM2M), curr_log_level_lwm2m)
135 #define LOG_LEVEL_MAIN MIN((LOG_CONF_LEVEL_MAIN), curr_log_level_main)
136 
137 /* Main log function */
138 
139 #define LOG(newline, level, levelstr, levelcolor, ...) do { \
140  if(level <= (LOG_LEVEL)) { \
141  if(newline) { \
142  if(LOG_WITH_COLOR) { \
143  LOG_OUTPUT(levelcolor); \
144  } \
145  if(LOG_WITH_MODULE_PREFIX) { \
146  LOG_OUTPUT_PREFIX(level, levelstr, LOG_MODULE); \
147  } \
148  if(LOG_WITH_LOC) { \
149  LOG_OUTPUT("[%s: %d] ", __FILE__, __LINE__); \
150  } \
151  if(LOG_WITH_COLOR) { \
152  LOG_OUTPUT(LOG_COLOR_RESET); \
153  } \
154  } \
155  LOG_OUTPUT(__VA_ARGS__); \
156  } \
157  } while (0)
158 
159 /* For Cooja annotations */
160 #define LOG_ANNOTATE(...) do { \
161  if(LOG_WITH_ANNOTATE) { \
162  LOG_OUTPUT(__VA_ARGS__); \
163  } \
164  } while (0)
165 
166 /* Link-layer address */
167 #define LOG_LLADDR(level, lladdr) do { \
168  if(level <= (LOG_LEVEL)) { \
169  if(LOG_WITH_COMPACT_ADDR) { \
170  log_lladdr_compact(lladdr); \
171  } else { \
172  log_lladdr(lladdr); \
173  } \
174  } \
175  } while (0)
176 
177 /* IPv6 address */
178 #define LOG_6ADDR(level, ipaddr) do { \
179  if(level <= (LOG_LEVEL)) { \
180  if(LOG_WITH_COMPACT_ADDR) { \
181  log_6addr_compact(ipaddr); \
182  } else { \
183  log_6addr(ipaddr); \
184  } \
185  } \
186  } while (0)
187 
188 #define LOG_BYTES(level, data, length) do { \
189  if(level <= (LOG_LEVEL)) { \
190  log_bytes(data, length); \
191  } \
192  } while (0)
193 
194 /* More compact versions of LOG macros */
195 #define LOG_PRINT(...) LOG(1, 0, "PRI", LOG_COLOR_PRI, __VA_ARGS__)
196 #define LOG_ERR(...) LOG(1, LOG_LEVEL_ERR, "ERR", LOG_COLOR_ERR, __VA_ARGS__)
197 #define LOG_WARN(...) LOG(1, LOG_LEVEL_WARN, "WARN", LOG_COLOR_WARN, __VA_ARGS__)
198 #define LOG_INFO(...) LOG(1, LOG_LEVEL_INFO, "INFO", LOG_COLOR_INFO, __VA_ARGS__)
199 #define LOG_DBG(...) LOG(1, LOG_LEVEL_DBG, "DBG", LOG_COLOR_DBG, __VA_ARGS__)
200 
201 #define LOG_PRINT_(...) LOG(0, 0, "PRI", LOG_COLOR_PRI, __VA_ARGS__)
202 #define LOG_ERR_(...) LOG(0, LOG_LEVEL_ERR, "ERR", LOG_COLOR_ERR, __VA_ARGS__)
203 #define LOG_WARN_(...) LOG(0, LOG_LEVEL_WARN, "WARN", LOG_COLOR_WARN, __VA_ARGS__)
204 #define LOG_INFO_(...) LOG(0, LOG_LEVEL_INFO, "INFO", LOG_COLOR_INFO, __VA_ARGS__)
205 #define LOG_DBG_(...) LOG(0, LOG_LEVEL_DBG, "DBG", LOG_COLOR_DBG, __VA_ARGS__)
206 
207 #define LOG_PRINT_LLADDR(...) LOG_LLADDR(0, __VA_ARGS__)
208 #define LOG_ERR_LLADDR(...) LOG_LLADDR(LOG_LEVEL_ERR, __VA_ARGS__)
209 #define LOG_WARN_LLADDR(...) LOG_LLADDR(LOG_LEVEL_WARN, __VA_ARGS__)
210 #define LOG_INFO_LLADDR(...) LOG_LLADDR(LOG_LEVEL_INFO, __VA_ARGS__)
211 #define LOG_DBG_LLADDR(...) LOG_LLADDR(LOG_LEVEL_DBG, __VA_ARGS__)
212 
213 #define LOG_PRINT_6ADDR(...) LOG_6ADDR(0, __VA_ARGS__)
214 #define LOG_ERR_6ADDR(...) LOG_6ADDR(LOG_LEVEL_ERR, __VA_ARGS__)
215 #define LOG_WARN_6ADDR(...) LOG_6ADDR(LOG_LEVEL_WARN, __VA_ARGS__)
216 #define LOG_INFO_6ADDR(...) LOG_6ADDR(LOG_LEVEL_INFO, __VA_ARGS__)
217 #define LOG_DBG_6ADDR(...) LOG_6ADDR(LOG_LEVEL_DBG, __VA_ARGS__)
218 
219 #define LOG_PRINT_BYTES(data, length) LOG_BYTES(0, data, length)
220 #define LOG_ERR_BYTES(data, length) LOG_BYTES(LOG_LEVEL_ERR, data, length)
221 #define LOG_WARN_BYTES(data, length) LOG_BYTES(LOG_LEVEL_WARN, data, length)
222 #define LOG_INFO_BYTES(data, length) LOG_BYTES(LOG_LEVEL_INFO, data, length)
223 #define LOG_DBG_BYTES(data, length) LOG_BYTES(LOG_LEVEL_DBG, data, length)
224 
225 /* For checking log level.
226  As this builds on curr_log_level variables, this should not be used
227  in pre-processor macros. Use in a C 'if' statement instead, e.g.:
228  if(LOG_INFO_ENABLED) { ... }
229  Note that most compilers will still be able to strip the code out
230  for low enough log levels configurations. */
231 #define LOG_ERR_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_ERR)
232 #define LOG_WARN_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_WARN)
233 #define LOG_INFO_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_INFO)
234 #define LOG_DBG_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_DBG)
235 
236 #if NETSTACK_CONF_WITH_IPV6
237 
238 /**
239  * Logs an IPv6 address
240  * \param ipaddr The IPv6 address
241 */
242 void log_6addr(const uip_ipaddr_t *ipaddr);
243 
244 /**
245  * Logs an IPv6 address with a compact format
246  * \param ipaddr The IPv6 address
247 */
248 void log_6addr_compact(const uip_ipaddr_t *ipaddr);
249 
250 /**
251  * Write at most size - 1 characters of the IP address to the output string,
252  * in a compact representation. The output is always null-terminated, unless
253  * size is 0.
254  *
255  * \param buf A pointer to an output string with at least size bytes.
256  * \param size The max number of characters to write to the output string.
257  * \param ipaddr A pointer to a uip_ipaddr_t that will be printed with printf().
258  */
259 int log_6addr_compact_snprint(char *buf, size_t size, const uip_ipaddr_t *ipaddr);
260 
261 #endif /* NETSTACK_CONF_WITH_IPV6 */
262 
263 /**
264  * Logs a link-layer address
265  * \param lladdr The link-layer address
266 */
267 void log_lladdr(const linkaddr_t *lladdr);
268 
269 /**
270  * Logs a link-layer address with a compact format
271  * \param lladdr The link-layer address
272 */
273 void log_lladdr_compact(const linkaddr_t *lladdr);
274 
275 /**
276  * Logs a byte array as hex characters
277  * \param data The byte array
278  * \param length The length of the byte array
279 */
280 void log_bytes(const void *data, size_t length);
281 
282 /**
283  * Sets a log level at run-time. Logs are included in the firmware via
284  * the compile-time flags in log-conf.h, but this allows to force lower log
285  * levels, system-wide.
286  * \param module The target module string descriptor
287  * \param level The log level
288 */
289 void log_set_level(const char *module, int level);
290 
291 /**
292  * Returns the current log level.
293  * \param module The target module string descriptor
294  * \return The current log level
295 */
296 int log_get_level(const char *module);
297 
298 /**
299  * Returns a textual description of a log level
300  * \param level log level
301  * \return The textual description
302 */
303 const char *log_level_to_str(int level);
304 
305 #endif /* __LOG_H__ */
306 
307 /** @} */
308 /** @} */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
Default log levels for a number of modules
Header file for the link-layer address representation
void log_bytes(const void *data, size_t length)
Logs a byte array as hex characters.
Definition: log.c:163
void log_lladdr_compact(const linkaddr_t *lladdr)
Logs a link-layer address with a compact format.
Definition: log.c:145
void log_set_level(const char *module, int level)
Sets a log level at run-time.
Definition: log.c:173
void log_lladdr(const linkaddr_t *lladdr)
Logs a link-layer address.
Definition: log.c:128
void log_6addr(const uip_ipaddr_t *ipaddr)
Logs an IPv6 address.
Definition: log.c:89
Header file for the uIP TCP/IP stack.
const char * log_level_to_str(int level)
Returns a textual description of a log level.
Definition: log.c:204
int log_get_level(const char *module)
Returns the current log level.
Definition: log.c:188
int log_6addr_compact_snprint(char *buf, size_t size, const uip_ipaddr_t *ipaddr)
Write at most size - 1 characters of the IP address to the output string, in a compact representation...
Definition: log.c:97
void log_6addr_compact(const uip_ipaddr_t *ipaddr)
Logs an IPv6 address with a compact format.
Definition: log.c:119