blob: 91223abb68dbd2ff71094facba7f2c3938f20865 [file] [log] [blame]
/** @file
LogMessage implementation.
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "tscore/LogMessage.h"
#include "tscore/Diags.h"
using namespace std::chrono_literals;
std::atomic<std::chrono::milliseconds> LogMessage::_default_log_throttling_interval{0ms};
std::atomic<std::chrono::milliseconds> LogMessage::_default_debug_throttling_interval{0ms};
// static
void
LogMessage::set_default_log_throttling_interval(std::chrono::milliseconds new_interval)
{
_default_log_throttling_interval = new_interval;
}
// static
void
LogMessage::set_default_debug_throttling_interval(std::chrono::milliseconds new_interval)
{
_default_debug_throttling_interval = new_interval;
}
void
LogMessage::message_helper(std::chrono::microseconds current_configured_interval, log_function_f log_function, const char *fmt,
va_list args)
{
if (!_is_throttled) {
// If throttling is disabled, make this operation as efficient as possible.
// Simply log and exit without consulting the Throttler API.
//
// If the user changes the throttling value from some non-zero value to
// zero, then we may miss out on some "The following message was
// suppressed" logs. However we accept this as a tradeoff to make this
// common case as fast as possible.
log_function(fmt, args);
return;
}
if (!_throttling_value_is_explicitly_set) {
set_throttling_interval(current_configured_interval);
}
uint64_t number_of_suppressions = 0;
if (is_throttled(number_of_suppressions)) {
// The messages are the same and but we're still within the throttling
// interval. Suppress this message.
return;
}
// If we get here, the message should not be suppressed.
if (number_of_suppressions > 0) {
// We use no format parameters, so we just need an empty va_list.
va_list empty_args;
std::string message =
std::string("The following message was suppressed ") + std::to_string(number_of_suppressions) + std::string(" times.");
log_function(message.c_str(), empty_args);
}
log_function(fmt, args);
}
void
LogMessage::standard_message_helper(DiagsLevel level, SourceLocation const &loc, const char *fmt, va_list args)
{
message_helper(
_default_log_throttling_interval.load(),
[level, &loc](const char *fmt, va_list args) { diags->error_va(level, &loc, fmt, args); }, fmt, args);
}
void
LogMessage::message_debug_helper(const char *tag, DiagsLevel level, SourceLocation const &loc, const char *fmt, va_list args)
{
message_helper(
_default_debug_throttling_interval.load(),
[tag, level, &loc](const char *fmt, va_list args) { diags->log_va(tag, level, &loc, fmt, args); }, fmt, args);
}
void
LogMessage::message_print_helper(const char *tag, DiagsLevel level, SourceLocation const &loc, const char *fmt, va_list args)
{
message_helper(
_default_debug_throttling_interval.load(),
[tag, level, &loc](const char *fmt, va_list args) { diags->print_va(tag, level, &loc, fmt, args); }, fmt, args);
}
LogMessage::LogMessage(bool is_throttled)
// Turn throttling off by default. Each log event will check the configured
// throttling interval.
: Throttler{std::chrono::milliseconds{0}}, _throttling_value_is_explicitly_set{false}, _is_throttled{is_throttled}
{
}
LogMessage::LogMessage(std::chrono::milliseconds throttling_interval)
: Throttler{throttling_interval}, _throttling_value_is_explicitly_set{true}, _is_throttled{throttling_interval != 0ms}
{
}
void
LogMessage::diag(const char *tag, SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
message_debug_helper(tag, DL_Diag, loc, fmt, args);
va_end(args);
}
void
LogMessage::debug(const char *tag, SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
message_debug_helper(tag, DL_Debug, loc, fmt, args);
va_end(args);
}
void
LogMessage::status(SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
standard_message_helper(DL_Status, loc, fmt, args);
va_end(args);
}
void
LogMessage::note(SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
standard_message_helper(DL_Note, loc, fmt, args);
va_end(args);
}
void
LogMessage::warning(SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
standard_message_helper(DL_Warning, loc, fmt, args);
va_end(args);
}
void
LogMessage::error(SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
standard_message_helper(DL_Error, loc, fmt, args);
va_end(args);
}
void
LogMessage::fatal(SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
standard_message_helper(DL_Fatal, loc, fmt, args);
va_end(args);
}
void
LogMessage::alert(SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
standard_message_helper(DL_Alert, loc, fmt, args);
va_end(args);
}
void
LogMessage::emergency(SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
standard_message_helper(DL_Emergency, loc, fmt, args);
va_end(args);
}
void
LogMessage::message(DiagsLevel level, SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
standard_message_helper(level, loc, fmt, args);
va_end(args);
}
void
LogMessage::print(const char *tag, DiagsLevel level, SourceLocation const &loc, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
message_print_helper(tag, level, loc, fmt, args);
va_end(args);
}
void
LogMessage::diag_va(const char *tag, SourceLocation const &loc, const char *fmt, va_list args)
{
message_debug_helper(tag, DL_Diag, loc, fmt, args);
}
void
LogMessage::debug_va(const char *tag, SourceLocation const &loc, const char *fmt, va_list args)
{
message_debug_helper(tag, DL_Debug, loc, fmt, args);
}
void
LogMessage::status_va(SourceLocation const &loc, const char *fmt, va_list args)
{
standard_message_helper(DL_Status, loc, fmt, args);
}
void
LogMessage::note_va(SourceLocation const &loc, const char *fmt, va_list args)
{
standard_message_helper(DL_Note, loc, fmt, args);
}
void
LogMessage::warning_va(SourceLocation const &loc, const char *fmt, va_list args)
{
standard_message_helper(DL_Warning, loc, fmt, args);
}
void
LogMessage::error_va(SourceLocation const &loc, const char *fmt, va_list args)
{
standard_message_helper(DL_Error, loc, fmt, args);
}
void
LogMessage::fatal_va(SourceLocation const &loc, const char *fmt, va_list args)
{
standard_message_helper(DL_Fatal, loc, fmt, args);
}
void
LogMessage::alert_va(SourceLocation const &loc, const char *fmt, va_list args)
{
standard_message_helper(DL_Alert, loc, fmt, args);
}
void
LogMessage::emergency_va(SourceLocation const &loc, const char *fmt, va_list args)
{
standard_message_helper(DL_Emergency, loc, fmt, args);
}
void
LogMessage::message_va(DiagsLevel level, SourceLocation const &loc, const char *fmt, va_list args)
{
standard_message_helper(level, loc, fmt, args);
}