Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/hotspot/share/jfr/dcmd/jfrDcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,13 @@ static void handle_dcmd_result(outputStream* output,
assert(!HAS_PENDING_EXCEPTION, "invariant");

if (startup) {
if (log_is_enabled(Warning, jfr, startup)) {
// if warning is set, assume user hasn't configured log level
if (log_is_default(jfr, startup)) {
// The user hasn't configured a log level
// Log to Info and reset to Warning. This way user can disable
// default output by setting -Xlog:jfr+startup=error/off
// default output by setting -Xlog:jfr+startup=error/warning/off
LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(jfr, startup));
log(result, THREAD);
LogConfiguration::configure_stdout(LogLevel::Warning, true, LOG_TAGS(jfr, startup));
LogConfiguration::reset_stdout(true, LOG_TAGS(jfr, startup));
} else {
log(result, THREAD);
}
Expand Down
5 changes: 5 additions & 0 deletions src/hotspot/share/logging/log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class LogMessageBuffer;

// Convenience macro to test if the logging is enabled on the specified level for given tags.
#define log_is_enabled(level, ...) (LogImpl<LOG_TAGS(__VA_ARGS__)>::is_level(LogLevel::level))
#define log_is_default(...) (!LogImpl<LOG_TAGS(__VA_ARGS__)>::is_output_level_configured_by_user())

//
// Log class for more advanced logging scenarios.
Expand Down Expand Up @@ -122,6 +123,10 @@ class LogImpl {
return LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().is_level(level);
}

static bool is_output_level_configured_by_user() {
return LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().is_output_level_configured_by_user();
}

ATTRIBUTE_PRINTF(2, 3)
static void write(LogLevelType level, const char* fmt, ...) {
va_list args;
Expand Down
26 changes: 22 additions & 4 deletions src/hotspot/share/logging/logConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "logging/logDecorators.hpp"
#include "logging/logDiagnosticCommand.hpp"
#include "logging/logFileOutput.hpp"
#include "logging/logLevel.hpp"
#include "logging/logOutput.hpp"
#include "logging/logSelectionList.hpp"
#include "logging/logStream.hpp"
Expand Down Expand Up @@ -237,7 +238,7 @@ void LogConfiguration::delete_output(size_t idx) {
// is a subset of relevant tagsets decorators. After updating output's decorators, it is still safe to shrink all
// decorators of tagsets.
//
void LogConfiguration::configure_output(size_t idx, const LogSelectionList& selections, const LogDecorators& decorators) {
void LogConfiguration::configure_output(size_t idx, const LogSelectionList& selections, const LogDecorators& decorators, bool is_user_provided) {
assert(ConfigurationLock::current_thread_has_lock(), "Must hold configuration lock to call this function.");
assert(idx < _n_outputs, "Invalid index, idx = %zu and _n_outputs = %zu", idx, _n_outputs);
LogOutput* output = _outputs[idx];
Expand Down Expand Up @@ -265,6 +266,11 @@ void LogConfiguration::configure_output(size_t idx, const LogSelectionList& sele
// Set the new level, if it changed
if (level != LogLevel::NotMentioned) {
ts->set_output_level(output, level);
if (is_user_provided) {
ts->set_output_level_configured_by_user();
} else {
ts->set_output_level_not_configured_by_user();
}
} else {
// Look up the previously set level for this output on this tagset
level = ts->level_for(output);
Expand Down Expand Up @@ -365,7 +371,7 @@ void LogConfiguration::disable_tags(int exact_match, ...) {
// Apply configuration to all outputs, with the same decorators as before.
ConfigurationLock cl;
for (size_t i = 0; i < _n_outputs; i++) {
configure_output(i, list, _outputs[i]->decorators());
configure_output(i, list, _outputs[i]->decorators(), true);
}
notify_update_listeners();
}
Expand All @@ -378,7 +384,19 @@ void LogConfiguration::configure_stdout(LogLevelType level, int exact_match, ...

// Apply configuration to stdout (output #0), with the same decorators as before.
ConfigurationLock cl;
configure_output(0, list, _outputs[0]->decorators());
configure_output(0, list, _outputs[0]->decorators(), true);
notify_update_listeners();
}

void LogConfiguration::reset_stdout(int exact_match, ...) {
va_list ap;
va_start(ap, exact_match);
LogSelectionList list = create_selection_list(LogLevel::Off, exact_match, ap);
va_end(ap);

// Apply configuration to stdout (output #0), with the same decorators as before.
ConfigurationLock cl;
configure_output(0, list, _outputs[0]->decorators(), false);
notify_update_listeners();
}

Expand Down Expand Up @@ -554,7 +572,7 @@ bool LogConfiguration::parse_log_arguments(const char* outputstr,
if (!added && output_options != nullptr && strlen(output_options) > 0) {
errstream->print_cr("Output options for existing outputs are ignored.");
}
configure_output(idx, selections, decorators);
configure_output(idx, selections, decorators, true);
notify_update_listeners();
selections.verify_selections(errstream);
return true;
Expand Down
5 changes: 4 additions & 1 deletion src/hotspot/share/logging/logConfiguration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class LogConfiguration : public AllStatic {
static size_t find_output(const char* name);

// Configure output (add or update existing configuration) to log on tag-level combination using specified decorators.
static void configure_output(size_t idx, const LogSelectionList& tag_level_expression, const LogDecorators& decorators);
static void configure_output(size_t idx, const LogSelectionList& tag_level_expression, const LogDecorators& decorators, bool is_user_provided);

// This should be called after any configuration change while still holding ConfigurationLock
static void notify_update_listeners();
Expand Down Expand Up @@ -126,6 +126,9 @@ class LogConfiguration : public AllStatic {
// LogConfiguration::configure_stdout(LogLevel::<level>, <true/false>, LOG_TAGS(<tags>));
static void configure_stdout(LogLevelType level, int exact_match, ...);

// Configures logging on stdout for the given tags to be the default level, not specified by users
static void reset_stdout(int exact_match, ...);

// Parse command line configuration. Parameter 'opts' is the string immediately following the -Xlog: argument ("gc" for -Xlog:gc).
static bool parse_command_line_arguments(const char* opts = "all");

Expand Down
15 changes: 14 additions & 1 deletion src/hotspot/share/logging/logOutputList.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class LogOutputList {
};

LogOutputNode* volatile _level_start[LogLevel::Count];
volatile bool _output_level_configured_by_user;
volatile jint _active_readers;

LogOutputNode* find(const LogOutput* output) const;
Expand All @@ -66,7 +67,7 @@ class LogOutputList {
jint decrease_readers();

public:
LogOutputList() : _active_readers(0) {
LogOutputList() : _output_level_configured_by_user(false), _active_readers(0) {
for (size_t i = 0; i < LogLevel::Count; i++) {
_level_start[i] = nullptr;
}
Expand All @@ -88,6 +89,18 @@ class LogOutputList {
// Set (add/update/remove) the output to the specified level.
void set_output_level(LogOutput* output, LogLevelType level);

void set_output_level_configured_by_user() {
AtomicAccess::release_store(&_output_level_configured_by_user, true);
}

void set_output_level_not_configured_by_user() {
AtomicAccess::release_store(&_output_level_configured_by_user, false);
}

bool is_output_level_configured_by_user() const {
return AtomicAccess::load_acquire(&_output_level_configured_by_user);
}

// Removes all outputs. Equivalent of set_output_level(out, Off)
// for all outputs.
void clear();
Expand Down
12 changes: 12 additions & 0 deletions src/hotspot/share/logging/logTagSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ class LogTagSet {
_output_list.set_output_level(output, level);
}

void set_output_level_configured_by_user() {
_output_list.set_output_level_configured_by_user();
}

void set_output_level_not_configured_by_user() {
_output_list.set_output_level_not_configured_by_user();
}

bool is_output_level_configured_by_user() const {
return _output_list.is_output_level_configured_by_user();
}

// Refresh the decorators for this tagset to contain the decorators for all
// of its current outputs combined with the given decorators.
void update_decorators(const LogDecorators& decorator = LogDecorators::None);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ private static void launchBinary(String options1, String options2) throws Except
String recording1 = START_FLIGHT_RECORDING + (options1 != null ? options1 : "");
String recording2 = START_FLIGHT_RECORDING + (options2 != null ? options2 : "");
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(recording1, recording2, MainClass.class.getName());
System.err.println("Out: " + pb.command());
test(pb, "Started recording 1", "Started recording 2");
}

Expand Down
6 changes: 4 additions & 2 deletions test/jdk/jdk/jfr/startupargs/TestStartupMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ public static void main(String[] args) throws Exception {
.shouldNotContain("Started recording")
.shouldNotContain("Use jcmd");

// Known limitation.
// Can't turn off log with -Xlog:jfr+startup=warning
startJfrJvm("-Xlog:jfr+startup=warning")
.shouldNotContain("[jfr,startup")
.shouldNotContain("Started recording")
.shouldNotContain("Use jcmd");

startJfrJvm()
.shouldContain("[info][jfr,startup")
Expand Down