8341622: Tag-specific disabled default decorators for UnifiedLogging
Reviewed-by: jsjolen, rcastanedalo, aboldtch
This commit is contained in:
parent
1ea1f33f66
commit
9bdface147
@ -491,7 +491,7 @@ bool LogConfiguration::parse_log_arguments(const char* outputstr,
|
||||
return false;
|
||||
}
|
||||
|
||||
LogDecorators decorators;
|
||||
LogDecorators decorators = selections.get_default_decorators();
|
||||
if (!decorators.parse(decoratorstr, errstream)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,8 @@
|
||||
#include "logging/logDecorators.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
|
||||
const LogLevelType AnyLevel = LogLevelType::NotMentioned;
|
||||
|
||||
template <LogDecorators::Decorator d>
|
||||
struct AllBitmask {
|
||||
// Use recursive template deduction to calculate the bitmask of all decorations.
|
||||
@ -45,6 +47,19 @@ const char* LogDecorators::_name[][2] = {
|
||||
#undef DECORATOR
|
||||
};
|
||||
|
||||
#define UNDECORATED_DEFAULTS \
|
||||
UNDECORATED_DEFAULT(AnyLevel, LOG_TAGS(jit, inlining))
|
||||
|
||||
const LogDecorators::DefaultUndecoratedSelection LogDecorators::default_decorators[] = {
|
||||
#define UNDECORATED_DEFAULT(level, ...) LogDecorators::DefaultUndecoratedSelection::make<level, __VA_ARGS__>(),
|
||||
UNDECORATED_DEFAULTS
|
||||
#undef UNDECORATED_DEFAULT
|
||||
};
|
||||
|
||||
#undef UNDERCORATED_DEFAULTS
|
||||
|
||||
const size_t LogDecorators::number_of_default_decorators = ARRAY_SIZE(default_decorators);
|
||||
|
||||
LogDecorators::Decorator LogDecorators::from_string(const char* str) {
|
||||
for (size_t i = 0; i < Count; i++) {
|
||||
Decorator d = static_cast<Decorator>(i);
|
||||
@ -57,7 +72,7 @@ LogDecorators::Decorator LogDecorators::from_string(const char* str) {
|
||||
|
||||
bool LogDecorators::parse(const char* decorator_args, outputStream* errstream) {
|
||||
if (decorator_args == nullptr || strlen(decorator_args) == 0) {
|
||||
_decorators = DefaultDecoratorsMask;
|
||||
// No decorators supplied, keep default decorators
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -93,3 +108,16 @@ bool LogDecorators::parse(const char* decorator_args, outputStream* errstream) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LogDecorators::has_disabled_default_decorators(const LogSelection& selection, const DefaultUndecoratedSelection* defaults, size_t defaults_count) {
|
||||
for (size_t i = 0; i < defaults_count; ++i) {
|
||||
DefaultUndecoratedSelection current_default = defaults[i];
|
||||
const bool ignore_level = current_default.selection().level() == AnyLevel;
|
||||
const bool level_matches = ignore_level || selection.level() == current_default.selection().level();
|
||||
if (!level_matches) continue;
|
||||
if (selection.superset_of(current_default.selection())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@
|
||||
#define SHARE_LOGGING_LOGDECORATORS_HPP
|
||||
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "logging/logSelection.hpp"
|
||||
|
||||
class outputStream;
|
||||
|
||||
@ -59,6 +60,7 @@ class outputStream;
|
||||
// declared above. For example, logging with 'uptime, level, tags' decorators results in:
|
||||
// [0,943s][info ][logging] message.
|
||||
class LogDecorators {
|
||||
friend class TestLogDecorators;
|
||||
public:
|
||||
enum Decorator {
|
||||
#define DECORATOR(name, abbr) name##_decorator,
|
||||
@ -68,24 +70,48 @@ class LogDecorators {
|
||||
Invalid
|
||||
};
|
||||
|
||||
class DefaultUndecoratedSelection {
|
||||
friend class TestLogDecorators;
|
||||
LogSelection _selection;
|
||||
|
||||
DefaultUndecoratedSelection() : _selection(LogSelection::Invalid) {}
|
||||
|
||||
DefaultUndecoratedSelection(LogLevelType level, LogTagType t0, LogTagType t1, LogTagType t2,
|
||||
LogTagType t3, LogTagType t4) : _selection(LogSelection::Invalid) {
|
||||
LogTagType tag_arr[LogTag::MaxTags] = { t0, t1, t2, t3, t4 };
|
||||
_selection = LogSelection(tag_arr, false, level);
|
||||
}
|
||||
|
||||
public:
|
||||
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>
|
||||
static DefaultUndecoratedSelection make() {
|
||||
STATIC_ASSERT(GuardTag == LogTag::__NO_TAG);
|
||||
return DefaultUndecoratedSelection(Level, T0, T1, T2, T3, T4);
|
||||
}
|
||||
|
||||
const LogSelection& selection() const { return _selection; }
|
||||
};
|
||||
|
||||
private:
|
||||
uint _decorators;
|
||||
static const char* _name[][2];
|
||||
static const uint DefaultDecoratorsMask = (1 << uptime_decorator) | (1 << level_decorator) | (1 << tags_decorator);
|
||||
static const uint defaultsMask = (1 << uptime_decorator) | (1 << level_decorator) | (1 << tags_decorator);
|
||||
static const LogDecorators::DefaultUndecoratedSelection default_decorators[];
|
||||
static const size_t number_of_default_decorators;
|
||||
|
||||
static uint mask(LogDecorators::Decorator decorator) {
|
||||
return 1 << decorator;
|
||||
}
|
||||
|
||||
constexpr LogDecorators(uint mask) : _decorators(mask) {
|
||||
}
|
||||
|
||||
public:
|
||||
static const LogDecorators None;
|
||||
static const LogDecorators All;
|
||||
|
||||
LogDecorators() : _decorators(DefaultDecoratorsMask) {
|
||||
}
|
||||
constexpr LogDecorators(uint mask) : _decorators(mask) {}
|
||||
|
||||
LogDecorators() : _decorators(defaultsMask) {}
|
||||
|
||||
void clear() {
|
||||
_decorators = 0;
|
||||
@ -99,6 +125,20 @@ class LogDecorators {
|
||||
return _name[decorator][1];
|
||||
}
|
||||
|
||||
template<typename... Decorators>
|
||||
static uint mask_from_decorators(LogDecorators::Decorator first, Decorators... rest) {
|
||||
uint bitmask = 0;
|
||||
LogDecorators::Decorator decorators[1 + sizeof...(rest)] = { first, rest... };
|
||||
for (const LogDecorators::Decorator decorator : decorators) {
|
||||
bitmask |= mask(decorator);
|
||||
}
|
||||
return bitmask;
|
||||
}
|
||||
|
||||
// Check if we have some default decorators for a given LogSelection. If that is the case,
|
||||
// the output parameter mask will contain the defaults-specified decorators mask
|
||||
static bool has_disabled_default_decorators(const LogSelection& selection, const DefaultUndecoratedSelection* defaults = default_decorators, size_t defaults_count = number_of_default_decorators);
|
||||
|
||||
static LogDecorators::Decorator from_string(const char* str);
|
||||
|
||||
void combine_with(const LogDecorators &source) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -69,6 +69,23 @@ bool LogSelection::operator!=(const LogSelection& ref) const {
|
||||
return !operator==(ref);
|
||||
}
|
||||
|
||||
bool LogSelection::superset_of(const LogSelection& other) const {
|
||||
bool match;
|
||||
for (size_t i = 0; i < other.ntags(); ++i) {
|
||||
match = false;
|
||||
for (size_t j = 0; j < _ntags; ++j) {
|
||||
if (other._tags[i] == _tags[j]) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static LogSelection parse_internal(char *str, outputStream* errstream) {
|
||||
// Parse the level, if specified
|
||||
LogLevelType level = LogLevel::Unspecified;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,6 +54,8 @@ class LogSelection : public StackObj {
|
||||
bool operator==(const LogSelection& ref) const;
|
||||
bool operator!=(const LogSelection& ref) const;
|
||||
|
||||
bool superset_of(const LogSelection& ref) const;
|
||||
|
||||
size_t ntags() const;
|
||||
LogLevelType level() const;
|
||||
size_t tag_sets_selected() const;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -53,6 +53,14 @@ bool LogSelectionList::verify_selections(outputStream* out) const {
|
||||
return valid;
|
||||
}
|
||||
|
||||
LogDecorators LogSelectionList::get_default_decorators() const {
|
||||
for (size_t i = 0; i < _nselections; ++i) {
|
||||
if (!LogDecorators::has_disabled_default_decorators(_selections[i])) {
|
||||
return LogDecorators();
|
||||
}
|
||||
}
|
||||
return LogDecorators::None;
|
||||
}
|
||||
|
||||
bool LogSelectionList::parse(const char* str, outputStream* errstream) {
|
||||
bool success = true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -60,6 +60,8 @@ class LogSelectionList : public StackObj {
|
||||
// Returns false if some invalid selection was found. If given an outputstream,
|
||||
// this function will list all the invalid selections on the stream.
|
||||
bool verify_selections(outputStream* out = nullptr) const;
|
||||
|
||||
LogDecorators get_default_decorators() const;
|
||||
};
|
||||
|
||||
#endif // SHARE_LOGGING_LOGSELECTIONLIST_HPP
|
||||
|
104
test/hotspot/gtest/logging/test_logDefaultDecorators.cpp
Normal file
104
test/hotspot/gtest/logging/test_logDefaultDecorators.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "jvm.h"
|
||||
#include "logging/logDecorators.hpp"
|
||||
#include "logging/logTag.hpp"
|
||||
#include "unittest.hpp"
|
||||
|
||||
|
||||
class TestLogDecorators : public testing::Test {
|
||||
using LD = LogDecorators;
|
||||
|
||||
static const size_t defaults_cnt = 3;
|
||||
LD::DefaultUndecoratedSelection defaults[defaults_cnt] = {
|
||||
LD::DefaultUndecoratedSelection::make<LogLevelType::Trace, LOG_TAGS(gc)>(),
|
||||
LD::DefaultUndecoratedSelection::make<LogLevelType::Trace, LOG_TAGS(jit)>(),
|
||||
LD::DefaultUndecoratedSelection::make<LogLevelType::NotMentioned, LOG_TAGS(ref)>(),
|
||||
};
|
||||
|
||||
public:
|
||||
void test_default_decorators() {
|
||||
LogTagType tags[LogTag::MaxTags] = { LogTag::__NO_TAG, LogTag::__NO_TAG, LogTag::__NO_TAG, LogTag::__NO_TAG, LogTag::__NO_TAG };
|
||||
bool result;
|
||||
|
||||
// If a -Xlog selection matches one of the undecorated defaults, the default decorators will be disabled
|
||||
tags[0] = LogTagType::_jit;
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, false, LogLevelType::Trace), defaults, defaults_cnt);
|
||||
EXPECT_TRUE(result);
|
||||
|
||||
|
||||
// If a -Xlog selection contains one of the undecorated defaults, the default decorators will be disabled
|
||||
tags[0] = LogTagType::_jit;
|
||||
tags[1] = LogTagType::_inlining;
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, false, LogLevelType::Trace), defaults, defaults_cnt);
|
||||
EXPECT_TRUE(result);
|
||||
|
||||
|
||||
// Wildcards are ignored
|
||||
tags[0] = LogTag::_compilation;
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, true, LogLevelType::Debug), defaults, defaults_cnt);
|
||||
EXPECT_FALSE(result);
|
||||
|
||||
|
||||
// If there is no level match, default decorators are kept
|
||||
tags[0] = LogTagType::_gc;
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, false, LogLevelType::Info), defaults, defaults_cnt);
|
||||
EXPECT_FALSE(result);
|
||||
|
||||
|
||||
// If NotMentioned is specified, it will match every level and so default decorators will never be added if there is a positive tagset match
|
||||
tags[0] = LogTagType::_ref;
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, false, LogLevelType::Error), defaults, defaults_cnt);
|
||||
EXPECT_TRUE(result);
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, false, LogLevelType::Warning), defaults, defaults_cnt);
|
||||
EXPECT_TRUE(result);
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, false, LogLevelType::Info), defaults, defaults_cnt);
|
||||
EXPECT_TRUE(result);
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, false, LogLevelType::Debug), defaults, defaults_cnt);
|
||||
EXPECT_TRUE(result);
|
||||
result = LD::has_disabled_default_decorators(LogSelection(tags, false, LogLevelType::Trace), defaults, defaults_cnt);
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
void test_mask_from_decorators() {
|
||||
// Single tags should yield 2^{decorator_value_in_enum}
|
||||
EXPECT_EQ(LD::mask_from_decorators(LD::time_decorator), (uint)(1 << LD::time_decorator));
|
||||
EXPECT_EQ(LD::mask_from_decorators(LD::pid_decorator), (uint)(1 << LD::pid_decorator));
|
||||
EXPECT_EQ(LD::mask_from_decorators(LD::tid_decorator), (uint)(1 << LD::tid_decorator));
|
||||
EXPECT_EQ(LD::mask_from_decorators(LD::tags_decorator), (uint)(1 << LD::tags_decorator));
|
||||
|
||||
// Combinations of decorators should fill the mask accordingly to their bitmask positions
|
||||
uint mask = (1 << LD::time_decorator) | (1 << LD::uptimemillis_decorator) | (1 << LD::tid_decorator);
|
||||
EXPECT_EQ(LD::mask_from_decorators(LD::time_decorator, LD::uptimemillis_decorator, LD::tid_decorator), mask);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_VM_F(TestLogDecorators, MaskFromDecorators) {
|
||||
test_mask_from_decorators();
|
||||
}
|
||||
|
||||
TEST_VM_F(TestLogDecorators, HasDefaultDecorators) {
|
||||
test_default_decorators();
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @requires vm.flagless
|
||||
* @summary Running -Xlog with tags which have disabled default decorators should not yield decorated logs
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
* @run driver DefaultLogDecoratorsTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DefaultLogDecoratorsTest {
|
||||
private static Pattern DECORATED_LINE = Pattern.compile("(\\[.+\\])+ .*");
|
||||
|
||||
private static void doTest(boolean shouldHave, String... xlog) throws Exception {
|
||||
List<String> argsList = new ArrayList(Arrays.asList(xlog));
|
||||
argsList.add(InnerClass.class.getName());
|
||||
String[] args = argsList.toArray(new String[0]);
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args);
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(0);
|
||||
List<String> allLines = Files.readAllLines(Path.of("decorators.log"));
|
||||
for (String line : allLines) {
|
||||
if (DECORATED_LINE.matcher(line).find() == !shouldHave) {
|
||||
throw new RuntimeException("Logging should " + (shouldHave ? "" : "not ") + "contain decorators!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// JIT inlining logging, as per defaults, shall have all decorators disabled
|
||||
doTest(false, "-Xlog:jit+inlining*=trace:decorators.log");
|
||||
|
||||
// If decorators are specified, the defaults are not taken into account
|
||||
doTest(true, "-Xlog:jit+inlining*=trace:decorators.log:time");
|
||||
|
||||
// Even if decorators are only supplied for another tag(s), the defaults are not taken into account
|
||||
doTest(true, "-Xlog:jit+inlining*=trace:decorators.log", "-Xlog:gc*=info:decorators.log:time");
|
||||
|
||||
// Defaults are not taken into account also when another tag implicitly imposes the "standard" defaults
|
||||
doTest(true, "-Xlog:jit+inlining*=trace:decorators.log", "-Xlog:gc*=info:decorators.log");
|
||||
|
||||
// Other logging shall not be affected by a tag with defaults
|
||||
doTest(true, "-Xlog:gc*=trace:decorators.log");
|
||||
}
|
||||
|
||||
public static class InnerClass {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("DefaultLogDecorators test");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user