Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef INCLUDE_PERFETTO_BASE_LOGGING_H_
     18 #define INCLUDE_PERFETTO_BASE_LOGGING_H_
     19 
     20 #include <errno.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>  // For strerror.
     24 #include <unistd.h>
     25 
     26 #if defined(NDEBUG)
     27 #define PERFETTO_DCHECK_IS_ON() 0
     28 #else
     29 #define PERFETTO_DCHECK_IS_ON() 1
     30 #endif
     31 
     32 #include "perfetto/base/build_config.h"
     33 #include "perfetto/base/utils.h"
     34 
     35 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
     36 #include <android/log.h>
     37 #endif
     38 
     39 namespace perfetto {
     40 namespace base {
     41 
     42 // Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c .
     43 constexpr const char* StrEnd(const char* s) {
     44   return *s ? StrEnd(s + 1) : s;
     45 }
     46 
     47 constexpr const char* BasenameRecursive(const char* s,
     48                                         const char* begin,
     49                                         const char* end) {
     50   return (*s == '/' && s < end)
     51              ? (s + 1)
     52              : ((s > begin) ? BasenameRecursive(s - 1, begin, end) : s);
     53 }
     54 
     55 constexpr const char* Basename(const char* str) {
     56   return BasenameRecursive(StrEnd(str), str, StrEnd(str));
     57 }
     58 
     59 enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError };
     60 constexpr const char* kLogFmt[] = {"\x1b[2m", "\x1b[39m", "\x1b[32m\x1b[1m",
     61                                    "\x1b[31m"};
     62 
     63 #define PERFETTO_LOG_LINE__(x) #x
     64 #define PERFETTO_LOG_LINE_(x) PERFETTO_LOG_LINE__(x)
     65 #define PERFETTO_LOG_LINE PERFETTO_LOG_LINE_(__LINE__)
     66 
     67 #define PERFETTO_XLOG_STDERR(level, fmt, ...)                         \
     68   fprintf(stderr, "\x1b[90m%-24.24s\x1b[0m %s" fmt "\x1b[0m\n",       \
     69           ::perfetto::base::Basename(__FILE__ ":" PERFETTO_LOG_LINE), \
     70           ::perfetto::base::kLogFmt[::perfetto::base::LogLev::level], \
     71           ##__VA_ARGS__)
     72 
     73 // Let android log to both stderr and logcat. When part of the Android tree
     74 // stderr points to /dev/null so logcat is the only way to get some logging.
     75 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
     76 #define PERFETTO_XLOG(level, fmt, ...)                                         \
     77   do {                                                                         \
     78     __android_log_print(                                                       \
     79         (ANDROID_LOG_DEBUG + ::perfetto::base::LogLev::level), "perfetto",     \
     80         "%s " fmt, ::perfetto::base::Basename(__FILE__ ":" PERFETTO_LOG_LINE), \
     81         ##__VA_ARGS__);                                                        \
     82     PERFETTO_XLOG_STDERR(level, fmt, ##__VA_ARGS__);                           \
     83   } while (0)
     84 #else
     85 #define PERFETTO_XLOG PERFETTO_XLOG_STDERR
     86 #endif
     87 
     88 #define PERFETTO_IMMEDIATE_CRASH() \
     89   do {                             \
     90     __builtin_trap();              \
     91     __builtin_unreachable();       \
     92   } while (0)
     93 
     94 #define PERFETTO_LOG(fmt, ...) PERFETTO_XLOG(kLogInfo, fmt, ##__VA_ARGS__)
     95 #define PERFETTO_ILOG(fmt, ...) PERFETTO_XLOG(kLogImportant, fmt, ##__VA_ARGS__)
     96 #define PERFETTO_ELOG(fmt, ...) PERFETTO_XLOG(kLogError, fmt, ##__VA_ARGS__)
     97 #define PERFETTO_FATAL(fmt, ...)       \
     98   do {                                 \
     99     PERFETTO_ELOG(fmt, ##__VA_ARGS__); \
    100     PERFETTO_IMMEDIATE_CRASH();        \
    101   } while (0)
    102 
    103 #define PERFETTO_PLOG(x, ...) \
    104   PERFETTO_ELOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
    105 
    106 #if PERFETTO_DCHECK_IS_ON()
    107 
    108 #define PERFETTO_DLOG(fmt, ...) PERFETTO_XLOG(kLogDebug, fmt, ##__VA_ARGS__)
    109 
    110 #define PERFETTO_DPLOG(x, ...) \
    111   PERFETTO_DLOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
    112 
    113 #define PERFETTO_DCHECK(x)                            \
    114   do {                                                \
    115     if (PERFETTO_UNLIKELY(!(x))) {                    \
    116       PERFETTO_DPLOG("%s", "PERFETTO_CHECK(" #x ")"); \
    117       PERFETTO_IMMEDIATE_CRASH();                     \
    118     }                                                 \
    119   } while (0)
    120 
    121 #else
    122 
    123 #define PERFETTO_DLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
    124 #define PERFETTO_DPLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
    125 #define PERFETTO_DCHECK(x) ::perfetto::base::ignore_result(x)
    126 
    127 #endif  // PERFETTO_DCHECK_IS_ON()
    128 
    129 #if PERFETTO_DCHECK_IS_ON()
    130 #define PERFETTO_CHECK(x) PERFETTO_DCHECK(x)
    131 #else
    132 #define PERFETTO_CHECK(x)                            \
    133   do {                                               \
    134     if (PERFETTO_UNLIKELY(!(x))) {                   \
    135       PERFETTO_ELOG("%s", "PERFETTO_CHECK(" #x ")"); \
    136       PERFETTO_IMMEDIATE_CRASH();                    \
    137     }                                                \
    138   } while (0)
    139 
    140 #endif  // PERFETTO_DCHECK_IS_ON()
    141 
    142 }  // namespace base
    143 }  // namespace perfetto
    144 
    145 #endif  // INCLUDE_PERFETTO_BASE_LOGGING_H_
    146