Quick Links: |
Provide throttling equivalents of some of the ball_log
macros.
More...
ball_log
macros. ball_log
. For example, the throttling version of BALL_LOG_INFO
is BALL_LOGTHROTTLE_INFO
, and the throttling version of BALL_LOGVA
is BALL_LOGTHROTTLEVA
. SEVERITY
associated with it (see ball_severity
for the definitions of the six standard severities). Those macros that don't contain a SEVERITY
in their name are passed an integral severity value in the range [0 .. 255]
, with suggested values defined in ball::Severity
, as their first argument. The next two arguments, MAX_SIMULTANEOUS_MESSAGES
and NANOSECONDS_PER_MESSAGE
, are described immediately below. bdlmt::Throttle
object to effect the throttling behavior. Note that each throttle object is statically declared, so it is shared by all threads. MAX_SIMULTANEOUS_MESSAGES * NANOSECONDS_PER_MESSAGE
. The MAX_SIMULTANEOUS_MESSAGES
configuration parameter thereby limits the maximum number of messages that will be permitted in an arbitrarily short time, and debt is "paid off" at a rate of 1 / NANOSECONDS_PER_MESSAGE
. MAX_SIMULTANEOUS_MESSAGES
and NANOSECONDS_PER_MESSAGE
constraints are 4 and 10LL * 1000 * 1000 * 1000
(10 seconds), respectively. For ease of exposition, all nanosecond quantities in the rest of this example are expressed in seconds. +--------------+----------------+----------------+---------------+
| Time | Time Debt | Message | Time Debt |
| in Seconds | in Seconds | Permitted? | in Seconds |
| Since First | Before Logging | Threshold: | After Log or |
| Message | Attempt | (4-1)*10 = 30 | Attempt |
+--------------+----------------+----------------+---------------+
| 0 | 0 | 0 <= 30 Yes | 0+10 -> 10 |
| 2 | 10- 2 -> 8 | 8 <= 30 Yes | 8+10 -> 18 |
| 4 | 18- 2 -> 16 | 16 <= 30 Yes | 16+10 -> 26 |
| 8 | 26- 4 -> 22 | 22 <= 30 Yes | 22+10 -> 32 |
| 9 | 32- 1 -> 31 | 31 > 30 No | 31+ 0 -> 31 |
| 10 | 31- 1 -> 30 | 30 <= 30 Yes | 30+10 -> 40 |
| 11 | 40- 1 -> 39 | 39 > 30 No | 39+ 0 -> 39 |
| 12 | 39- 1 -> 38 | 38 > 30 No | 38+ 0 -> 38 |
| 13 | 38- 1 -> 37 | 37 > 30 No | 37+ 0 -> 37 |
| 14 | 37- 1 -> 36 | 36 > 30 No | 36+ 0 -> 36 |
| 15 | 36- 1 -> 35 | 35 > 30 No | 35+ 0 -> 35 |
| 35 | 35-20 -> 15 | 15 <= 30 Yes | 15+10 -> 25 |
| 75 | 25-40 -> 0* | 0 <= 30 Yes | 0+10 -> 10 |
+--------------+----------------+----------------+---------------+
-- At 'Time == 75', the time debt goes to zero, even though 25-40 is
negative -- the time debt can never go negative, and never above the
bucket capacity of 40.
26 - 4 == 22
. This is less than the threshold of 30, so the message is permitted, and we add the time per message, which is 10 billion nanoseconds, or 10 seconds, and the time debt at the end is 32 seconds. 32 - 1 == 31
. This is higher than the threshold of 30, so the message is not permitted, and the time debt remains 31. MAX_SIMULTANEOUS_MESSAGES
to occur within any time span of less than NANOSECONDS_PER_MESSAGE
nanoseconds. MAX_SIMULTANEOUS_MESSAGES
and NANOSECONDS_PER_MESSAGE
arguments to all the macros defined in this component must be compile-time constants, and may not contain any floating-point subexpressions. Also note that MAX_SIMULTANEOUS_MESSAGES
is of type int
, NANOSECONDS_PER_MESSAGE
is of type bsls::Types::Int64
, and any SEVERITY
argument is of type int
and is interpreted as described by the ball_severity
component. MAX_SIMULTANEOUS_MESSAGES
and NANOSECONDS_PER_MESSAGE
must be compile-time constants, and may not contain any floating-point subexpressions. MAX_SIMULTANEOUS_MESSAGES
, NANOSECONDS_PER_MESSAGE
, and SEVERITY
are of types int
, bsls::Types::Int64
, and int
, respectively. SEVERITY
is in the range [0 .. 255]
, 0 <= MAX_SIMULTANEOUS_MESSAGES
, 0 <= NANOSECONDS_PER_MESSAGE
, 0 < MAX_SIMULTANEOUS_MESSAGES || 0 < NANOSECONDS_PER_MESSAGE
, and MAX_SIMULTANEOUS_MESSAGES * NANOSECONDS_PER_MESSAGE <= LLONG_MAX
. static const int k_MSM = 4; // 'MAX_SIMULTANEOUS_MESSAGES' argument static const bsls::Types::Int64 k_NPM = 10LL * 1000 * 1000 * 1000; // 'NANOSECONDS_PER_MESSAGE' argument
BALL_LOGTHROTTLE_*
macros are analogous to the BALL_LOG_*
macros, except that they take two additional throttle-related arguments, MAX_SIMULTANEOUS_MESSAGE
and NANOSECONDS_PER_MESSAGE
, described in Throttling Concepts above. BALL_LOGTHROTTLE_TRACE
, BALL_LOGTHROTTLE_DEBUG
, BALL_LOGTHROTTLE_INFO
, BALL_LOGTHROTTLE_WARN
, BALL_LOGTHROTTLE_ERROR
, and BALL_LOGTHROTTLE_FATAL
, are the ones most commonly used for log throttling. They have the following usage pattern: BALL_LOGTHROTTLE_<SEVERITY>(MAX_SIMULTANEOUS_MESSAGES, NANOSECONDS_PER_MESSAGE) << X << Y ... ; Throttle logging with the specified 'MAX_SIMULTANEOUS_MESSAGES' and 'NANOSECONDS_PER_MESSAGE' as described in {Throttling Concepts}, where 'X, Y, ...' represents any sequence of values for which 'operator<<' is defined. If the throttle permits a message to be logged, the resulting formatted message is logged with the severity indicated by the name of the macro (e.g., 'BALL_LOGTHROTTLE_ERROR' logs with severity 'ball::Severity::e_ERROR').
int cpu = 6502; BALL_LOGTHROTTLE_ERROR(k_MSM, k_NPM) << "Help, I'm being held prisoner in a " << cpu << " microprocessor!";
BALL_LOGTHROTTLE_STREAM
, requires that the severity be explicitly supplied as an argument: BALL_LOGTHROTTLE_STREAM(SEVERITY, MAX_SIMULTANEOUS_MESSAGES, NANOSECONDS_PER_MESSAGE) << X << Y ... ; Throttle logging with the specified 'MAX_SIMULTANEOUS_MESSAGES' and 'NANOSECONDS_PER_MESSAGE' as described in {Throttling Concepts}, where 'X, Y, ...' represents any sequence of values for which 'operator<<' is defined. If the throttle permits a message to be logged, the resulting formatted message is logged with the specified 'SEVERITY'.
int cpu = 6502; BALL_LOGTHROTTLE_STREAM(ball::Severity::e_ERROR, k_MSM, k_NPM) << "Help, I'm being held prisoner in a " << cpu << " microprocessor!";
BALL_LOGTHROTTLE_*_BLOCK
macros are analogous to the BALL_LOG_*_BLOCK
macros, except that they take two throttle-related arguments, MAX_SIMULTANEOUS_MESSAGES
and NANOSECONDS_PER_MESSAGE
, described in Throttling Concepts above. BALL_LOGTHROTTLE_<SEVERITY>_BLOCK(MAX_SIMULTANEOUS_MESSAGES, NANOSECONDS_PER_MESSAGE) <block> Throttle logging with the specified 'MAX_SIMULTANEOUS_MESSAGES' and 'NANOSECONDS_PER_MESSAGE' as described in {Throttling Concepts}, where any sequence of values for which 'operator<<' is defined may be streamed to 'BALL_LOG_OUTPUT_STREAM' within the controlled '<block>'. If the throttle permits a message to be logged, the resulting formatted message is logged with the severity indicated by the name of the macro (e.g., 'BALL_LOGTHROTTLE_WARN_BLOCK' logs with severity 'ball::Severity::e_WARN').
BALL_LOGTHROTTLE_ERROR_BLOCK(k_MSM, k_NPM) { int cpu = 6502; if (x < y(z) + 7.2) { BALL_LOG_OUTPUT_STREAM << "Help, I'm being held prisoner in a " << cpu << " microprocessor!"; } }
BALL_LOGTHROTTLE_BLOCK
, requires that the severity be explicitly supplied as an argument: BALL_LOGTHROTTLE_BLOCK(SEVERITY, MAX_SIMULTANEOUS_MESSAGES, NANOSECONDS_PER_MESSAGE) <block> Throttle logging with the specified 'MAX_SIMULTANEOUS_MESSAGES' and 'NANOSECONDS_PER_MESSAGE' as described in {Throttling Concepts}, where any sequence of values for which 'operator<<' is defined may be streamed to 'BALL_LOG_OUTPUT_STREAM' within the controlled '<block>'. If the throttle permits a message to be logged, the resulting formatted message is logged with the specified 'SEVERITY'.
BALL_LOGTHROTTLE_BLOCK(ball::Severity::e_ERROR, k_MSM, k_NPM) { int cpu = 6502; if (x < y(z) + 7.2) { BALL_LOG_OUTPUT_STREAM << "Help, I'm being held prisoner in a " << cpu << " microprocessor!"; } }
BALL_LOGTHROTTLEVA_*
macros are analogous to the BALL_LOGVA_*
macros, except that they take two additional throttle-related arguments, MAX_SIMULTANEOUS_MESSAGES
and NANOSECONDS_PER_MESSAGE
, described in Throttling Concepts above. BALL_LOGTHROTTLEVA_<SEVERITY>(MAX_SIMULTANEOUS_MESSAGE, NANOSECONDS_PER_MESSAGE, MSG, ...); Throttle logging with the specified 'MAX_SIMULTANEOUS_MESSAGES' and 'NANOSECONDS_PER_MESSAGE' as described in {Throttling Concepts}. If the throttle permits a message to be logged, format the specified '...' optional arguments, if any, according to the 'printf'-style format specification in the specified 'MSG' (assumed to be of type convertible to 'const char *'), and log the resulting formatted message with the severity indicated by the name of the macro (e.g., 'BALL_LOGTHROTTLEVA_INFO' logs with severity 'ball::Severity::e_INFO'). The behavior is undefined unless the number and types of the optional arguments are compatible with the format specification in 'MSG'. Note that each use of these macros must be terminated by a ';'.
int cpu = 6502; BALL_LOGTHROTTLEVA_ERROR(k_MSM, k_NPM, "Help, I'm being held prisoner" " in a %d microprocessor!", cpu);
BALL_LOGTHROTTLEVA
that takes the SEVERITY
as an argument, rather than being part of the macro name. BALL_LOGTHROTTLEVA(SEVERITY, MAX_SIMULTANEOUS_MESSAGES, NANOSECONDS_PER_MESSAGE, MSG, ...); Throttle logging with the specified 'MAX_SIMULTANEOUS_MESSAGES' and 'NANOSECONDS_PER_MESSAGE' as described in {Throttling Concepts}. If the throttle permits a message to be logged, format the specified '...' optional arguments, if any, according to the 'printf'-style format specification in the specified 'MSG' (assumed to be of type convertible to 'const char *'), and log the resulting formatted message with the specified 'SEVERITY'. The behavior is undefined unless the number and types of the optional arguments are compatible with the format specification in 'MSG'. Note that each use of this macro must be terminated by a ';'.
int cpu = 6502; BALL_LOGTHROTTLEVA_ERROR(ball::Severity::e_ERROR, k_MSM, k_NPM, "Help, I'm being held prisoner" " in a %d microprocessor!", cpu);
enum { k_NUM_INFO = 20, // max # of info messages in a very short time k_NUM_DEBUG = 5, // max # of debug messages in a very short time k_NUM_TRACE = 1 // max # of trace messages in a very short time }; const Int64 k_NS_PER_HOUR = BloombergLP::bdlt::TimeUnitRatio::k_NANOSECONDS_PER_HOUR; const Int64 k_NS_PER_INFO = k_NS_PER_HOUR / k_NUM_INFO; // long-term minimum nanoseconds per info message permitted const Int64 k_NS_PER_DEBUG = k_NS_PER_HOUR / k_NUM_DEBUG; // long-term minimum nanoseconds per debug message permitted const Int64 k_NS_PER_TRACE = k_NS_PER_HOUR / k_NUM_TRACE; // long-term minimum nanoseconds per trace message permitted
double
values from a radio receiver, ten per second, which represent readings of radiation detected by a Geiger counter on a spacecraft, and is transmitting them to a ground control at Jet Propulsion Laboratories in California. double yield()
manipulator of a RadiationMeterReceiver
object (the implementation of which is omitted). The yield
method blocks until it obtains a reading to return. If called in a tight loop, yield
returns ten readings per second. e_TRACE
severity, and at most one per hour (i.e., messages will be throttled). e_DEBUG
severity, and at most five per hour. e_INFO
severity, and at most twenty per hour. e_WARN
severity, with no limit on the number of readings reported (i.e., no throttling). void radiationMonitorStreamDaemon() // Daemon to run the radiation monitor. { BALL_LOG_SET_CATEGORY("RADIATION.MONITOR"); RadiationMeterReceiver receiver; BALL_LOG_DEBUG << "Start gathering data."; double reading; while (-1.0 != (reading = receiver.yield())) {
e_WARN
readings: if (90 < reading) { BALL_LOG_WARN << "Serious Radiation reading of " << reading; }
e_INFO
readings, which aren't as severe as e_WARN
: else if (60 < reading) { BALL_LOGTHROTTLE_INFO(k_NUM_INFO, k_NS_PER_INFO) << "Radiation reading of " << reading; }
e_DEBUG
messages less severe than e_INFO
readings: else if (30 < reading) { BALL_LOGTHROTTLE_DEBUG(k_NUM_DEBUG, k_NS_PER_DEBUG) << "Radiation reading of " << reading; }
e_TRACE
messages less severe than e_DEBUG
readings: else if (10 < reading) { BALL_LOGTHROTTLE_TRACE(k_NUM_TRACE, k_NS_PER_TRACE) << "Radiation reading of " << reading; } } BALL_LOG_DEBUG << "Finished gathering data."; }
receiver.yield()
are: 0 0 12.3 0 10.5 33.1 11.9 53.7 0 0 46.1 14.7 67.4 43.9 53.3 98.2 0 22.3 77.3 36.2 0 17.7 52.5 0 43.2 0 72.9 0 51.9 71.2 92.4 0 0 11.8 33.1 0 47.2 15.5 35.7 0 22.3 17.6 0 52.7 0 22.1 -1
(10.0 .. 30.0]
, which correspond to e_TRACE
level messages, occurred. (30.0 .. 60.0]
, which correspond to e_DEBUG
level messages, occurred. (60.0 .. 90.0]
, which correspond to e_INFO
level messages, occurred. e_WARN
level messages, occurred. e_TRACE
message and 5 e_DEBUG
messages are permitted by the throttle within the (very long) time period of one hour, so the other messages at those levels will be suppressed. radiationMonitorPrintfDaemon
produces output like: 24APR2018_16:36:22.791 61260 139907579877152 DEBUG ball_logthrottle.t.cpp 460 RADIATION.MONITOR Start gathering data. 24APR2018_16:36:23.094 61260 139907579877152 TRACE ball_logthrottle.t.cpp 488 RADIATION.MONITOR Radiation reading of 12.3 24APR2018_16:36:23.396 61260 139907579877152 DEBUG ball_logthrottle.t.cpp 481 RADIATION.MONITOR Radiation reading of 33.1 24APR2018_16:36:23.597 61260 139907579877152 DEBUG ball_logthrottle.t.cpp 481 RADIATION.MONITOR Radiation reading of 53.7 24APR2018_16:36:23.901 61260 139907579877152 DEBUG ball_logthrottle.t.cpp 481 RADIATION.MONITOR Radiation reading of 46.1 24APR2018_16:36:24.102 61260 139907579877152 INFO ball_logthrottle.t.cpp 474 RADIATION.MONITOR Radiation reading of 67.4 24APR2018_16:36:24.203 61260 139907579877152 DEBUG ball_logthrottle.t.cpp 481 RADIATION.MONITOR Radiation reading of 43.9 24APR2018_16:36:24.304 61260 139907579877152 DEBUG ball_logthrottle.t.cpp 481 RADIATION.MONITOR Radiation reading of 53.3 24APR2018_16:36:24.404 61260 139907579877152 WARN ball_logthrottle.t.cpp 468 RADIATION.MONITOR Serious Radiation reading of 98.2 24APR2018_16:36:24.706 61260 139907579877152 INFO ball_logthrottle.t.cpp 474 RADIATION.MONITOR Radiation reading of 77.3 24APR2018_16:36:25.513 61260 139907579877152 INFO ball_logthrottle.t.cpp 474 RADIATION.MONITOR Radiation reading of 72.9 24APR2018_16:36:25.816 61260 139907579877152 INFO ball_logthrottle.t.cpp 474 RADIATION.MONITOR Radiation reading of 71.2 24APR2018_16:36:25.918 61260 139907579877152 WARN ball_logthrottle.t.cpp 468 RADIATION.MONITOR Serious Radiation reading of 92.4 24APR2018_16:36:27.429 61260 139907579877152 DEBUG ball_logthrottle.t.cpp 493 RADIATION.MONITOR Finished gathering data.
e_TRACE
messages and 8 e_DEBUG
messages were suppressed by the throttling. void radiationMonitorBlockDaemon() // Daemon to run the radiation monitor. { BALL_LOG_SET_CATEGORY("RADIATION.MONITOR"); RadiationMeterReceiver receiver; BALL_LOGVA_DEBUG("Start gathering data."); double reading; while (-1.0 != (reading = receiver.yield())) {
e_WARN
messages: if (90 < reading) { BALL_LOG_WARN_BLOCK { BALL_LOG_OUTPUT_STREAM << "Serious radiation reading of " << reading; } }
e_INFO
messages that aren't as severe as e_WARN
: else if (60 < reading) { BALL_LOGTHROTTLE_INFO_BLOCK(k_NUM_INFO, k_NS_PER_INFO) { BALL_LOG_OUTPUT_STREAM << "Radiation reading of " << reading; } }
e_DEBUG
messages less severe than e_INFO
readings: else if (30 < reading) { BALL_LOGTHROTTLE_DEBUG_BLOCK(k_NUM_DEBUG, k_NS_PER_DEBUG) { BALL_LOG_OUTPUT_STREAM << "Radiation reading of " << reading; } }
e_TRACE
messages less severe than e_DEBUG
readings. else if (10 < reading) { BALL_LOGTHROTTLE_TRACE_BLOCK(k_NUM_TRACE, k_NS_PER_TRACE) { BALL_LOG_OUTPUT_STREAM << "Radiation reading of " << reading; } } } BALL_LOG_DEBUG << "Finished gathering data."; }
receiver.yield()
match those from Usage Example 1, then the output will be identical to that example. printf
-style throttling macros: void radiationMonitorPrintfDaemon() // Daemon to run the radiation monitor. { BALL_LOG_SET_CATEGORY("RADIATION.MONITOR"); RadiationMeterReceiver receiver; BALL_LOGVA_DEBUG("Start gathering data."); double reading; while (-1.0 != (reading = receiver.yield())) {
e_WARN
messages: if (90 < reading) { BALL_LOGVA_WARN("Serious radiation reading of %g", reading); }
e_INFO
messages that aren't as severe as e_WARN
: else if (60 < reading) { BALL_LOGTHROTTLEVA_INFO( k_NUM_INFO, k_NS_PER_INFO, "Radiation reading of %g", reading); }
e_DEBUG
messages less severe than e_INFO
readings: else if (30 < reading) { BALL_LOGTHROTTLEVA_DEBUG( k_NUM_DEBUG, k_NS_PER_DEBUG, "Radiation reading of %g", reading); }
e_TRACE
messages less severe than e_DEBUG
readings: else if (10 < reading) { BALL_LOGTHROTTLEVA_TRACE( k_NUM_TRACE, k_NS_PER_TRACE, "Radiation reading of %g", reading); } } BALL_LOGVA_DEBUG("Finished gathering data."); }
receiver.yield()
match those from Usage Example 1, then the output will be identical to that example.