Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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() {
Atomic::release_store(&_output_level_configured_by_user, true);
}

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

bool is_output_level_configured_by_user() const {
return Atomic::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