8152635: Create a UL class to represent a Log + Level combination

Reviewed-by: brutisso, mlarsson, rehn
This commit is contained in:
Stefan Karlsson 2016-04-04 12:45:04 +02:00
parent 64efc0eb0f
commit 65a3b7e6b3
4 changed files with 118 additions and 7 deletions
hotspot/src/share/vm

@ -2373,14 +2373,14 @@ void CompactibleFreeListSpace::check_free_list_consistency() const {
void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
assert_lock_strong(&_freelistLock);
Log(gc, freelist, census) log;
if (!log.is_debug()) {
LogTarget(Debug, gc, freelist, census) log;
if (!log.is_enabled()) {
return;
}
AdaptiveFreeList<FreeChunk> total;
log.debug("end sweep# " SIZE_FORMAT, sweep_count);
log.print("end sweep# " SIZE_FORMAT, sweep_count);
ResourceMark rm;
outputStream* out = log.debug_stream();
outputStream* out = log.stream();
AdaptiveFreeList<FreeChunk>::print_labels_on(out, "size");
size_t total_free = 0;
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.print_on(out, "TOTAL");
log.debug("Total free in indexed lists " SIZE_FORMAT " words", total_free);
log.debug("growth: %8.5f deficit: %8.5f",
log.print("Total free in indexed lists " SIZE_FORMAT " words", total_free);
log.print("growth: %8.5f deficit: %8.5f",
(double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/
(total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0),
(double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));

@ -93,6 +93,7 @@ class TestLogSavedConfig {
Log(logging) _log;
public:
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());
bool success = LogConfiguration::parse_log_arguments("stdout", "all=off", NULL, NULL, _log.error_stream());
assert(success, "test unable to turn all off");
@ -105,6 +106,7 @@ class TestLogSavedConfig {
}
~TestLogSavedConfig() {
ResourceMark rm;
if (_new_output) {
bool success = LogConfiguration::parse_log_arguments(_new_output, "all=off", NULL, NULL, _log.error_stream());
assert(success, "test unable to turn all off");
@ -154,7 +156,7 @@ void Test_logconfiguration_subscribe() {
ResourceMark rm;
Log(logging) log;
TestLogSavedConfig log_cfg("stdout", "logging+test=trace");
TestLogSavedConfig log_cfg("stdout", "logging*=trace");
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

@ -106,6 +106,24 @@ class LogWriteHelper : AllStatic {
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,
LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>
class LogImpl VALUE_OBJ_CLASS_SPEC {
@ -184,4 +202,30 @@ class LogImpl VALUE_OBJ_CLASS_SPEC {
#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

@ -67,6 +67,7 @@ void InternalVMTests::run() {
run_unit_test(Test_linked_list);
run_unit_test(TestChunkedList_test);
run_unit_test(JSON_test);
run_unit_test(Test_logtarget);
run_unit_test(Test_configure_stdout);
run_unit_test(Test_logconfiguration_subscribe);
run_unit_test(Test_log_prefix);