annotate src/share/vm/logging/logConfiguration.cpp @ 10939:8005261869c9

8151526: Print -Xlog configuration in the hs_err_pid file Summary: logging configuration is now printed in hs_err and in vm info. Reviewed-by: coleenp, mlarsson, dholmes
author mockner
date Tue, 19 Apr 2016 11:03:37 -0400
parents 5bc83f454d50
children d525d1232cdc
rev   line source
mlarsson@9046 1 /*
mlarsson@10271 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
mlarsson@9046 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mlarsson@9046 4 *
mlarsson@9046 5 * This code is free software; you can redistribute it and/or modify it
mlarsson@9046 6 * under the terms of the GNU General Public License version 2 only, as
mlarsson@9046 7 * published by the Free Software Foundation.
mlarsson@9046 8 *
mlarsson@9046 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mlarsson@9046 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mlarsson@9046 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mlarsson@9046 12 * version 2 for more details (a copy is included in the LICENSE file that
mlarsson@9046 13 * accompanied this code).
mlarsson@9046 14 *
mlarsson@9046 15 * You should have received a copy of the GNU General Public License version
mlarsson@9046 16 * 2 along with this work; if not, write to the Free Software Foundation,
mlarsson@9046 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mlarsson@9046 18 *
mlarsson@9046 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mlarsson@9046 20 * or visit www.oracle.com if you need additional information or have any
mlarsson@9046 21 * questions.
mlarsson@9046 22 *
mlarsson@9046 23 */
mlarsson@9046 24 #include "precompiled.hpp"
mlarsson@9046 25 #include "logging/log.hpp"
mlarsson@9046 26 #include "logging/logConfiguration.hpp"
mlarsson@9046 27 #include "logging/logDecorations.hpp"
mlarsson@9046 28 #include "logging/logDecorators.hpp"
mlarsson@9046 29 #include "logging/logDiagnosticCommand.hpp"
mlarsson@9046 30 #include "logging/logFileOutput.hpp"
mlarsson@9046 31 #include "logging/logOutput.hpp"
mlarsson@9046 32 #include "logging/logTagLevelExpression.hpp"
mlarsson@9046 33 #include "logging/logTagSet.hpp"
mlarsson@9046 34 #include "memory/allocation.inline.hpp"
mlarsson@9046 35 #include "memory/resourceArea.hpp"
mlarsson@9046 36 #include "runtime/os.inline.hpp"
mlarsson@9893 37 #include "runtime/semaphore.hpp"
mlarsson@9046 38 #include "utilities/globalDefinitions.hpp"
mlarsson@9046 39
mlarsson@9046 40 LogOutput** LogConfiguration::_outputs = NULL;
mlarsson@9046 41 size_t LogConfiguration::_n_outputs = 0;
mlarsson@9046 42
rehn@10621 43 LogConfiguration::UpdateListenerFunction* LogConfiguration::_listener_callbacks = NULL;
rehn@10621 44 size_t LogConfiguration::_n_listener_callbacks = 0;
rehn@10621 45
mlarsson@9893 46 // Stack object to take the lock for configuring the logging.
mlarsson@9893 47 // Should only be held during the critical parts of the configuration
mlarsson@9893 48 // (when calling configure_output or reading/modifying the outputs array).
mlarsson@9893 49 // Thread must never block when holding this lock.
mlarsson@9893 50 class ConfigurationLock : public StackObj {
mlarsson@9893 51 private:
mlarsson@9893 52 // Semaphore used as lock
mlarsson@9893 53 static Semaphore _semaphore;
mlarsson@9893 54 debug_only(static intx _locking_thread_id;)
mlarsson@9893 55 public:
mlarsson@9893 56 ConfigurationLock() {
mlarsson@9893 57 _semaphore.wait();
mlarsson@9893 58 debug_only(_locking_thread_id = os::current_thread_id());
mlarsson@9893 59 }
mlarsson@9893 60 ~ConfigurationLock() {
mlarsson@9893 61 debug_only(_locking_thread_id = -1);
mlarsson@9893 62 _semaphore.signal();
mlarsson@9893 63 }
mlarsson@9893 64 debug_only(static bool current_thread_has_lock();)
mlarsson@9893 65 };
mlarsson@9893 66
mlarsson@9893 67 Semaphore ConfigurationLock::_semaphore(1);
mlarsson@9893 68 #ifdef ASSERT
mlarsson@9893 69 intx ConfigurationLock::_locking_thread_id = -1;
mlarsson@9893 70 bool ConfigurationLock::current_thread_has_lock() {
mlarsson@9893 71 return _locking_thread_id == os::current_thread_id();
mlarsson@9893 72 }
mlarsson@9893 73 #endif
mlarsson@9893 74
mlarsson@9046 75 void LogConfiguration::post_initialize() {
mlarsson@9046 76 LogDiagnosticCommand::registerCommand();
stefank@10755 77 Log(logging) log;
mlarsson@9046 78 log.info("Log configuration fully initialized.");
mlarsson@9514 79 log_develop_info(logging)("Develop logging is available.");
mlarsson@9046 80 if (log.is_trace()) {
mlarsson@9046 81 ResourceMark rm;
mlarsson@9046 82 describe(log.trace_stream());
mlarsson@9046 83 }
mlarsson@9046 84 }
mlarsson@9046 85
mlarsson@9046 86 void LogConfiguration::initialize(jlong vm_start_time) {
mlarsson@9046 87 LogFileOutput::set_file_name_parameters(vm_start_time);
mlarsson@10271 88 LogDecorations::initialize(vm_start_time);
mlarsson@9046 89 assert(_outputs == NULL, "Should not initialize _outputs before this function, initialize called twice?");
mlarsson@9046 90 _outputs = NEW_C_HEAP_ARRAY(LogOutput*, 2, mtLogging);
mlarsson@9046 91 _outputs[0] = LogOutput::Stdout;
mlarsson@9046 92 _outputs[1] = LogOutput::Stderr;
mlarsson@9046 93 _n_outputs = 2;
mlarsson@9046 94 }
mlarsson@9046 95
mlarsson@9046 96 void LogConfiguration::finalize() {
mlarsson@9046 97 for (size_t i = 2; i < _n_outputs; i++) {
mlarsson@9046 98 delete _outputs[i];
mlarsson@9046 99 }
mlarsson@9046 100 FREE_C_HEAP_ARRAY(LogOutput*, _outputs);
mlarsson@9046 101 }
mlarsson@9046 102
mlarsson@9046 103 size_t LogConfiguration::find_output(const char* name) {
mlarsson@9046 104 for (size_t i = 0; i < _n_outputs; i++) {
mlarsson@9046 105 if (strcmp(_outputs[i]->name(), name) == 0) {
mlarsson@9046 106 return i;
mlarsson@9046 107 }
mlarsson@9046 108 }
mlarsson@9046 109 return SIZE_MAX;
mlarsson@9046 110 }
mlarsson@9046 111
mlarsson@9894 112 LogOutput* LogConfiguration::new_output(char* name, const char* options, outputStream* errstream) {
mlarsson@9046 113 const char* type;
mlarsson@9046 114 char* equals_pos = strchr(name, '=');
mlarsson@9046 115 if (equals_pos == NULL) {
mlarsson@9046 116 type = "file";
mlarsson@9046 117 } else {
mlarsson@9046 118 *equals_pos = '\0';
mlarsson@9046 119 type = name;
mlarsson@9046 120 name = equals_pos + 1;
mlarsson@9046 121 }
mlarsson@9046 122
mlarsson@9894 123 // Check if name is quoted, and if so, strip the quotes
mlarsson@9894 124 char* quote = strchr(name, '"');
mlarsson@9894 125 if (quote != NULL) {
mlarsson@9894 126 char* end_quote = strchr(name + 1, '"');
mlarsson@9894 127 if (end_quote == NULL) {
mlarsson@9894 128 errstream->print_cr("Output name has opening quote but is missing a terminating quote.");
mlarsson@9894 129 return NULL;
mlarsson@9894 130 } else if (quote != name || end_quote[1] != '\0') {
mlarsson@9894 131 errstream->print_cr("Output name can not be partially quoted."
mlarsson@9894 132 " Either surround the whole name with quotation marks,"
mlarsson@9894 133 " or do not use quotation marks at all.");
mlarsson@9894 134 return NULL;
mlarsson@9894 135 }
mlarsson@9894 136 name++;
mlarsson@9894 137 *end_quote = '\0';
mlarsson@9894 138 }
mlarsson@9894 139
mlarsson@9046 140 LogOutput* output;
mlarsson@9046 141 if (strcmp(type, "file") == 0) {
mlarsson@9046 142 output = new LogFileOutput(name);
mlarsson@9046 143 } else {
mlarsson@9894 144 errstream->print_cr("Unsupported log output type.");
mlarsson@9046 145 return NULL;
mlarsson@9046 146 }
mlarsson@9046 147
mlarsson@10869 148 bool success = output->initialize(options, errstream);
mlarsson@9046 149 if (!success) {
mlarsson@9894 150 errstream->print_cr("Initialization of output '%s' using options '%s' failed.", name, options);
mlarsson@9046 151 delete output;
mlarsson@9046 152 return NULL;
mlarsson@9046 153 }
mlarsson@9046 154 return output;
mlarsson@9046 155 }
mlarsson@9046 156
mlarsson@9046 157 size_t LogConfiguration::add_output(LogOutput* output) {
mlarsson@9046 158 size_t idx = _n_outputs++;
mlarsson@9046 159 _outputs = REALLOC_C_HEAP_ARRAY(LogOutput*, _outputs, _n_outputs, mtLogging);
mlarsson@9046 160 _outputs[idx] = output;
mlarsson@9046 161 return idx;
mlarsson@9046 162 }
mlarsson@9046 163
mlarsson@9046 164 void LogConfiguration::delete_output(size_t idx) {
mlarsson@9046 165 assert(idx > 1 && idx < _n_outputs,
david@9054 166 "idx must be in range 1 < idx < _n_outputs, but idx = " SIZE_FORMAT
david@9054 167 " and _n_outputs = " SIZE_FORMAT, idx, _n_outputs);
mlarsson@9046 168 LogOutput* output = _outputs[idx];
mlarsson@9046 169 // Swap places with the last output and shrink the array
mlarsson@9046 170 _outputs[idx] = _outputs[--_n_outputs];
mlarsson@9046 171 _outputs = REALLOC_C_HEAP_ARRAY(LogOutput*, _outputs, _n_outputs, mtLogging);
mlarsson@9046 172 delete output;
mlarsson@9046 173 }
mlarsson@9046 174
mlarsson@9046 175 void LogConfiguration::configure_output(size_t idx, const LogTagLevelExpression& tag_level_expression, const LogDecorators& decorators) {
mlarsson@9893 176 assert(ConfigurationLock::current_thread_has_lock(), "Must hold configuration lock to call this function.");
david@9054 177 assert(idx < _n_outputs, "Invalid index, idx = " SIZE_FORMAT " and _n_outputs = " SIZE_FORMAT, idx, _n_outputs);
mlarsson@9046 178 LogOutput* output = _outputs[idx];
mlarsson@9578 179
mlarsson@9578 180 // Clear the previous config description
mlarsson@9578 181 output->clear_config_string();
mlarsson@9578 182
mlarsson@9046 183 bool enabled = false;
mlarsson@9046 184 for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
mlarsson@9046 185 LogLevelType level = tag_level_expression.level_for(*ts);
mlarsson@9578 186
mlarsson@9578 187 // Ignore tagsets that do not, and will not log on the output
mlarsson@9578 188 if (!ts->has_output(output) && (level == LogLevel::NotMentioned || level == LogLevel::Off)) {
mlarsson@9578 189 continue;
mlarsson@9578 190 }
mlarsson@9578 191
mlarsson@9578 192 // Update decorators before adding/updating output level,
mlarsson@9578 193 // so that the tagset will have the necessary decorators when requiring them.
mlarsson@9046 194 if (level != LogLevel::Off) {
mlarsson@9578 195 ts->update_decorators(decorators);
mlarsson@9578 196 }
mlarsson@9578 197
mlarsson@9578 198 // Set the new level, if it changed
mlarsson@9578 199 if (level != LogLevel::NotMentioned) {
mlarsson@9578 200 ts->set_output_level(output, level);
mlarsson@9578 201 }
mlarsson@9578 202
mlarsson@9578 203 if (level != LogLevel::Off) {
mlarsson@9578 204 // Keep track of whether or not the output is ever used by some tagset
mlarsson@9046 205 enabled = true;
mlarsson@9578 206
mlarsson@9578 207 if (level == LogLevel::NotMentioned) {
mlarsson@9578 208 // Look up the previously set level for this output on this tagset
mlarsson@9578 209 level = ts->level_for(output);
mlarsson@9578 210 }
mlarsson@9578 211
mlarsson@9578 212 // Update the config description with this tagset and level
mlarsson@9578 213 output->add_to_config_string(ts, level);
mlarsson@9046 214 }
mlarsson@9046 215 }
mlarsson@9046 216
mlarsson@9578 217 // It is now safe to set the new decorators for the actual output
mlarsson@9578 218 output->set_decorators(decorators);
mlarsson@9578 219
mlarsson@9578 220 // Update the decorators on all tagsets to get rid of unused decorators
mlarsson@9578 221 for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
mlarsson@9578 222 ts->update_decorators();
mlarsson@9578 223 }
mlarsson@9578 224
mlarsson@9578 225 if (enabled) {
mlarsson@9578 226 assert(strlen(output->config_string()) > 0,
mlarsson@9578 227 "Should always have a config description if the output is enabled.");
mlarsson@9578 228 } else if (idx > 1) {
mlarsson@9578 229 // Output is unused and should be removed.
mlarsson@9046 230 delete_output(idx);
mlarsson@9578 231 } else {
mlarsson@9578 232 // Output is either stdout or stderr, which means we can't remove it.
mlarsson@9578 233 // Update the config description to reflect that the output is disabled.
mlarsson@9578 234 output->set_config_string("all=off");
mlarsson@9046 235 }
mlarsson@9046 236 }
mlarsson@9046 237
mlarsson@9046 238 void LogConfiguration::disable_output(size_t idx) {
mlarsson@9046 239 LogOutput* out = _outputs[idx];
mlarsson@9046 240
mlarsson@9046 241 // Remove the output from all tagsets.
mlarsson@9046 242 for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
mlarsson@9046 243 ts->set_output_level(out, LogLevel::Off);
mlarsson@9578 244 ts->update_decorators();
mlarsson@9046 245 }
mlarsson@9046 246
mlarsson@9046 247 // Delete the output unless stdout/stderr
mlarsson@9046 248 if (out != LogOutput::Stderr && out != LogOutput::Stdout) {
mlarsson@9046 249 delete_output(find_output(out->name()));
mlarsson@9046 250 } else {
mlarsson@9046 251 out->set_config_string("all=off");
mlarsson@9046 252 }
mlarsson@9046 253 }
mlarsson@9046 254
mlarsson@9046 255 void LogConfiguration::disable_logging() {
mlarsson@9893 256 ConfigurationLock cl;
mlarsson@9046 257 for (size_t i = 0; i < _n_outputs; i++) {
mlarsson@9046 258 disable_output(i);
mlarsson@9046 259 }
rehn@10621 260 notify_update_listeners();
mlarsson@9046 261 }
mlarsson@9046 262
mlarsson@9578 263 void LogConfiguration::configure_stdout(LogLevelType level, bool exact_match, ...) {
mlarsson@9578 264 size_t i;
mlarsson@9578 265 va_list ap;
mlarsson@9578 266 LogTagLevelExpression expr;
mlarsson@9578 267 va_start(ap, exact_match);
mlarsson@9578 268 for (i = 0; i < LogTag::MaxTags; i++) {
mlarsson@9578 269 LogTagType tag = static_cast<LogTagType>(va_arg(ap, int));
mlarsson@9578 270 expr.add_tag(tag);
mlarsson@9578 271 if (tag == LogTag::__NO_TAG) {
mlarsson@9578 272 assert(i > 0, "Must specify at least one tag!");
mlarsson@9578 273 break;
mlarsson@9578 274 }
mlarsson@9578 275 }
mlarsson@9578 276 assert(i < LogTag::MaxTags || static_cast<LogTagType>(va_arg(ap, int)) == LogTag::__NO_TAG,
mlarsson@9578 277 "Too many tags specified! Can only have up to " SIZE_FORMAT " tags in a tag set.", LogTag::MaxTags);
mlarsson@9578 278 va_end(ap);
mlarsson@9578 279
mlarsson@9578 280 if (!exact_match) {
mlarsson@9578 281 expr.set_allow_other_tags();
mlarsson@9578 282 }
mlarsson@9578 283 expr.set_level(level);
mlarsson@9578 284 expr.new_combination();
mlarsson@9578 285
mlarsson@9578 286 // Apply configuration to stdout (output #0), with the same decorators as before.
mlarsson@9893 287 ConfigurationLock cl;
mlarsson@9578 288 configure_output(0, expr, LogOutput::Stdout->decorators());
rehn@10621 289 notify_update_listeners();
mlarsson@9578 290 }
mlarsson@9578 291
mlarsson@9046 292 bool LogConfiguration::parse_command_line_arguments(const char* opts) {
mlarsson@9046 293 char* copy = os::strdup_check_oom(opts, mtLogging);
mlarsson@9046 294
mlarsson@9046 295 // Split the option string to its colon separated components.
mlarsson@9894 296 char* str = copy;
mlarsson@9894 297 char* substrings[4] = {0};
mlarsson@9894 298 for (int i = 0 ; i < 4; i++) {
mlarsson@9894 299 substrings[i] = str;
mlarsson@9046 300
mlarsson@9894 301 // Find the next colon or quote
mlarsson@9894 302 char* next = strpbrk(str, ":\"");
mlarsson@9894 303 while (next != NULL && *next == '"') {
mlarsson@9894 304 char* end_quote = strchr(next + 1, '"');
mlarsson@9894 305 if (end_quote == NULL) {
mlarsson@9894 306 log_error(logging)("Missing terminating quote in -Xlog option '%s'", str);
mlarsson@9894 307 os::free(copy);
mlarsson@9894 308 return false;
mlarsson@9046 309 }
mlarsson@9894 310 // Keep searching after the quoted substring
mlarsson@9894 311 next = strpbrk(end_quote + 1, ":\"");
mlarsson@9894 312 }
mlarsson@9894 313
mlarsson@9894 314 if (next != NULL) {
mlarsson@9894 315 *next = '\0';
mlarsson@9894 316 str = next + 1;
mlarsson@9894 317 } else {
mlarsson@9894 318 break;
mlarsson@9046 319 }
mlarsson@9046 320 }
mlarsson@9046 321
mlarsson@9894 322 // Parse and apply the separated configuration options
mlarsson@9894 323 char* what = substrings[0];
mlarsson@9894 324 char* output = substrings[1];
mlarsson@9894 325 char* decorators = substrings[2];
mlarsson@9894 326 char* output_options = substrings[3];
mlarsson@9046 327 char errbuf[512];
mlarsson@9046 328 stringStream ss(errbuf, sizeof(errbuf));
mlarsson@9894 329 bool success = parse_log_arguments(output, what, decorators, output_options, &ss);
mlarsson@9046 330 if (!success) {
mlarsson@9046 331 errbuf[strlen(errbuf) - 1] = '\0'; // Strip trailing newline.
mlarsson@9046 332 log_error(logging)("%s", errbuf);
mlarsson@9046 333 }
mlarsson@9046 334
mlarsson@9046 335 os::free(copy);
mlarsson@9046 336 return success;
mlarsson@9046 337 }
mlarsson@9046 338
mlarsson@9046 339 bool LogConfiguration::parse_log_arguments(const char* outputstr,
mlarsson@9046 340 const char* what,
mlarsson@9046 341 const char* decoratorstr,
mlarsson@9046 342 const char* output_options,
mlarsson@9046 343 outputStream* errstream) {
mlarsson@9046 344 if (outputstr == NULL || strlen(outputstr) == 0) {
mlarsson@9046 345 outputstr = "stdout";
mlarsson@9046 346 }
mlarsson@9046 347
mlarsson@9893 348 LogTagLevelExpression expr;
mlarsson@9893 349 if (!expr.parse(what, errstream)) {
mlarsson@9893 350 return false;
mlarsson@9893 351 }
mlarsson@9893 352
mlarsson@9893 353 LogDecorators decorators;
mlarsson@9893 354 if (!decorators.parse(decoratorstr, errstream)) {
mlarsson@9893 355 return false;
mlarsson@9893 356 }
mlarsson@9893 357
mlarsson@9893 358 ConfigurationLock cl;
mlarsson@9046 359 size_t idx;
mlarsson@9046 360 if (outputstr[0] == '#') {
mlarsson@9046 361 int ret = sscanf(outputstr+1, SIZE_FORMAT, &idx);
mlarsson@9046 362 if (ret != 1 || idx >= _n_outputs) {
mlarsson@9046 363 errstream->print_cr("Invalid output index '%s'", outputstr);
mlarsson@9046 364 return false;
mlarsson@9046 365 }
mlarsson@9046 366 } else {
mlarsson@9046 367 idx = find_output(outputstr);
mlarsson@9046 368 if (idx == SIZE_MAX) {
mlarsson@9046 369 char* tmp = os::strdup_check_oom(outputstr, mtLogging);
mlarsson@9894 370 LogOutput* output = new_output(tmp, output_options, errstream);
mlarsson@9046 371 os::free(tmp);
mlarsson@9046 372 if (output == NULL) {
mlarsson@9046 373 return false;
mlarsson@9046 374 }
mlarsson@9046 375 idx = add_output(output);
mlarsson@9046 376 } else if (output_options != NULL && strlen(output_options) > 0) {
mlarsson@9046 377 errstream->print_cr("Output options for existing outputs are ignored.");
mlarsson@9046 378 }
mlarsson@9046 379 }
mlarsson@9046 380 configure_output(idx, expr, decorators);
rehn@10621 381 notify_update_listeners();
mlarsson@9046 382 return true;
mlarsson@9046 383 }
mlarsson@9046 384
mockner@10939 385 void LogConfiguration::describe_available(outputStream* out){
mlarsson@9046 386 out->print("Available log levels:");
mlarsson@9046 387 for (size_t i = 0; i < LogLevel::Count; i++) {
mlarsson@9046 388 out->print("%s %s", (i == 0 ? "" : ","), LogLevel::name(static_cast<LogLevelType>(i)));
mlarsson@9046 389 }
mlarsson@9046 390 out->cr();
mlarsson@9046 391
mlarsson@9046 392 out->print("Available log decorators:");
mlarsson@9046 393 for (size_t i = 0; i < LogDecorators::Count; i++) {
mlarsson@9046 394 LogDecorators::Decorator d = static_cast<LogDecorators::Decorator>(i);
mlarsson@9046 395 out->print("%s %s (%s)", (i == 0 ? "" : ","), LogDecorators::name(d), LogDecorators::abbreviation(d));
mlarsson@9046 396 }
mlarsson@9046 397 out->cr();
mlarsson@9046 398
mlarsson@9046 399 out->print("Available log tags:");
mlarsson@9046 400 for (size_t i = 1; i < LogTag::Count; i++) {
mlarsson@9046 401 out->print("%s %s", (i == 1 ? "" : ","), LogTag::name(static_cast<LogTagType>(i)));
mlarsson@9046 402 }
mlarsson@9046 403 out->cr();
mlarsson@9046 404
mockner@10939 405 }
mockner@10939 406
mockner@10939 407 void LogConfiguration::describe_current_configuration(outputStream* out){
mlarsson@9046 408 out->print_cr("Log output configuration:");
mlarsson@9046 409 for (size_t i = 0; i < _n_outputs; i++) {
mlarsson@9046 410 out->print("#" SIZE_FORMAT ": %s %s ", i, _outputs[i]->name(), _outputs[i]->config_string());
mlarsson@9046 411 for (size_t d = 0; d < LogDecorators::Count; d++) {
mlarsson@9046 412 LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(d);
mlarsson@9046 413 if (_outputs[i]->decorators().is_decorator(decorator)) {
mlarsson@9046 414 out->print("%s,", LogDecorators::name(decorator));
mlarsson@9046 415 }
mlarsson@9046 416 }
mlarsson@9046 417 out->cr();
mlarsson@9046 418 }
mlarsson@9046 419 }
mlarsson@9046 420
mockner@10939 421 void LogConfiguration::describe(outputStream* out) {
mockner@10939 422 describe_available(out);
mockner@10939 423 ConfigurationLock cl;
mockner@10939 424 describe_current_configuration(out);
mockner@10939 425 }
mockner@10939 426
mlarsson@9046 427 void LogConfiguration::print_command_line_help(FILE* out) {
mlarsson@9046 428 jio_fprintf(out, "-Xlog Usage: -Xlog[:[what][:[output][:[decorators][:output-options]]]]\n"
mlarsson@9046 429 "\t where 'what' is a combination of tags and levels on the form tag1[+tag2...][*][=level][,...]\n"
mlarsson@9046 430 "\t Unless wildcard (*) is specified, only log messages tagged with exactly the tags specified will be matched.\n\n");
mlarsson@9046 431
mlarsson@9046 432 jio_fprintf(out, "Available log levels:\n");
mlarsson@9046 433 for (size_t i = 0; i < LogLevel::Count; i++) {
mlarsson@9046 434 jio_fprintf(out, "%s %s", (i == 0 ? "" : ","), LogLevel::name(static_cast<LogLevelType>(i)));
mlarsson@9046 435 }
mlarsson@9046 436
mlarsson@9046 437 jio_fprintf(out, "\n\nAvailable log decorators: \n");
mlarsson@9046 438 for (size_t i = 0; i < LogDecorators::Count; i++) {
mlarsson@9046 439 LogDecorators::Decorator d = static_cast<LogDecorators::Decorator>(i);
mlarsson@9046 440 jio_fprintf(out, "%s %s (%s)", (i == 0 ? "" : ","), LogDecorators::name(d), LogDecorators::abbreviation(d));
mlarsson@9046 441 }
mlarsson@9046 442 jio_fprintf(out, "\n Decorators can also be specified as 'none' for no decoration.\n\n");
mlarsson@9046 443
mlarsson@9046 444 jio_fprintf(out, "Available log tags:\n");
mlarsson@9046 445 for (size_t i = 1; i < LogTag::Count; i++) {
mlarsson@9046 446 jio_fprintf(out, "%s %s", (i == 1 ? "" : ","), LogTag::name(static_cast<LogTagType>(i)));
mlarsson@9046 447 }
mlarsson@9046 448 jio_fprintf(out, "\n Specifying 'all' instead of a tag combination matches all tag combinations.\n\n");
mlarsson@9046 449
mlarsson@9046 450 jio_fprintf(out, "Available log outputs:\n"
mlarsson@9046 451 " stdout, stderr, file=<filename>\n"
mlarsson@9046 452 " Specifying %%p and/or %%t in the filename will expand to the JVM's PID and startup timestamp, respectively.\n\n"
mlarsson@9046 453
mlarsson@9046 454 "Some examples:\n"
mlarsson@9046 455 " -Xlog\n"
mlarsson@9046 456 "\t Log all messages using 'info' level to stdout with 'uptime', 'levels' and 'tags' decorations.\n"
mlarsson@9046 457 "\t (Equivalent to -Xlog:all=info:stdout:uptime,levels,tags).\n\n"
mlarsson@9046 458
mlarsson@9046 459 " -Xlog:gc\n"
mlarsson@9046 460 "\t Log messages tagged with 'gc' tag using 'info' level to stdout, with default decorations.\n\n"
mlarsson@9046 461
mlarsson@9046 462 " -Xlog:gc=debug:file=gc.txt:none\n"
mlarsson@9046 463 "\t Log messages tagged with 'gc' tag using 'debug' level to file 'gc.txt' with no decorations.\n\n"
mlarsson@9046 464
mlarsson@9046 465 " -Xlog:gc=trace:file=gctrace.txt:uptimemillis,pids:filecount=5,filesize=1024\n"
mlarsson@9046 466 "\t Log messages tagged with 'gc' tag using 'trace' level to a rotating fileset of 5 files of size 1MB,\n"
mlarsson@9046 467 "\t using the base name 'gctrace.txt', with 'uptimemillis' and 'pid' decorations.\n\n"
mlarsson@9046 468
mlarsson@9046 469 " -Xlog:gc::uptime,tid\n"
mlarsson@9046 470 "\t Log messages tagged with 'gc' tag using 'info' level to output 'stdout', using 'uptime' and 'tid' decorations.\n\n"
mlarsson@9046 471
mlarsson@9046 472 " -Xlog:gc*=info,rt*=off\n"
mlarsson@9046 473 "\t Log messages tagged with at least 'gc' using 'info' level, but turn off logging of messages tagged with 'rt'.\n"
mlarsson@9046 474 "\t (Messages tagged with both 'gc' and 'rt' will not be logged.)\n\n"
mlarsson@9046 475
mlarsson@9046 476 " -Xlog:disable -Xlog:rt=trace:rttrace.txt\n"
mlarsson@9046 477 "\t Turn off all logging, including warnings and errors,\n"
mlarsson@9046 478 "\t and then enable messages tagged with 'rt' using 'trace' level to file 'rttrace.txt'.\n");
mlarsson@9046 479 }
ysuenaga@9653 480
ysuenaga@9653 481 void LogConfiguration::rotate_all_outputs() {
mlarsson@9895 482 // Start from index 2 since neither stdout nor stderr can be rotated.
mlarsson@9895 483 for (size_t idx = 2; idx < _n_outputs; idx++) {
mlarsson@9895 484 _outputs[idx]->force_rotate();
ysuenaga@9653 485 }
ysuenaga@9653 486 }
ysuenaga@9653 487
rehn@10621 488 void LogConfiguration::register_update_listener(UpdateListenerFunction cb) {
rehn@10621 489 assert(cb != NULL, "Should not register NULL as listener");
rehn@10621 490 ConfigurationLock cl;
rehn@10621 491 size_t idx = _n_listener_callbacks++;
rehn@10621 492 _listener_callbacks = REALLOC_C_HEAP_ARRAY(UpdateListenerFunction,
rehn@10621 493 _listener_callbacks,
rehn@10621 494 _n_listener_callbacks,
rehn@10621 495 mtLogging);
rehn@10621 496 _listener_callbacks[idx] = cb;
rehn@10621 497 }
rehn@10621 498
rehn@10621 499 void LogConfiguration::notify_update_listeners() {
rehn@10621 500 assert(ConfigurationLock::current_thread_has_lock(), "notify_update_listeners must be called in ConfigurationLock scope (lock held)");
rehn@10621 501 for (size_t i = 0; i < _n_listener_callbacks; i++) {
rehn@10621 502 _listener_callbacks[i]();
rehn@10621 503 }
rehn@10621 504 }