blob: c71e5c4a58e629060b6105b2bc86fda0c18172ff [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_LOGGING_LOGGING_H_
2#define AOS_LOGGING_LOGGING_H_
brians343bc112013-02-10 01:53:46 +00003
Brian Silvermanf665d692013-02-17 22:11:39 -08004// This file contains the logging client interface. It works with both C and C++
5// code.
6
Austin Schuhf257f3c2019-10-27 21:00:43 -07007#include <errno.h>
brians343bc112013-02-10 01:53:46 +00008#include <stdint.h>
Austin Schuhf257f3c2019-10-27 21:00:43 -07009#include <stdio.h>
Brian Silvermanb067abf2013-09-13 22:01:06 -070010#include <stdlib.h>
Brian Silverman01be0002014-05-10 15:44:38 -070011#include <string.h>
brians343bc112013-02-10 01:53:46 +000012
John Park33858a32018-09-28 23:05:48 -070013#include "aos/libc/aos_strerror.h"
Austin Schuhf257f3c2019-10-27 21:00:43 -070014#include "aos/macros.h"
Brian Silvermana7234c62014-03-24 20:23:25 -070015
brians343bc112013-02-10 01:53:46 +000016#ifdef __cplusplus
17extern "C" {
18#endif
19
20typedef uint8_t log_level;
Brian Silvermanf665d692013-02-17 22:11:39 -080021
Austin Schuhf257f3c2019-10-27 21:00:43 -070022#define DECL_LEVELS \
23 DECL_LEVEL(DEBUG, 0); /* stuff that gets printed out every cycle */ \
24 DECL_LEVEL(INFO, 1); /* things like PosEdge/NegEdge */ \
25 /* things that might still work if they happen occasionally */ \
26 DECL_LEVEL(WARNING, 2); \
27 /*-1 so that vxworks macro of same name will have same effect if used*/ \
28 DECL_LEVEL(ERROR, -1); /* errors */ \
29 /* serious errors. the logging code will terminate the process/task */ \
30 DECL_LEVEL(FATAL, 4); \
31 DECL_LEVEL(LOG_UNKNOWN, 5); /* unknown logging level */
Brian Silvermanf665d692013-02-17 22:11:39 -080032#define DECL_LEVEL(name, value) static const log_level name = value;
Brian Silvermanf665d692013-02-17 22:11:39 -080033DECL_LEVELS;
brians343bc112013-02-10 01:53:46 +000034#undef DECL_LEVEL
35
Brian Silvermanf665d692013-02-17 22:11:39 -080036#ifdef __cplusplus
37extern "C" {
38#endif
Brian Silverman01be0002014-05-10 15:44:38 -070039
Brian Silvermanf665d692013-02-17 22:11:39 -080040// Actually implements the basic logging call.
41// Does not check that level is valid.
42void log_do(log_level level, const char *format, ...)
Austin Schuhf257f3c2019-10-27 21:00:43 -070043 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 3)));
Brian Silvermanf665d692013-02-17 22:11:39 -080044
Brian Silvermanf665d692013-02-17 22:11:39 -080045#ifdef __cplusplus
46}
47#endif
48
49// A magical static const char[] or string literal that communicates the name
50// of the enclosing function.
51// It's currently using __PRETTY_FUNCTION__ because both GCC and Clang support
52// that and it gives nicer results in C++ than the standard __func__ (which
53// would also work).
Brian Silvermanc11f3b72013-03-19 18:32:02 -070054//#define LOG_CURRENT_FUNCTION __PRETTY_FUNCTION__
55#define LOG_CURRENT_FUNCTION __func__
Brian Silvermanf665d692013-02-17 22:11:39 -080056
Brian Silverman8fc7bc92013-03-13 23:15:47 -070057#define LOG_SOURCENAME __FILE__
58
Brian Silvermanf665d692013-02-17 22:11:39 -080059// The basic logging call.
Austin Schuhc69e6792021-02-05 11:20:05 -080060#define AOS_LOG(level, format, args...) \
61 do { \
62 log_do(level, LOG_SOURCENAME ": " AOS_STRINGIFY(__LINE__) ": %s: " format, \
63 LOG_CURRENT_FUNCTION, ##args); \
64 /* so that GCC knows that it won't return */ \
65 if (level == FATAL) { \
66 fprintf(stderr, "log_do(FATAL) fell through!!!!!\n"); \
67 printf("see stderr\n"); \
68 abort(); \
69 } \
Brian Silvermand6974f42014-02-14 13:39:21 -080070 } while (0)
brians343bc112013-02-10 01:53:46 +000071
Brian Silvermanb3efcca2014-06-03 19:47:06 -070072// Same as LOG except appends " due to %d (%s)\n" (formatted with errno and
Brian Silverman01be0002014-05-10 15:44:38 -070073// aos_strerror(errno)) to the message.
Austin Schuhf257f3c2019-10-27 21:00:43 -070074#define AOS_PLOG(level, format, args...) AOS_PELOG(level, errno, format, ##args)
Brian Silverman01be0002014-05-10 15:44:38 -070075
76// Like PLOG except allows specifying an error other than errno.
Austin Schuhf257f3c2019-10-27 21:00:43 -070077#define AOS_PELOG(level, error_in, format, args...) \
78 do { \
79 const int error = error_in; \
80 AOS_LOG(level, format " due to %d (%s)\n", ##args, error, \
81 aos_strerror(error)); \
Brian Silverman01be0002014-05-10 15:44:38 -070082 } while (0);
83
brians343bc112013-02-10 01:53:46 +000084// Allows format to not be a string constant.
Austin Schuhf257f3c2019-10-27 21:00:43 -070085#define AOS_LOG_DYNAMIC(level, format, args...) \
86 do { \
87 static char log_buf[LOG_MESSAGE_LEN]; \
88 int ret = snprintf(log_buf, sizeof(log_buf), format, ##args); \
89 if (ret < 0 || (uintmax_t)ret >= LOG_MESSAGE_LEN) { \
90 AOS_LOG(ERROR, "next message was too long so not subbing in args\n"); \
91 AOS_LOG(level, "%s", format); \
92 } else { \
93 AOS_LOG(level, "%s", log_buf); \
94 } \
Brian Silvermand6974f42014-02-14 13:39:21 -080095 } while (0)
brians343bc112013-02-10 01:53:46 +000096
brians343bc112013-02-10 01:53:46 +000097#ifdef __cplusplus
98}
99#endif
100
Brian Silvermanb067abf2013-09-13 22:01:06 -0700101#ifdef __cplusplus
102
103namespace aos {
104
105// CHECK* macros, similar to glog
106// (<http://google-glog.googlecode.com/svn/trunk/doc/glog.html>)'s, except they
107// don't support streaming in extra text. Some of the implementation is borrowed
108// from there too.
109// They all LOG(FATAL) with a helpful message when the check fails.
Brian Silvermanb067abf2013-09-13 22:01:06 -0700110// Portions copyright (c) 1999, Google Inc.
111// All rights reserved.
112//
113// Redistribution and use in source and binary forms, with or without
114// modification, are permitted provided that the following conditions are
115// met:
116//
117// * Redistributions of source code must retain the above copyright
118// notice, this list of conditions and the following disclaimer.
119// * Redistributions in binary form must reproduce the above
120// copyright notice, this list of conditions and the following disclaimer
121// in the documentation and/or other materials provided with the
122// distribution.
123// * Neither the name of Google Inc. nor the names of its
124// contributors may be used to endorse or promote products derived from
125// this software without specific prior written permission.
126//
127// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
128// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
129// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
130// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
131// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
132// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
133// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
134// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
135// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
136// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
137// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
138
Brian Silverman862b1632013-09-14 15:29:59 -0700139// CHECK dies with a fatal error if condition is not true. It is *not*
140// controlled by NDEBUG, so the check will be executed regardless of
141// compilation mode. Therefore, it is safe to do things like:
142// CHECK(fp->Write(x) == 4)
Austin Schuh24cdb7e2020-10-24 18:34:25 -0700143// TODO(austin): We want to be pushing people to glog instead of AOS_CHECK here.
144// You are crashing anyways. If we want glog to tee to AOS_LOG as well, we'll
145// implement that through that path.
Austin Schuhf257f3c2019-10-27 21:00:43 -0700146#define AOS_CHECK(condition) \
147 if (__builtin_expect(!(condition), 0)) { \
148 AOS_LOG(FATAL, "CHECK(%s) failed\n", #condition); \
Brian Silverman862b1632013-09-14 15:29:59 -0700149 }
150
Brian Silvermanb067abf2013-09-13 22:01:06 -0700151// Helper functions for CHECK_OP macro.
152// The (int, int) specialization works around the issue that the compiler
153// will not instantiate the template version of the function on values of
154// unnamed enum type.
Austin Schuhc69e6792021-02-05 11:20:05 -0800155#define AOS_DEFINE_CHECK_OP_IMPL(name, op) \
156 template <typename T1, typename T2> \
157 inline void LogImpl##name(const T1 &v1, const T2 &v2, \
158 const char *exprtext) { \
159 if (!__builtin_expect(v1 op v2, 1)) { \
160 log_do(FATAL, \
161 LOG_SOURCENAME \
162 ": " AOS_STRINGIFY(__LINE__) ": CHECK(%s) failed\n", \
163 exprtext); \
164 fprintf(stderr, "log_do(FATAL) fell through!!!!!\n"); \
165 printf("see stderr\n"); \
166 abort(); \
167 } \
168 } \
169 inline void LogImpl##name(int v1, int v2, const char *exprtext) { \
170 ::aos::LogImpl##name<int, int>(v1, v2, exprtext); \
Brian Silvermanb067abf2013-09-13 22:01:06 -0700171 }
172
173// We use the full name Check_EQ, Check_NE, etc. in case the file including
174// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
175// This happens if, for example, those are used as token names in a
176// yacc grammar.
Austin Schuh60e77942022-05-16 17:48:24 -0700177AOS_DEFINE_CHECK_OP_IMPL(Check_EQ,
178 ==) // Compilation error with CHECK_EQ(NULL, x)?
Austin Schuhf257f3c2019-10-27 21:00:43 -0700179AOS_DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead.
180AOS_DEFINE_CHECK_OP_IMPL(Check_LE, <=)
181AOS_DEFINE_CHECK_OP_IMPL(Check_LT, <)
182AOS_DEFINE_CHECK_OP_IMPL(Check_GE, >=)
183AOS_DEFINE_CHECK_OP_IMPL(Check_GT, >)
Brian Silvermanb067abf2013-09-13 22:01:06 -0700184
Austin Schuhf257f3c2019-10-27 21:00:43 -0700185#define AOS_CHECK_OP(name, op, val1, val2) \
Austin Schuhc69e6792021-02-05 11:20:05 -0800186 ::aos::LogImplCheck##name( \
187 val1, val2, AOS_STRINGIFY(val1) AOS_STRINGIFY(op) AOS_STRINGIFY(val2))
Brian Silvermanb067abf2013-09-13 22:01:06 -0700188
Austin Schuhf257f3c2019-10-27 21:00:43 -0700189#define AOS_CHECK_EQ(val1, val2) AOS_CHECK_OP(_EQ, ==, val1, val2)
190#define AOS_CHECK_NE(val1, val2) AOS_CHECK_OP(_NE, !=, val1, val2)
191#define AOS_CHECK_LE(val1, val2) AOS_CHECK_OP(_LE, <=, val1, val2)
192#define AOS_CHECK_LT(val1, val2) AOS_CHECK_OP(_LT, <, val1, val2)
193#define AOS_CHECK_GE(val1, val2) AOS_CHECK_OP(_GE, >=, val1, val2)
194#define AOS_CHECK_GT(val1, val2) AOS_CHECK_OP(_GT, >, val1, val2)
Brian Silvermanb067abf2013-09-13 22:01:06 -0700195
196// A small helper for CHECK_NOTNULL().
197template <typename T>
Austin Schuhf257f3c2019-10-27 21:00:43 -0700198inline T *CheckNotNull(const char *value_name, T *t) {
Brian Silvermanb067abf2013-09-13 22:01:06 -0700199 if (t == NULL) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700200 AOS_LOG(FATAL, "'%s' must not be NULL\n", value_name);
Brian Silvermanb067abf2013-09-13 22:01:06 -0700201 }
202 return t;
203}
204
205// Check that the input is non NULL. This very useful in constructor
206// initializer lists.
Austin Schuhc69e6792021-02-05 11:20:05 -0800207#define AOS_CHECK_NOTNULL(val) ::aos::CheckNotNull(AOS_STRINGIFY(val), val)
Brian Silvermanb067abf2013-09-13 22:01:06 -0700208
Brian Silvermanfe457de2014-05-26 22:04:08 -0700209inline int CheckSyscall(const char *syscall_string, int value) {
210 if (__builtin_expect(value == -1, false)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700211 AOS_PLOG(FATAL, "%s failed", syscall_string);
Brian Silvermanfe457de2014-05-26 22:04:08 -0700212 }
213 return value;
214}
215
Brian Silvermanb20e06a2014-09-03 12:09:24 -0400216inline void CheckSyscallReturn(const char *syscall_string, int value) {
217 if (__builtin_expect(value != 0, false)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700218 AOS_PELOG(FATAL, value, "%s failed", syscall_string);
Brian Silvermanb20e06a2014-09-03 12:09:24 -0400219 }
220}
221
Brian Silvermanfe457de2014-05-26 22:04:08 -0700222// Check that syscall does not return -1. If it does, PLOG(FATAL)s. This is
223// useful for quickly checking syscalls where it's not very useful to print out
Brian Silvermanb20e06a2014-09-03 12:09:24 -0400224// the values of any of the arguments. Returns the result otherwise.
225//
Austin Schuhf257f3c2019-10-27 21:00:43 -0700226// Example: const int fd = AOS_PCHECK(open("/tmp/whatever", O_WRONLY))
Austin Schuhc69e6792021-02-05 11:20:05 -0800227#define AOS_PCHECK(syscall) ::aos::CheckSyscall(AOS_STRINGIFY(syscall), syscall)
Brian Silvermanfe457de2014-05-26 22:04:08 -0700228
Brian Silvermanb20e06a2014-09-03 12:09:24 -0400229// PELOG(FATAL)s with the result of syscall if it returns anything other than 0.
230// This is useful for quickly checking things like many of the pthreads
231// functions where it's not very useful to print out the values of any of the
232// arguments.
233//
Austin Schuhf257f3c2019-10-27 21:00:43 -0700234// Example: AOS_PRCHECK(munmap(address, length))
235#define AOS_PRCHECK(syscall) \
Austin Schuhc69e6792021-02-05 11:20:05 -0800236 ::aos::CheckSyscallReturn(AOS_STRINGIFY(syscall), syscall)
Brian Silvermanb20e06a2014-09-03 12:09:24 -0400237
Brian Silvermanb067abf2013-09-13 22:01:06 -0700238} // namespace aos
239
240#endif // __cplusplus
241
brians343bc112013-02-10 01:53:46 +0000242#endif