blob: 03f3e316ff4e4cb561a0bddc2032cf0c83930fa7 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef AOS_COMMON_LOGGING_LOGGING_H_
brians343bc112013-02-10 01:53:46 +00002#define AOS_COMMON_LOGGING_LOGGING_H_
3
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
7#include <stdio.h>
brians343bc112013-02-10 01:53:46 +00008#include <stdint.h>
Brian Silvermanb067abf2013-09-13 22:01:06 -07009#include <stdlib.h>
brians343bc112013-02-10 01:53:46 +000010
Brian Silvermana7234c62014-03-24 20:23:25 -070011#include "aos/common/macros.h"
12
brians343bc112013-02-10 01:53:46 +000013#ifdef __cplusplus
14extern "C" {
15#endif
16
17typedef uint8_t log_level;
Brian Silvermanf665d692013-02-17 22:11:39 -080018
brians343bc112013-02-10 01:53:46 +000019#define DECL_LEVELS \
20DECL_LEVEL(DEBUG, 0); /* stuff that gets printed out every cycle */ \
21DECL_LEVEL(INFO, 1); /* things like PosEdge/NegEdge */ \
Brian Silvermanf665d692013-02-17 22:11:39 -080022/* things that might still work if they happen occasionally */ \
brians343bc112013-02-10 01:53:46 +000023DECL_LEVEL(WARNING, 2); \
24/*-1 so that vxworks macro of same name will have same effect if used*/ \
25DECL_LEVEL(ERROR, -1); /* errors */ \
Brian Silvermanf665d692013-02-17 22:11:39 -080026/* serious errors. the logging code will terminate the process/task */ \
27DECL_LEVEL(FATAL, 4); \
brians343bc112013-02-10 01:53:46 +000028DECL_LEVEL(LOG_UNKNOWN, 5); /* unknown logging level */
Brian Silvermanf665d692013-02-17 22:11:39 -080029#define DECL_LEVEL(name, value) static const log_level name = value;
Brian Silvermanf665d692013-02-17 22:11:39 -080030DECL_LEVELS;
brians343bc112013-02-10 01:53:46 +000031#undef DECL_LEVEL
32
Brian Silvermanb0893882014-02-10 14:48:30 -080033// Not static const size_t for C code.
Brian Silvermanc11f3b72013-03-19 18:32:02 -070034#define LOG_MESSAGE_LEN 400
Brian Silvermanf665d692013-02-17 22:11:39 -080035
Brian Silvermanf665d692013-02-17 22:11:39 -080036#ifdef __cplusplus
37extern "C" {
38#endif
39// Actually implements the basic logging call.
40// Does not check that level is valid.
41void log_do(log_level level, const char *format, ...)
Brian Silvermanf7986142014-04-21 17:42:35 -070042 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 3)));
Brian Silvermanf665d692013-02-17 22:11:39 -080043
44void log_cork(int line, const char *function, const char *format, ...)
Brian Silvermanf7986142014-04-21 17:42:35 -070045 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4)));
Brian Silvermanf665d692013-02-17 22:11:39 -080046// Implements the uncork logging call.
47void log_uncork(int line, const char *function, log_level level,
48 const char *file, const char *format, ...)
Brian Silvermanf7986142014-04-21 17:42:35 -070049 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 5, 6)));
Brian Silvermanf665d692013-02-17 22:11:39 -080050#ifdef __cplusplus
51}
52#endif
53
54// A magical static const char[] or string literal that communicates the name
55// of the enclosing function.
56// It's currently using __PRETTY_FUNCTION__ because both GCC and Clang support
57// that and it gives nicer results in C++ than the standard __func__ (which
58// would also work).
Brian Silvermanc11f3b72013-03-19 18:32:02 -070059//#define LOG_CURRENT_FUNCTION __PRETTY_FUNCTION__
60#define LOG_CURRENT_FUNCTION __func__
Brian Silvermanf665d692013-02-17 22:11:39 -080061
Brian Silverman8fc7bc92013-03-13 23:15:47 -070062#define LOG_SOURCENAME __FILE__
63
Brian Silvermanf665d692013-02-17 22:11:39 -080064// The basic logging call.
Brian Silvermand6974f42014-02-14 13:39:21 -080065#define LOG(level, format, args...) \
66 do { \
67 log_do(level, LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": %s: " format, \
68 LOG_CURRENT_FUNCTION, ##args); \
69 /* so that GCC knows that it won't return */ \
70 if (level == FATAL) { \
71 fprintf(stderr, "log_do(FATAL) fell through!!!!!\n"); \
72 printf("see stderr\n"); \
73 abort(); \
74 } \
75 } while (0)
brians343bc112013-02-10 01:53:46 +000076
77// Allows format to not be a string constant.
Brian Silvermand6974f42014-02-14 13:39:21 -080078#define LOG_DYNAMIC(level, format, args...) \
79 do { \
80 static char log_buf[LOG_MESSAGE_LEN]; \
81 int ret = snprintf(log_buf, sizeof(log_buf), format, ##args); \
82 if (ret < 0 || (uintmax_t)ret >= LOG_MESSAGE_LEN) { \
83 LOG(ERROR, "next message was too long so not subbing in args\n"); \
84 LOG(level, "%s", format); \
85 } else { \
86 LOG(level, "%s", log_buf); \
87 } \
88 } while (0)
brians343bc112013-02-10 01:53:46 +000089
Brian Silvermanf665d692013-02-17 22:11:39 -080090// Allows "bottling up" multiple log fragments which can then all be logged in
91// one message with LOG_UNCORK.
92// Calls from a given thread/task will be grouped together.
Brian Silvermand6974f42014-02-14 13:39:21 -080093#define LOG_CORK(format, args...) \
94 do { \
95 log_cork(__LINE__, LOG_CURRENT_FUNCTION, format, ##args); \
96 } while (0)
Brian Silvermanf665d692013-02-17 22:11:39 -080097// Actually logs all of the saved up log fragments (including format and args on
98// the end).
Brian Silvermand6974f42014-02-14 13:39:21 -080099#define LOG_UNCORK(level, format, args...) \
100 do { \
101 log_uncork(__LINE__, LOG_CURRENT_FUNCTION, level, LOG_SOURCENAME, format, \
102 ##args); \
103 } while (0)
brians343bc112013-02-10 01:53:46 +0000104
brians343bc112013-02-10 01:53:46 +0000105#ifdef __cplusplus
106}
107#endif
108
Brian Silvermanb067abf2013-09-13 22:01:06 -0700109#ifdef __cplusplus
110
111namespace aos {
112
113// CHECK* macros, similar to glog
114// (<http://google-glog.googlecode.com/svn/trunk/doc/glog.html>)'s, except they
115// don't support streaming in extra text. Some of the implementation is borrowed
116// from there too.
117// They all LOG(FATAL) with a helpful message when the check fails.
118// TODO(brians): Replace assert with CHECK
119// Portions copyright (c) 1999, Google Inc.
120// All rights reserved.
121//
122// Redistribution and use in source and binary forms, with or without
123// modification, are permitted provided that the following conditions are
124// met:
125//
126// * Redistributions of source code must retain the above copyright
127// notice, this list of conditions and the following disclaimer.
128// * Redistributions in binary form must reproduce the above
129// copyright notice, this list of conditions and the following disclaimer
130// in the documentation and/or other materials provided with the
131// distribution.
132// * Neither the name of Google Inc. nor the names of its
133// contributors may be used to endorse or promote products derived from
134// this software without specific prior written permission.
135//
136// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
137// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
138// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
139// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
140// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
141// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
142// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
143// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
144// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
145// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
146// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
147
Brian Silverman862b1632013-09-14 15:29:59 -0700148// CHECK dies with a fatal error if condition is not true. It is *not*
149// controlled by NDEBUG, so the check will be executed regardless of
150// compilation mode. Therefore, it is safe to do things like:
151// CHECK(fp->Write(x) == 4)
Brian Silvermand6974f42014-02-14 13:39:21 -0800152#define CHECK(condition) \
153 if (__builtin_expect(!(condition), 0)) { \
Brian Silverman5d790752014-01-01 13:25:36 -0800154 LOG(FATAL, "CHECK(%s) failed\n", #condition); \
Brian Silverman862b1632013-09-14 15:29:59 -0700155 }
156
Brian Silvermanb067abf2013-09-13 22:01:06 -0700157// Helper functions for CHECK_OP macro.
158// The (int, int) specialization works around the issue that the compiler
159// will not instantiate the template version of the function on values of
160// unnamed enum type.
Brian Silvermand6974f42014-02-14 13:39:21 -0800161#define DEFINE_CHECK_OP_IMPL(name, op) \
162 template <typename T1, typename T2> \
163 inline void LogImpl##name(const T1 &v1, const T2 &v2, \
164 const char *exprtext) { \
165 if (!__builtin_expect(v1 op v2, 1)) { \
166 LOG(FATAL, "CHECK(%s) failed\n", exprtext); \
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.
177DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)?
178DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead.
179DEFINE_CHECK_OP_IMPL(Check_LE, <=)
180DEFINE_CHECK_OP_IMPL(Check_LT, < )
181DEFINE_CHECK_OP_IMPL(Check_GE, >=)
182DEFINE_CHECK_OP_IMPL(Check_GT, > )
183
Brian Silvermand6974f42014-02-14 13:39:21 -0800184#define CHECK_OP(name, op, val1, val2) \
Brian Silvermanb067abf2013-09-13 22:01:06 -0700185 ::aos::LogImplCheck##name(val1, val2, \
186 STRINGIFY(val1) STRINGIFY(op) STRINGIFY(val2))
187
188#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
189#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
190#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
191#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
192#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
193#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
194
195// A small helper for CHECK_NOTNULL().
196template <typename T>
197inline T* CheckNotNull(const char *value_name, T *t) {
198 if (t == NULL) {
199 LOG(FATAL, "'%s' must not be NULL\n", value_name);
200 }
201 return t;
202}
203
204// Check that the input is non NULL. This very useful in constructor
205// initializer lists.
Brian Silvermand6974f42014-02-14 13:39:21 -0800206#define CHECK_NOTNULL(val) ::aos::CheckNotNull(STRINGIFY(val), val)
Brian Silvermanb067abf2013-09-13 22:01:06 -0700207
208} // namespace aos
209
210#endif // __cplusplus
211
brians343bc112013-02-10 01:53:46 +0000212#endif