mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8152635: Create a UL class to represent a Log + Level combination
Reviewed-by: brutisso, mlarsson, rehn
This commit is contained in:
parent
64efc0eb0f
commit
65a3b7e6b3
4 changed files with 118 additions and 7 deletions
|
@ -2373,14 +2373,14 @@ void CompactibleFreeListSpace::check_free_list_consistency() const {
|
||||||
|
|
||||||
void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
|
void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
|
||||||
assert_lock_strong(&_freelistLock);
|
assert_lock_strong(&_freelistLock);
|
||||||
Log(gc, freelist, census) log;
|
LogTarget(Debug, gc, freelist, census) log;
|
||||||
if (!log.is_debug()) {
|
if (!log.is_enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AdaptiveFreeList<FreeChunk> total;
|
AdaptiveFreeList<FreeChunk> total;
|
||||||
log.debug("end sweep# " SIZE_FORMAT, sweep_count);
|
log.print("end sweep# " SIZE_FORMAT, sweep_count);
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
outputStream* out = log.debug_stream();
|
outputStream* out = log.stream();
|
||||||
AdaptiveFreeList<FreeChunk>::print_labels_on(out, "size");
|
AdaptiveFreeList<FreeChunk>::print_labels_on(out, "size");
|
||||||
size_t total_free = 0;
|
size_t total_free = 0;
|
||||||
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
|
||||||
|
@ -2402,8 +2402,8 @@ void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
|
||||||
total.set_split_deaths(total.split_deaths() + fl->split_deaths());
|
total.set_split_deaths(total.split_deaths() + fl->split_deaths());
|
||||||
}
|
}
|
||||||
total.print_on(out, "TOTAL");
|
total.print_on(out, "TOTAL");
|
||||||
log.debug("Total free in indexed lists " SIZE_FORMAT " words", total_free);
|
log.print("Total free in indexed lists " SIZE_FORMAT " words", total_free);
|
||||||
log.debug("growth: %8.5f deficit: %8.5f",
|
log.print("growth: %8.5f deficit: %8.5f",
|
||||||
(double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/
|
(double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/
|
||||||
(total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0),
|
(total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0),
|
||||||
(double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
|
(double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
|
||||||
|
|
|
@ -93,6 +93,7 @@ class TestLogSavedConfig {
|
||||||
Log(logging) _log;
|
Log(logging) _log;
|
||||||
public:
|
public:
|
||||||
TestLogSavedConfig(const char* apply_output = NULL, const char* apply_setting = NULL) : _new_output(0) {
|
TestLogSavedConfig(const char* apply_output = NULL, const char* apply_setting = NULL) : _new_output(0) {
|
||||||
|
ResourceMark rm;
|
||||||
_saved_config = os::strdup_check_oom(LogOutput::Stdout->config_string());
|
_saved_config = os::strdup_check_oom(LogOutput::Stdout->config_string());
|
||||||
bool success = LogConfiguration::parse_log_arguments("stdout", "all=off", NULL, NULL, _log.error_stream());
|
bool success = LogConfiguration::parse_log_arguments("stdout", "all=off", NULL, NULL, _log.error_stream());
|
||||||
assert(success, "test unable to turn all off");
|
assert(success, "test unable to turn all off");
|
||||||
|
@ -105,6 +106,7 @@ class TestLogSavedConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
~TestLogSavedConfig() {
|
~TestLogSavedConfig() {
|
||||||
|
ResourceMark rm;
|
||||||
if (_new_output) {
|
if (_new_output) {
|
||||||
bool success = LogConfiguration::parse_log_arguments(_new_output, "all=off", NULL, NULL, _log.error_stream());
|
bool success = LogConfiguration::parse_log_arguments(_new_output, "all=off", NULL, NULL, _log.error_stream());
|
||||||
assert(success, "test unable to turn all off");
|
assert(success, "test unable to turn all off");
|
||||||
|
@ -154,7 +156,7 @@ void Test_logconfiguration_subscribe() {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
Log(logging) log;
|
Log(logging) log;
|
||||||
|
|
||||||
TestLogSavedConfig log_cfg("stdout", "logging+test=trace");
|
TestLogSavedConfig log_cfg("stdout", "logging*=trace");
|
||||||
|
|
||||||
LogConfiguration::register_update_listener(&Test_logconfiguration_subscribe_helper);
|
LogConfiguration::register_update_listener(&Test_logconfiguration_subscribe_helper);
|
||||||
|
|
||||||
|
@ -267,4 +269,68 @@ void Test_logtagset_duplicates() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define Test_logtarget_string_literal "First line"
|
||||||
|
|
||||||
|
|
||||||
|
static void Test_logtarget_on() {
|
||||||
|
TestLogFile log_file("log_target");
|
||||||
|
TestLogSavedConfig tlsc(log_file.name(), "gc=debug");
|
||||||
|
|
||||||
|
LogTarget(Debug, gc) log;
|
||||||
|
|
||||||
|
assert(log.is_enabled(), "assert");
|
||||||
|
|
||||||
|
// Log the line and expect it to be available in the output file.
|
||||||
|
log.print(Test_logtarget_string_literal);
|
||||||
|
|
||||||
|
FILE* fp = fopen(log_file.name(), "r");
|
||||||
|
assert(fp != NULL, "File read error");
|
||||||
|
|
||||||
|
char output[256 /* Large enough buffer */];
|
||||||
|
char* res = fgets(output, sizeof(output), fp);
|
||||||
|
assert(res != NULL, "assert");
|
||||||
|
|
||||||
|
assert(strstr(output, Test_logtarget_string_literal) != NULL, "log line missing");
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Test_logtarget_off() {
|
||||||
|
TestLogFile log_file("log_target");
|
||||||
|
TestLogSavedConfig tlsc(log_file.name(), "gc=info");
|
||||||
|
|
||||||
|
LogTarget(Debug, gc) log;
|
||||||
|
|
||||||
|
if (log.is_enabled()) {
|
||||||
|
// The log config could have been redirected gc=debug to a file. If gc=debug
|
||||||
|
// is enabled, we can only test that the LogTarget returns the same value
|
||||||
|
// as the log_is_enabled function. The rest of the test will be ignored.
|
||||||
|
assert(log.is_enabled() == log_is_enabled(Debug, gc), "assert");
|
||||||
|
log_warning(logging)("This test doesn't support runs with -Xlog");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to log, but expect this to be filtered out.
|
||||||
|
log.print(Test_logtarget_string_literal);
|
||||||
|
|
||||||
|
// Log a dummy line so that fgets doesn't return NULL because the file is empty.
|
||||||
|
log_info(gc)("Dummy line");
|
||||||
|
|
||||||
|
FILE* fp = fopen(log_file.name(), "r");
|
||||||
|
assert(fp != NULL, "File read error");
|
||||||
|
|
||||||
|
char output[256 /* Large enough buffer */];
|
||||||
|
char* res = fgets(output, sizeof(output), fp);
|
||||||
|
assert(res != NULL, "assert");
|
||||||
|
|
||||||
|
assert(strstr(output, Test_logtarget_string_literal) == NULL, "log line not missing");
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Test_logtarget() {
|
||||||
|
Test_logtarget_on();
|
||||||
|
Test_logtarget_off();
|
||||||
|
}
|
||||||
|
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
|
@ -106,6 +106,24 @@ class LogWriteHelper : AllStatic {
|
||||||
va_list args);
|
va_list args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Log class that embeds both log tags and a log level.
|
||||||
|
//
|
||||||
|
// The class provides a way to write the tags and log level once,
|
||||||
|
// so that redundant specification of tags or levels can be avoided.
|
||||||
|
//
|
||||||
|
// Example usage:
|
||||||
|
// LogTarget(Debug, gc) out;
|
||||||
|
// if (out.is_enabled()) {
|
||||||
|
// ...
|
||||||
|
// out.print("Worker: %u", i);
|
||||||
|
// out.print(" data: %d", x);
|
||||||
|
// ...
|
||||||
|
// print_stats(out.stream());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
#define LogTarget(level, ...) LogTargetImpl<LogLevel::level, LOG_TAGS(__VA_ARGS__)>
|
||||||
|
|
||||||
template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG, LogTagType T3 = LogTag::__NO_TAG,
|
template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG, LogTagType T3 = LogTag::__NO_TAG,
|
||||||
LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>
|
LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>
|
||||||
class LogImpl VALUE_OBJ_CLASS_SPEC {
|
class LogImpl VALUE_OBJ_CLASS_SPEC {
|
||||||
|
@ -184,4 +202,30 @@ class LogImpl VALUE_OBJ_CLASS_SPEC {
|
||||||
#undef LOG_LEVEL
|
#undef LOG_LEVEL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Combines logging tags and a logging level.
|
||||||
|
template <LogLevelType level, LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG,
|
||||||
|
LogTagType T3 = LogTag::__NO_TAG, LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>
|
||||||
|
class LogTargetImpl {
|
||||||
|
public:
|
||||||
|
// Empty constructor to avoid warnings on MSVC about unused variables
|
||||||
|
// when the log instance is only used for static functions.
|
||||||
|
LogTargetImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_enabled() {
|
||||||
|
return LogImpl<T0, T1, T2, T3, T4, GuardTag>::is_level(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print(const char* fmt, ...) ATTRIBUTE_PRINTF(1, 2) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
LogImpl<T0, T1, T2, T3, T4, GuardTag>::vwrite(level, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static outputStream* stream() {
|
||||||
|
return new logStream(&LogImpl<T0, T1, T2, T3, T4, GuardTag>::template write<level>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_LOGGING_LOG_HPP
|
#endif // SHARE_VM_LOGGING_LOG_HPP
|
||||||
|
|
|
@ -67,6 +67,7 @@ void InternalVMTests::run() {
|
||||||
run_unit_test(Test_linked_list);
|
run_unit_test(Test_linked_list);
|
||||||
run_unit_test(TestChunkedList_test);
|
run_unit_test(TestChunkedList_test);
|
||||||
run_unit_test(JSON_test);
|
run_unit_test(JSON_test);
|
||||||
|
run_unit_test(Test_logtarget);
|
||||||
run_unit_test(Test_configure_stdout);
|
run_unit_test(Test_configure_stdout);
|
||||||
run_unit_test(Test_logconfiguration_subscribe);
|
run_unit_test(Test_logconfiguration_subscribe);
|
||||||
run_unit_test(Test_log_prefix);
|
run_unit_test(Test_log_prefix);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue