xref: /aosp_15_r20/external/ot-br-posix/src/common/logging.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *    Copyright (c) 2017, The OpenThread Authors.
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 are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #define OTBR_LOG_TAG "LOG"
30 
31 #ifndef OTBR_SYSLOG_FACILITY_ID
32 #define OTBR_SYSLOG_FACILITY_ID LOG_USER
33 #endif
34 
35 #include "common/logging.hpp"
36 
37 #include <assert.h>
38 #include <errno.h>
39 #include <stdarg.h>
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/time.h>
45 #include <syslog.h>
46 
47 #if OTBR_ENABLE_PLATFORM_ANDROID
48 #include <log/log.h>
49 #endif
50 
51 #include <sstream>
52 
53 #include "common/code_utils.hpp"
54 #include "common/time.hpp"
55 
56 static otbrLogLevel sLevel            = OTBR_LOG_INFO;
57 static const char   sLevelString[][8] = {
58       "[EMERG]", "[ALERT]", "[CRIT]", "[ERR ]", "[WARN]", "[NOTE]", "[INFO]", "[DEBG]",
59 };
60 static bool sSyslogDisabled = false;
61 
62 static otbrLogLevel sDefaultLevel = OTBR_LOG_INFO;
63 
64 /** Get the current debug log level */
otbrLogGetLevel(void)65 otbrLogLevel otbrLogGetLevel(void)
66 {
67     return sLevel;
68 }
69 
70 /** Get the default log level */
otbrLogGetDefaultLevel(void)71 otbrLogLevel otbrLogGetDefaultLevel(void)
72 {
73     return sDefaultLevel;
74 }
75 
76 /**
77  * Set current log level.
78  */
otbrLogSetLevel(otbrLogLevel aLevel)79 void otbrLogSetLevel(otbrLogLevel aLevel)
80 {
81     assert(aLevel >= OTBR_LOG_EMERG && aLevel <= OTBR_LOG_DEBUG);
82     sLevel = aLevel;
83 }
84 
85 /** Enable/disable logging with syslog */
otbrLogSyslogSetEnabled(bool aEnabled)86 void otbrLogSyslogSetEnabled(bool aEnabled)
87 {
88     sSyslogDisabled = !aEnabled;
89 }
90 
91 /** Initialize logging */
otbrLogInit(const char * aProgramName,otbrLogLevel aLevel,bool aPrintStderr,bool aSyslogDisable)92 void otbrLogInit(const char *aProgramName, otbrLogLevel aLevel, bool aPrintStderr, bool aSyslogDisable)
93 {
94     assert(aLevel >= OTBR_LOG_EMERG && aLevel <= OTBR_LOG_DEBUG);
95     otbrLogSyslogSetEnabled(!aSyslogDisable);
96 
97 #if OTBR_ENABLE_PLATFORM_ANDROID
98     OTBR_UNUSED_VARIABLE(aProgramName);
99 #else
100     assert(aProgramName != nullptr);
101 
102     if (!sSyslogDisabled)
103     {
104         const char *ident;
105 
106         ident = strrchr(aProgramName, '/');
107         ident = (ident != nullptr) ? ident + 1 : aProgramName;
108 
109         openlog(ident, (LOG_CONS | LOG_PID) | (aPrintStderr ? LOG_PERROR : 0), OTBR_SYSLOG_FACILITY_ID);
110     }
111 #endif
112 
113     sLevel        = aLevel;
114     sDefaultLevel = sLevel;
115 }
116 
GetPrefix(const char * aLogTag)117 static const char *GetPrefix(const char *aLogTag)
118 {
119     // Log prefix format : -xxx-----
120     const uint8_t kMaxTagSize = 7;
121     const uint8_t kBufferSize = kMaxTagSize + 3;
122     static char   prefix[kBufferSize];
123     uint8_t       tagLength = strlen(aLogTag) > kMaxTagSize ? kMaxTagSize : strlen(aLogTag);
124     int           index     = 0;
125 
126     if (strlen(aLogTag) > 0)
127     {
128         prefix[0] = '-';
129         memcpy(&prefix[1], aLogTag, tagLength);
130 
131         index = tagLength + 1;
132 
133         memset(&prefix[index], '-', kMaxTagSize - tagLength + 1);
134         index += kMaxTagSize - tagLength + 1;
135     }
136 
137     prefix[index++] = '\0';
138 
139     return prefix;
140 }
141 
142 #if OTBR_ENABLE_PLATFORM_ANDROID
ConvertToAndroidLogPriority(otbrLogLevel aLevel)143 static android_LogPriority ConvertToAndroidLogPriority(otbrLogLevel aLevel)
144 {
145     android_LogPriority priority;
146 
147     switch (aLevel)
148     {
149     case OTBR_LOG_EMERG:
150     case OTBR_LOG_ALERT:
151     case OTBR_LOG_CRIT:
152         priority = ANDROID_LOG_FATAL;
153         break;
154     case OTBR_LOG_ERR:
155         priority = ANDROID_LOG_ERROR;
156         break;
157     case OTBR_LOG_WARNING:
158         priority = ANDROID_LOG_WARN;
159         break;
160     case OTBR_LOG_NOTICE:
161     case OTBR_LOG_INFO:
162         priority = ANDROID_LOG_INFO;
163         break;
164     case OTBR_LOG_DEBUG:
165     default:
166         priority = ANDROID_LOG_DEBUG;
167         break;
168     }
169 
170     return priority;
171 }
172 #endif
173 
174 /** log to the syslog or standard out */
otbrLog(otbrLogLevel aLevel,const char * aLogTag,const char * aFormat,...)175 void otbrLog(otbrLogLevel aLevel, const char *aLogTag, const char *aFormat, ...)
176 {
177     const uint16_t kBufferSize = 1024;
178     va_list        ap;
179     char           buffer[kBufferSize];
180 
181     va_start(ap, aFormat);
182 
183     if ((aLevel <= sLevel) && (vsnprintf(buffer, sizeof(buffer), aFormat, ap) > 0))
184     {
185         if (sSyslogDisabled)
186         {
187             printf("%s%s: %s\n", sLevelString[aLevel], GetPrefix(aLogTag), buffer);
188         }
189         else
190         {
191 #if OTBR_ENABLE_PLATFORM_ANDROID
192             __android_log_print(ConvertToAndroidLogPriority(aLevel), LOG_TAG, "%s%s: %s", sLevelString[aLevel],
193                                 GetPrefix(aLogTag), buffer);
194 #else
195             syslog(static_cast<int>(aLevel), "%s%s: %s", sLevelString[aLevel], GetPrefix(aLogTag), buffer);
196 #endif
197         }
198     }
199 
200     va_end(ap);
201 
202     return;
203 }
204 
205 /** log to the syslog or standard out */
otbrLogv(otbrLogLevel aLevel,const char * aFormat,va_list aArgList)206 void otbrLogv(otbrLogLevel aLevel, const char *aFormat, va_list aArgList)
207 {
208     assert(aFormat);
209 
210     if (aLevel <= sLevel)
211     {
212         otbrLogvNoFilter(aLevel, aFormat, aArgList);
213     }
214 }
215 
216 /** log to the syslog or standard out */
otbrLogvNoFilter(otbrLogLevel aLevel,const char * aFormat,va_list aArgList)217 void otbrLogvNoFilter(otbrLogLevel aLevel, const char *aFormat, va_list aArgList)
218 {
219     if (sSyslogDisabled)
220     {
221         vprintf(aFormat, aArgList);
222         printf("\n");
223     }
224     else
225     {
226 #if OTBR_ENABLE_PLATFORM_ANDROID
227         __android_log_vprint(ConvertToAndroidLogPriority(aLevel), LOG_TAG, aFormat, aArgList);
228 #else
229         vsyslog(static_cast<int>(aLevel), aFormat, aArgList);
230 #endif
231     }
232 }
233 
234 /** Hex dump data to the log */
otbrDump(otbrLogLevel aLevel,const char * aLogTag,const char * aPrefix,const void * aMemory,size_t aSize)235 void otbrDump(otbrLogLevel aLevel, const char *aLogTag, const char *aPrefix, const void *aMemory, size_t aSize)
236 {
237     static const char kHexChars[] = "0123456789abcdef";
238     assert(aPrefix && (aMemory || aSize == 0));
239     const uint8_t *pEnd;
240     const uint8_t *p8;
241     int            addr;
242 
243     if (aLevel >= sLevel)
244     {
245         return;
246     }
247 
248     /* break hex dumps into 16byte lines
249      * In the form ADDR: XX XX XX XX ...
250      */
251 
252     // we pre-increment... so subtract
253     addr = -16;
254 
255     while (aSize > 0)
256     {
257         size_t this_size;
258         char   hex[16 * 3 + 1];
259 
260         addr = addr + 16;
261         p8   = (const uint8_t *)(aMemory) + addr;
262 
263         /* truncate line to max 16 bytes */
264         this_size = aSize;
265         if (this_size > 16)
266         {
267             this_size = 16;
268         }
269         aSize = aSize - this_size;
270 
271         char *ch = hex - 1;
272 
273         for (pEnd = p8 + this_size; p8 < pEnd; p8++)
274         {
275             *++ch = kHexChars[(*p8) >> 4];
276             *++ch = kHexChars[(*p8) & 0x0f];
277             *++ch = ' ';
278         }
279         *ch = 0;
280 
281         otbrLog(aLevel, aLogTag, "%s: %04x: %s", aPrefix, addr, hex);
282     }
283 }
284 
otbrErrorString(otbrError aError)285 const char *otbrErrorString(otbrError aError)
286 {
287     const char *error;
288 
289     switch (aError)
290     {
291     case OTBR_ERROR_NONE:
292         error = "OK";
293         break;
294 
295     case OTBR_ERROR_ERRNO:
296         error = strerror(errno);
297         break;
298 
299     case OTBR_ERROR_DBUS:
300         error = "DBUS error";
301         break;
302 
303     case OTBR_ERROR_MDNS:
304         error = "MDNS error";
305         break;
306 
307     case OTBR_ERROR_OPENTHREAD:
308         error = "OpenThread error";
309         break;
310 
311     case OTBR_ERROR_NOT_FOUND:
312         error = "Not found";
313         break;
314 
315     case OTBR_ERROR_PARSE:
316         error = "Parse error";
317         break;
318 
319     case OTBR_ERROR_NOT_IMPLEMENTED:
320         error = "Not implemented";
321         break;
322 
323     case OTBR_ERROR_INVALID_ARGS:
324         error = "Invalid arguments";
325         break;
326 
327     case OTBR_ERROR_DUPLICATED:
328         error = "Duplicated";
329         break;
330 
331     case OTBR_ERROR_ABORTED:
332         error = "Aborted";
333         break;
334 
335     case OTBR_ERROR_INVALID_STATE:
336         error = "Invalid state";
337         break;
338 
339     default:
340         error = "Unknown";
341     }
342 
343     return error;
344 }
345 
otbrLogDeinit(void)346 void otbrLogDeinit(void)
347 {
348     closelog();
349 }
350 
ConvertToOtLogLevel(otbrLogLevel aLevel)351 otLogLevel ConvertToOtLogLevel(otbrLogLevel aLevel)
352 {
353     otLogLevel level;
354 
355     switch (aLevel)
356     {
357     case OTBR_LOG_EMERG:
358     case OTBR_LOG_ALERT:
359     case OTBR_LOG_CRIT:
360         level = OT_LOG_LEVEL_CRIT;
361         break;
362     case OTBR_LOG_ERR:
363     case OTBR_LOG_WARNING:
364         level = OT_LOG_LEVEL_WARN;
365         break;
366     case OTBR_LOG_NOTICE:
367         level = OT_LOG_LEVEL_NOTE;
368         break;
369     case OTBR_LOG_INFO:
370         level = OT_LOG_LEVEL_INFO;
371         break;
372     case OTBR_LOG_DEBUG:
373     default:
374         level = OT_LOG_LEVEL_DEBG;
375         break;
376     }
377 
378     return level;
379 }
380