Path: blob/master/src/hotspot/share/logging/log.hpp
40930 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/23#ifndef SHARE_LOGGING_LOG_HPP24#define SHARE_LOGGING_LOG_HPP2526#include "logging/logLevel.hpp"27#include "logging/logPrefix.hpp"28#include "logging/logTagSet.hpp"29#include "logging/logTag.hpp"30#include "utilities/debug.hpp"3132class LogMessageBuffer;3334//35// Logging macros36//37// Usage:38// log_<level>(<comma separated log tags>)(<printf-style log arguments>);39// e.g.40// log_debug(logging)("message %d", i);41//42// Note that these macros will not evaluate the arguments unless the logging is enabled.43//44#define log_error(...) (!log_is_enabled(Error, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Error>45#define log_warning(...) (!log_is_enabled(Warning, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Warning>46#define log_info(...) (!log_is_enabled(Info, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info>47#define log_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug>48#define log_trace(...) (!log_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace>4950// Macros for logging that should be excluded in product builds.51// Available for levels Info, Debug and Trace. Includes test macro that52// evaluates to false in product builds.53#ifndef PRODUCT54#define log_develop_info(...) (!log_is_enabled(Info, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info>55#define log_develop_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug>56#define log_develop_trace(...) (!log_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : LogImpl<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace>57#define log_develop_is_enabled(level, ...) log_is_enabled(level, __VA_ARGS__)58#else59#define DUMMY_ARGUMENT_CONSUMER(...)60#define log_develop_info(...) DUMMY_ARGUMENT_CONSUMER61#define log_develop_debug(...) DUMMY_ARGUMENT_CONSUMER62#define log_develop_trace(...) DUMMY_ARGUMENT_CONSUMER63#define log_develop_is_enabled(...) false64#endif6566// Convenience macro to test if the logging is enabled on the specified level for given tags.67#define log_is_enabled(level, ...) (LogImpl<LOG_TAGS(__VA_ARGS__)>::is_level(LogLevel::level))6869//70// Log class for more advanced logging scenarios.71// Has printf-style member functions for each log level (trace(), debug(), etc).72//73// The (trace(), debug(), etc) functions can also be used along with the LogStream74// class to obtain an outputStream object, to be passed to various printing75// functions that accept an outputStream:76//77// Example usage:78// Log(codecache, sweep) log;79// if (log.is_debug()) {80// log.debug("result = %d", result).trace(" tracing info");81// LogStream ls(log.debug());82// CodeCache::print_summary(&ls, false);83// }84//85#define Log(...) LogImpl<LOG_TAGS(__VA_ARGS__)>8687//88// Log class that embeds both log tags and a log level.89//90// The class provides a way to write the tags and log level once,91// so that redundant specification of tags or levels can be avoided.92//93// Example usage:94// LogTarget(Debug, codecache, sweep) out;95// if (out.is_enabled()) {96// out.print("result = %d", result);97// LogStream ls(out);98// CodeCache::print_summary(&ls, false);99// }100//101#define LogTarget(level, ...) LogTargetImpl<LogLevel::level, LOG_TAGS(__VA_ARGS__)>102103template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>104class LogTargetImpl;105106template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG, LogTagType T3 = LogTag::__NO_TAG,107LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>108class LogImpl {109private:110static const size_t LogBufferSize = 512;111public:112// Make sure no more than the maximum number of tags have been given.113// The GuardTag allows this to be detected if/when it happens. If the GuardTag114// is not __NO_TAG, the number of tags given exceeds the maximum allowed.115STATIC_ASSERT(GuardTag == LogTag::__NO_TAG); // Number of logging tags exceeds maximum supported!116117// Empty constructor to avoid warnings on MSVC about unused variables118// when the log instance is only used for static functions.119LogImpl() {120}121122static bool is_level(LogLevelType level) {123return LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().is_level(level);124}125126ATTRIBUTE_PRINTF(2, 3)127static void write(LogLevelType level, const char* fmt, ...) {128va_list args;129va_start(args, fmt);130vwrite(level, fmt, args);131va_end(args);132}133134static void write(const LogMessageBuffer& msg) {135LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().log(msg);136};137138template <LogLevelType Level>139ATTRIBUTE_PRINTF(1, 2)140static void write(const char* fmt, ...) {141va_list args;142va_start(args, fmt);143vwrite(Level, fmt, args);144va_end(args);145}146147ATTRIBUTE_PRINTF(2, 0)148static void vwrite(LogLevelType level, const char* fmt, va_list args) {149LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().vwrite(level, fmt, args);150}151152#define LOG_LEVEL(level, name) ATTRIBUTE_PRINTF(2, 0) \153LogImpl& v##name(const char* fmt, va_list args) { \154vwrite(LogLevel::level, fmt, args); \155return *this; \156} \157LogImpl& name(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3) { \158va_list args; \159va_start(args, fmt); \160vwrite(LogLevel::level, fmt, args); \161va_end(args); \162return *this; \163} \164static bool is_##name() { \165return is_level(LogLevel::level); \166} \167static LogTargetImpl<LogLevel::level, T0, T1, T2, T3, T4, GuardTag>* name() { \168return (LogTargetImpl<LogLevel::level, T0, T1, T2, T3, T4, GuardTag>*)NULL; \169}170LOG_LEVEL_LIST171#undef LOG_LEVEL172};173174// Combines logging tags and a logging level.175template <LogLevelType level, LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG,176LogTagType T3 = LogTag::__NO_TAG, LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>177class LogTargetImpl {178public:179// Empty constructor to avoid warnings on MSVC about unused variables180// when the log instance is only used for static functions.181LogTargetImpl() {182}183184static bool is_enabled() {185return LogImpl<T0, T1, T2, T3, T4, GuardTag>::is_level(level);186}187188static bool develop_is_enabled() {189NOT_PRODUCT(return is_enabled());190PRODUCT_ONLY(return false);191}192193static void print(const char* fmt, ...) ATTRIBUTE_PRINTF(1, 2) {194va_list args;195va_start(args, fmt);196LogImpl<T0, T1, T2, T3, T4, GuardTag>::vwrite(level, fmt, args);197va_end(args);198}199200};201202#endif // SHARE_LOGGING_LOG_HPP203204205