blob: 7730c32cb3c2f9fff5339860ed605b5c16c0084c [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef INCLUDE_PERFETTO_BASE_LOGGING_H_
#define INCLUDE_PERFETTO_BASE_LOGGING_H_
#include <errno.h>
#include <string.h> // For strerror.
#include "perfetto/base/build_config.h"
#include "perfetto/base/compiler.h"
#include "perfetto/base/export.h"
#if defined(__GNUC__) || defined(__clang__)
// Ignore GCC warning about a missing argument for a variadic macro parameter.
#pragma GCC system_header
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_ON)
#define PERFETTO_DCHECK_IS_ON() 1
#elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DCHECK_OFF)
#define PERFETTO_DCHECK_IS_ON() 0
#elif defined(DCHECK_ALWAYS_ON) || \
(!defined(NDEBUG) && (PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \
PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD) || \
PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)))
#define PERFETTO_DCHECK_IS_ON() 1
#else
#define PERFETTO_DCHECK_IS_ON() 0
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_ON)
#define PERFETTO_DLOG_IS_ON() 1
#elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_OFF)
#define PERFETTO_DLOG_IS_ON() 0
#else
#define PERFETTO_DLOG_IS_ON() PERFETTO_DCHECK_IS_ON()
#endif
#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
!PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
#error "Async-safe logging is limited to Android tree builds"
#endif
// For binaries which need a very lightweight logging implementation.
// Note that this header is incompatible with android/log.h.
#include <async_safe/log.h>
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
// Normal android logging.
#include <android/log.h>
#endif
// Enable the "Print the most recent PERFETTO_LOG(s) before crashing" feature
// on Android in-tree builds and on standalone builds (mainly for testing).
// This is deliberately no PERFETTO_OS_ANDROID because we don't want this
// feature when perfetto is embedded in other Android projects (e.g. SDK).
// TODO(b/203795298): TFLite is using the client library in blaze builds and is
// targeting API 19. For now disable the feature based on API level.
#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
#define PERFETTO_ENABLE_LOG_RING_BUFFER() 0
#elif PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
#define PERFETTO_ENABLE_LOG_RING_BUFFER() 1
#elif PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) && \
(!PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
(defined(__ANDROID_API__) && __ANDROID_API__ >= 21))
#define PERFETTO_ENABLE_LOG_RING_BUFFER() 1
#else
#define PERFETTO_ENABLE_LOG_RING_BUFFER() 0
#endif
namespace perfetto {
namespace base {
// Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c .
constexpr const char* StrEnd(const char* s) {
return *s ? StrEnd(s + 1) : s;
}
constexpr const char* BasenameRecursive(const char* s,
const char* begin,
const char* end) {
return (*s == '/' && s < end)
? (s + 1)
: ((s > begin) ? BasenameRecursive(s - 1, begin, end) : s);
}
constexpr const char* Basename(const char* str) {
return BasenameRecursive(StrEnd(str), str, StrEnd(str));
}
enum LogLev { kLogDebug = 0, kLogInfo, kLogImportant, kLogError };
struct LogMessageCallbackArgs {
LogLev level;
int line;
const char* filename;
const char* message;
};
using LogMessageCallback = void (*)(LogMessageCallbackArgs);
// This is not thread safe and must be called before using tracing from other
// threads.
PERFETTO_EXPORT_COMPONENT void SetLogMessageCallback(
LogMessageCallback callback);
PERFETTO_EXPORT_COMPONENT void LogMessage(LogLev,
const char* fname,
int line,
const char* fmt,
...) PERFETTO_PRINTF_FORMAT(4, 5);
// This is defined in debug_crash_stack_trace.cc, but that is only linked in
// standalone && debug builds, see enable_perfetto_stderr_crash_dump in
// perfetto.gni.
PERFETTO_EXPORT_COMPONENT void EnableStacktraceOnCrashForDebug();
#if PERFETTO_ENABLE_LOG_RING_BUFFER()
// Gets a snapshot of the logs from the internal log ring buffer and:
// - On Android in-tree builds: Passes that to android_set_abort_message().
// That will attach the logs to the crash report.
// - On standalone builds (all otther OSes) prints that on stderr.
// This function must called only once, right before inducing a crash (This is
// because android_set_abort_message() can only be called once).
PERFETTO_EXPORT_COMPONENT void MaybeSerializeLastLogsForCrashReporting();
#else
inline void MaybeSerializeLastLogsForCrashReporting() {}
#endif
#if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
#define PERFETTO_XLOG(level, fmt, ...) \
do { \
async_safe_format_log((ANDROID_LOG_DEBUG + level), "perfetto", \
"%s:%d " fmt, ::perfetto::base::Basename(__FILE__), \
__LINE__, ##__VA_ARGS__); \
} while (0)
#elif defined(PERFETTO_DISABLE_LOG)
#define PERFETTO_XLOG(level, fmt, ...) ::perfetto::base::ignore_result(level, \
fmt, ##__VA_ARGS__)
#else
#define PERFETTO_XLOG(level, fmt, ...) \
::perfetto::base::LogMessage(level, ::perfetto::base::Basename(__FILE__), \
__LINE__, fmt, ##__VA_ARGS__)
#endif
#if defined(_MSC_VER)
#define PERFETTO_IMMEDIATE_CRASH() \
do { \
::perfetto::base::MaybeSerializeLastLogsForCrashReporting(); \
__debugbreak(); \
__assume(0); \
} while (0)
#else
#define PERFETTO_IMMEDIATE_CRASH() \
do { \
::perfetto::base::MaybeSerializeLastLogsForCrashReporting(); \
__builtin_trap(); \
__builtin_unreachable(); \
} while (0)
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
#define PERFETTO_LOG(fmt, ...) \
PERFETTO_XLOG(::perfetto::base::kLogInfo, fmt, ##__VA_ARGS__)
#else // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
#define PERFETTO_LOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
#endif // PERFETTO_BUILDFLAG(PERFETTO_VERBOSE_LOGS)
#define PERFETTO_ILOG(fmt, ...) \
PERFETTO_XLOG(::perfetto::base::kLogImportant, fmt, ##__VA_ARGS__)
#define PERFETTO_ELOG(fmt, ...) \
PERFETTO_XLOG(::perfetto::base::kLogError, fmt, ##__VA_ARGS__)
#define PERFETTO_FATAL(fmt, ...) \
do { \
PERFETTO_PLOG(fmt, ##__VA_ARGS__); \
PERFETTO_IMMEDIATE_CRASH(); \
} while (0)
#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_PLOG(x, ...) \
PERFETTO_ELOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
#else
// MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
#define PERFETTO_PLOG PERFETTO_ELOG
#endif
#define PERFETTO_CHECK(x) \
do { \
if (PERFETTO_UNLIKELY(!(x))) { \
PERFETTO_PLOG("%s", "PERFETTO_CHECK(" #x ")"); \
PERFETTO_IMMEDIATE_CRASH(); \
} \
} while (0)
#if PERFETTO_DLOG_IS_ON()
#define PERFETTO_DLOG(fmt, ...) \
PERFETTO_XLOG(::perfetto::base::kLogDebug, fmt, ##__VA_ARGS__)
#if defined(__GNUC__) || defined(__clang__)
#define PERFETTO_DPLOG(x, ...) \
PERFETTO_DLOG(x " (errno: %d, %s)", ##__VA_ARGS__, errno, strerror(errno))
#else
// MSVC expands __VA_ARGS__ in a different order. Give up, not worth it.
#define PERFETTO_DPLOG PERFETTO_DLOG
#endif
#else // PERFETTO_DLOG_IS_ON()
#define PERFETTO_DLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
#define PERFETTO_DPLOG(...) ::perfetto::base::ignore_result(__VA_ARGS__)
#endif // PERFETTO_DLOG_IS_ON()
#if PERFETTO_DCHECK_IS_ON()
#define PERFETTO_DCHECK(x) PERFETTO_CHECK(x)
#define PERFETTO_DFATAL(...) PERFETTO_FATAL(__VA_ARGS__)
#define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_DFATAL(__VA_ARGS__)
#else // PERFETTO_DCHECK_IS_ON()
#define PERFETTO_DCHECK(x) \
do { \
} while (false && (x))
#define PERFETTO_DFATAL(...) ::perfetto::base::ignore_result(__VA_ARGS__)
#define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_ELOG(__VA_ARGS__)
#endif // PERFETTO_DCHECK_IS_ON()
} // namespace base
} // namespace perfetto
#endif // INCLUDE_PERFETTO_BASE_LOGGING_H_