2022-12-24 23:49:50 +00:00
// Copyright (c) 2019-2022 The Bitcoin Core developers
2019-09-19 13:59:49 -04:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2022-08-18 11:03:28 +02:00
# include <init/common.h>
2019-09-19 13:59:49 -04:00
# include <logging.h>
# include <logging/timer.h>
2019-11-05 15:18:59 -05:00
# include <test/util/setup_common.h>
2022-03-02 16:34:53 +08:00
# include <util/string.h>
2019-09-19 13:59:49 -04:00
# include <chrono>
2022-03-02 16:34:53 +08:00
# include <fstream>
# include <iostream>
2022-08-18 13:37:25 +02:00
# include <unordered_map>
2022-03-02 16:34:53 +08:00
# include <utility>
# include <vector>
2019-09-19 13:59:49 -04:00
# include <boost/test/unit_test.hpp>
BOOST_FIXTURE_TEST_SUITE ( logging_tests , BasicTestingSetup )
2022-08-18 11:03:28 +02:00
static void ResetLogger ( )
{
LogInstance ( ) . SetLogLevel ( BCLog : : DEFAULT_LOG_LEVEL ) ;
LogInstance ( ) . SetCategoryLogLevel ( { } ) ;
}
2022-03-02 16:34:53 +08:00
struct LogSetup : public BasicTestingSetup {
fs : : path prev_log_path ;
fs : : path tmp_log_path ;
bool prev_reopen_file ;
bool prev_print_to_file ;
bool prev_log_timestamps ;
bool prev_log_threadnames ;
bool prev_log_sourcelocations ;
2022-08-18 13:37:25 +02:00
std : : unordered_map < BCLog : : LogFlags , BCLog : : Level > prev_category_levels ;
BCLog : : Level prev_log_level ;
2022-03-02 16:34:53 +08:00
LogSetup ( ) : prev_log_path { LogInstance ( ) . m_file_path } ,
tmp_log_path { m_args . GetDataDirBase ( ) / " tmp_debug.log " } ,
prev_reopen_file { LogInstance ( ) . m_reopen_file } ,
prev_print_to_file { LogInstance ( ) . m_print_to_file } ,
prev_log_timestamps { LogInstance ( ) . m_log_timestamps } ,
prev_log_threadnames { LogInstance ( ) . m_log_threadnames } ,
2022-08-18 13:37:25 +02:00
prev_log_sourcelocations { LogInstance ( ) . m_log_sourcelocations } ,
prev_category_levels { LogInstance ( ) . CategoryLevels ( ) } ,
prev_log_level { LogInstance ( ) . LogLevel ( ) }
2022-03-02 16:34:53 +08:00
{
LogInstance ( ) . m_file_path = tmp_log_path ;
LogInstance ( ) . m_reopen_file = true ;
LogInstance ( ) . m_print_to_file = true ;
LogInstance ( ) . m_log_timestamps = false ;
LogInstance ( ) . m_log_threadnames = false ;
2022-08-18 13:37:25 +02:00
// Prevent tests from failing when the line number of the logs changes.
LogInstance ( ) . m_log_sourcelocations = false ;
LogInstance ( ) . SetLogLevel ( BCLog : : Level : : Debug ) ;
LogInstance ( ) . SetCategoryLogLevel ( { } ) ;
2022-03-02 16:34:53 +08:00
}
~ LogSetup ( )
{
LogInstance ( ) . m_file_path = prev_log_path ;
LogPrintf ( " Sentinel log to reopen log file \n " ) ;
LogInstance ( ) . m_print_to_file = prev_print_to_file ;
LogInstance ( ) . m_reopen_file = prev_reopen_file ;
LogInstance ( ) . m_log_timestamps = prev_log_timestamps ;
LogInstance ( ) . m_log_threadnames = prev_log_threadnames ;
LogInstance ( ) . m_log_sourcelocations = prev_log_sourcelocations ;
2022-08-18 13:37:25 +02:00
LogInstance ( ) . SetLogLevel ( prev_log_level ) ;
LogInstance ( ) . SetCategoryLogLevel ( prev_category_levels ) ;
2022-03-02 16:34:53 +08:00
}
} ;
2019-09-19 13:59:49 -04:00
BOOST_AUTO_TEST_CASE ( logging_timer )
{
2021-09-06 21:01:57 +02:00
auto micro_timer = BCLog : : Timer < std : : chrono : : microseconds > ( " tests " , " end_msg " ) ;
2023-01-03 12:28:52 +01:00
const std : : string_view result_prefix { " tests: msg ( " } ;
BOOST_CHECK_EQUAL ( micro_timer . LogMsg ( " msg " ) . substr ( 0 , result_prefix . size ( ) ) , result_prefix ) ;
2019-09-19 13:59:49 -04:00
}
2022-03-02 16:34:53 +08:00
BOOST_FIXTURE_TEST_CASE ( logging_LogPrintf_ , LogSetup )
{
2022-08-18 13:37:25 +02:00
LogInstance ( ) . m_log_sourcelocations = true ;
2023-07-27 12:11:43 +01:00
LogPrintf_ ( " fn1 " , " src1 " , 1 , BCLog : : LogFlags : : NET , BCLog : : Level : : Debug , " foo1: %s \n " , " bar1 " ) ;
LogPrintf_ ( " fn2 " , " src2 " , 2 , BCLog : : LogFlags : : NET , BCLog : : Level : : None , " foo2: %s \n " , " bar2 " ) ;
LogPrintf_ ( " fn3 " , " src3 " , 3 , BCLog : : LogFlags : : NONE , BCLog : : Level : : Debug , " foo3: %s \n " , " bar3 " ) ;
LogPrintf_ ( " fn4 " , " src4 " , 4 , BCLog : : LogFlags : : NONE , BCLog : : Level : : None , " foo4: %s \n " , " bar4 " ) ;
2022-03-02 16:34:53 +08:00
std : : ifstream file { tmp_log_path } ;
std : : vector < std : : string > log_lines ;
for ( std : : string log ; std : : getline ( file , log ) ; ) {
log_lines . push_back ( log ) ;
}
std : : vector < std : : string > expected = {
" [src1:1] [fn1] [net:debug] foo1: bar1 " ,
" [src2:2] [fn2] [net] foo2: bar2 " ,
" [src3:3] [fn3] [debug] foo3: bar3 " ,
" [src4:4] [fn4] foo4: bar4 " ,
} ;
BOOST_CHECK_EQUAL_COLLECTIONS ( log_lines . begin ( ) , log_lines . end ( ) , expected . begin ( ) , expected . end ( ) ) ;
}
BOOST_FIXTURE_TEST_CASE ( logging_LogPrintMacros , LogSetup )
{
LogPrintf ( " foo5: %s \n " , " bar5 " ) ;
LogPrint ( BCLog : : NET , " foo6: %s \n " , " bar6 " ) ;
2022-05-25 11:31:58 +02:00
LogPrintLevel ( BCLog : : NET , BCLog : : Level : : Debug , " foo7: %s \n " , " bar7 " ) ;
LogPrintLevel ( BCLog : : NET , BCLog : : Level : : Info , " foo8: %s \n " , " bar8 " ) ;
LogPrintLevel ( BCLog : : NET , BCLog : : Level : : Warning , " foo9: %s \n " , " bar9 " ) ;
LogPrintLevel ( BCLog : : NET , BCLog : : Level : : Error , " foo10: %s \n " , " bar10 " ) ;
2022-05-25 18:26:54 +02:00
LogPrintfCategory ( BCLog : : VALIDATION , " foo11: %s \n " , " bar11 " ) ;
2022-03-02 16:34:53 +08:00
std : : ifstream file { tmp_log_path } ;
std : : vector < std : : string > log_lines ;
for ( std : : string log ; std : : getline ( file , log ) ; ) {
log_lines . push_back ( log ) ;
}
std : : vector < std : : string > expected = {
" foo5: bar5 " ,
" [net] foo6: bar6 " ,
" [net:debug] foo7: bar7 " ,
" [net:info] foo8: bar8 " ,
" [net:warning] foo9: bar9 " ,
2022-05-25 18:26:54 +02:00
" [net:error] foo10: bar10 " ,
" [validation] foo11: bar11 " ,
} ;
2022-03-02 16:34:53 +08:00
BOOST_CHECK_EQUAL_COLLECTIONS ( log_lines . begin ( ) , log_lines . end ( ) , expected . begin ( ) , expected . end ( ) ) ;
}
BOOST_FIXTURE_TEST_CASE ( logging_LogPrintMacros_CategoryName , LogSetup )
{
LogInstance ( ) . EnableCategory ( BCLog : : LogFlags : : ALL ) ;
2022-08-18 13:37:25 +02:00
const auto concatenated_category_names = LogInstance ( ) . LogCategoriesString ( ) ;
2022-03-02 16:34:53 +08:00
std : : vector < std : : pair < BCLog : : LogFlags , std : : string > > expected_category_names ;
2022-08-18 13:37:25 +02:00
const auto category_names = SplitString ( concatenated_category_names , ' , ' ) ;
2022-03-02 16:34:53 +08:00
for ( const auto & category_name : category_names ) {
2022-08-18 13:37:25 +02:00
BCLog : : LogFlags category ;
2022-03-02 16:34:53 +08:00
const auto trimmed_category_name = TrimString ( category_name ) ;
2022-08-18 13:37:25 +02:00
BOOST_REQUIRE ( GetLogCategory ( category , trimmed_category_name ) ) ;
2022-03-02 16:34:53 +08:00
expected_category_names . emplace_back ( category , trimmed_category_name ) ;
}
std : : vector < std : : string > expected ;
for ( const auto & [ category , name ] : expected_category_names ) {
LogPrint ( category , " foo: %s \n " , " bar " ) ;
std : : string expected_log = " [ " ;
expected_log + = name ;
expected_log + = " ] foo: bar " ;
expected . push_back ( expected_log ) ;
}
std : : ifstream file { tmp_log_path } ;
std : : vector < std : : string > log_lines ;
for ( std : : string log ; std : : getline ( file , log ) ; ) {
log_lines . push_back ( log ) ;
}
BOOST_CHECK_EQUAL_COLLECTIONS ( log_lines . begin ( ) , log_lines . end ( ) , expected . begin ( ) , expected . end ( ) ) ;
}
2022-08-18 11:02:54 +02:00
BOOST_FIXTURE_TEST_CASE ( logging_SeverityLevels , LogSetup )
{
LogInstance ( ) . EnableCategory ( BCLog : : LogFlags : : ALL ) ;
Create BCLog::Level::Trace log severity level
for verbose log messages for development or debugging only, as bitcoind may run
more slowly, that are more granular/frequent than the Debug log level, i.e. for
very high-frequency, low-level messages to be logged distinctly from
higher-level, less-frequent debug logging that could still be usable in production.
An example would be to log higher-level peer events (connection, disconnection,
misbehavior, eviction) as Debug, versus Trace for low-level, high-volume p2p
messages in the BCLog::NET category. This will enable the user to log only the
former without the latter, in order to focus on high-level peer management events.
With respect to the name, "trace" is suggested as the most granular level
in resources like the following:
- https://sematext.com/blog/logging-levels
- https://howtodoinjava.com/log4j2/logging-levels
Update the test framework and add test coverage.
2022-06-01 13:44:59 +02:00
LogInstance ( ) . SetLogLevel ( BCLog : : Level : : Debug ) ;
2022-08-18 11:02:54 +02:00
LogInstance ( ) . SetCategoryLogLevel ( /*category_str=*/ " net " , /*level_str=*/ " info " ) ;
// Global log level
LogPrintLevel ( BCLog : : HTTP , BCLog : : Level : : Info , " foo1: %s \n " , " bar1 " ) ;
Create BCLog::Level::Trace log severity level
for verbose log messages for development or debugging only, as bitcoind may run
more slowly, that are more granular/frequent than the Debug log level, i.e. for
very high-frequency, low-level messages to be logged distinctly from
higher-level, less-frequent debug logging that could still be usable in production.
An example would be to log higher-level peer events (connection, disconnection,
misbehavior, eviction) as Debug, versus Trace for low-level, high-volume p2p
messages in the BCLog::NET category. This will enable the user to log only the
former without the latter, in order to focus on high-level peer management events.
With respect to the name, "trace" is suggested as the most granular level
in resources like the following:
- https://sematext.com/blog/logging-levels
- https://howtodoinjava.com/log4j2/logging-levels
Update the test framework and add test coverage.
2022-06-01 13:44:59 +02:00
LogPrintLevel ( BCLog : : MEMPOOL , BCLog : : Level : : Trace , " foo2: %s. This log level is lower than the global one. \n " , " bar2 " ) ;
2022-08-18 11:02:54 +02:00
LogPrintLevel ( BCLog : : VALIDATION , BCLog : : Level : : Warning , " foo3: %s \n " , " bar3 " ) ;
LogPrintLevel ( BCLog : : RPC , BCLog : : Level : : Error , " foo4: %s \n " , " bar4 " ) ;
// Category-specific log level
LogPrintLevel ( BCLog : : NET , BCLog : : Level : : Warning , " foo5: %s \n " , " bar5 " ) ;
Create BCLog::Level::Trace log severity level
for verbose log messages for development or debugging only, as bitcoind may run
more slowly, that are more granular/frequent than the Debug log level, i.e. for
very high-frequency, low-level messages to be logged distinctly from
higher-level, less-frequent debug logging that could still be usable in production.
An example would be to log higher-level peer events (connection, disconnection,
misbehavior, eviction) as Debug, versus Trace for low-level, high-volume p2p
messages in the BCLog::NET category. This will enable the user to log only the
former without the latter, in order to focus on high-level peer management events.
With respect to the name, "trace" is suggested as the most granular level
in resources like the following:
- https://sematext.com/blog/logging-levels
- https://howtodoinjava.com/log4j2/logging-levels
Update the test framework and add test coverage.
2022-06-01 13:44:59 +02:00
LogPrintLevel ( BCLog : : NET , BCLog : : Level : : Debug , " foo6: %s. This log level is the same as the global one but lower than the category-specific one, which takes precedence. \n " , " bar6 " ) ;
2022-08-18 11:02:54 +02:00
LogPrintLevel ( BCLog : : NET , BCLog : : Level : : Error , " foo7: %s \n " , " bar7 " ) ;
std : : vector < std : : string > expected = {
" [http:info] foo1: bar1 " ,
" [validation:warning] foo3: bar3 " ,
" [rpc:error] foo4: bar4 " ,
" [net:warning] foo5: bar5 " ,
" [net:error] foo7: bar7 " ,
} ;
std : : ifstream file { tmp_log_path } ;
std : : vector < std : : string > log_lines ;
for ( std : : string log ; std : : getline ( file , log ) ; ) {
log_lines . push_back ( log ) ;
}
BOOST_CHECK_EQUAL_COLLECTIONS ( log_lines . begin ( ) , log_lines . end ( ) , expected . begin ( ) , expected . end ( ) ) ;
}
2022-08-18 11:03:28 +02:00
BOOST_FIXTURE_TEST_CASE ( logging_Conf , LogSetup )
{
// Set global log level
{
ResetLogger ( ) ;
ArgsManager args ;
args . AddArg ( " -loglevel " , " ... " , ArgsManager : : ALLOW_ANY , OptionsCategory : : DEBUG_TEST ) ;
const char * argv_test [ ] = { " bitcoind " , " -loglevel=debug " } ;
std : : string err ;
BOOST_REQUIRE ( args . ParseParameters ( 2 , argv_test , err ) ) ;
2023-05-12 00:58:35 +02:00
auto result = init : : SetLoggingLevel ( args ) ;
BOOST_REQUIRE ( result ) ;
2022-08-18 11:03:28 +02:00
BOOST_CHECK_EQUAL ( LogInstance ( ) . LogLevel ( ) , BCLog : : Level : : Debug ) ;
}
// Set category-specific log level
{
ResetLogger ( ) ;
ArgsManager args ;
args . AddArg ( " -loglevel " , " ... " , ArgsManager : : ALLOW_ANY , OptionsCategory : : DEBUG_TEST ) ;
Create BCLog::Level::Trace log severity level
for verbose log messages for development or debugging only, as bitcoind may run
more slowly, that are more granular/frequent than the Debug log level, i.e. for
very high-frequency, low-level messages to be logged distinctly from
higher-level, less-frequent debug logging that could still be usable in production.
An example would be to log higher-level peer events (connection, disconnection,
misbehavior, eviction) as Debug, versus Trace for low-level, high-volume p2p
messages in the BCLog::NET category. This will enable the user to log only the
former without the latter, in order to focus on high-level peer management events.
With respect to the name, "trace" is suggested as the most granular level
in resources like the following:
- https://sematext.com/blog/logging-levels
- https://howtodoinjava.com/log4j2/logging-levels
Update the test framework and add test coverage.
2022-06-01 13:44:59 +02:00
const char * argv_test [ ] = { " bitcoind " , " -loglevel=net:trace " } ;
2022-08-18 11:03:28 +02:00
std : : string err ;
BOOST_REQUIRE ( args . ParseParameters ( 2 , argv_test , err ) ) ;
2023-05-12 00:58:35 +02:00
auto result = init : : SetLoggingLevel ( args ) ;
BOOST_REQUIRE ( result ) ;
2022-08-18 11:03:28 +02:00
BOOST_CHECK_EQUAL ( LogInstance ( ) . LogLevel ( ) , BCLog : : DEFAULT_LOG_LEVEL ) ;
const auto & category_levels { LogInstance ( ) . CategoryLevels ( ) } ;
const auto net_it { category_levels . find ( BCLog : : LogFlags : : NET ) } ;
BOOST_REQUIRE ( net_it ! = category_levels . end ( ) ) ;
Create BCLog::Level::Trace log severity level
for verbose log messages for development or debugging only, as bitcoind may run
more slowly, that are more granular/frequent than the Debug log level, i.e. for
very high-frequency, low-level messages to be logged distinctly from
higher-level, less-frequent debug logging that could still be usable in production.
An example would be to log higher-level peer events (connection, disconnection,
misbehavior, eviction) as Debug, versus Trace for low-level, high-volume p2p
messages in the BCLog::NET category. This will enable the user to log only the
former without the latter, in order to focus on high-level peer management events.
With respect to the name, "trace" is suggested as the most granular level
in resources like the following:
- https://sematext.com/blog/logging-levels
- https://howtodoinjava.com/log4j2/logging-levels
Update the test framework and add test coverage.
2022-06-01 13:44:59 +02:00
BOOST_CHECK_EQUAL ( net_it - > second , BCLog : : Level : : Trace ) ;
2022-08-18 11:03:28 +02:00
}
// Set both global log level and category-specific log level
{
ResetLogger ( ) ;
ArgsManager args ;
args . AddArg ( " -loglevel " , " ... " , ArgsManager : : ALLOW_ANY , OptionsCategory : : DEBUG_TEST ) ;
Create BCLog::Level::Trace log severity level
for verbose log messages for development or debugging only, as bitcoind may run
more slowly, that are more granular/frequent than the Debug log level, i.e. for
very high-frequency, low-level messages to be logged distinctly from
higher-level, less-frequent debug logging that could still be usable in production.
An example would be to log higher-level peer events (connection, disconnection,
misbehavior, eviction) as Debug, versus Trace for low-level, high-volume p2p
messages in the BCLog::NET category. This will enable the user to log only the
former without the latter, in order to focus on high-level peer management events.
With respect to the name, "trace" is suggested as the most granular level
in resources like the following:
- https://sematext.com/blog/logging-levels
- https://howtodoinjava.com/log4j2/logging-levels
Update the test framework and add test coverage.
2022-06-01 13:44:59 +02:00
const char * argv_test [ ] = { " bitcoind " , " -loglevel=debug " , " -loglevel=net:trace " , " -loglevel=http:info " } ;
2022-08-18 11:03:28 +02:00
std : : string err ;
BOOST_REQUIRE ( args . ParseParameters ( 4 , argv_test , err ) ) ;
2023-05-12 00:58:35 +02:00
auto result = init : : SetLoggingLevel ( args ) ;
BOOST_REQUIRE ( result ) ;
2022-08-18 11:03:28 +02:00
BOOST_CHECK_EQUAL ( LogInstance ( ) . LogLevel ( ) , BCLog : : Level : : Debug ) ;
const auto & category_levels { LogInstance ( ) . CategoryLevels ( ) } ;
BOOST_CHECK_EQUAL ( category_levels . size ( ) , 2 ) ;
const auto net_it { category_levels . find ( BCLog : : LogFlags : : NET ) } ;
BOOST_CHECK ( net_it ! = category_levels . end ( ) ) ;
Create BCLog::Level::Trace log severity level
for verbose log messages for development or debugging only, as bitcoind may run
more slowly, that are more granular/frequent than the Debug log level, i.e. for
very high-frequency, low-level messages to be logged distinctly from
higher-level, less-frequent debug logging that could still be usable in production.
An example would be to log higher-level peer events (connection, disconnection,
misbehavior, eviction) as Debug, versus Trace for low-level, high-volume p2p
messages in the BCLog::NET category. This will enable the user to log only the
former without the latter, in order to focus on high-level peer management events.
With respect to the name, "trace" is suggested as the most granular level
in resources like the following:
- https://sematext.com/blog/logging-levels
- https://howtodoinjava.com/log4j2/logging-levels
Update the test framework and add test coverage.
2022-06-01 13:44:59 +02:00
BOOST_CHECK_EQUAL ( net_it - > second , BCLog : : Level : : Trace ) ;
2022-08-18 11:03:28 +02:00
const auto http_it { category_levels . find ( BCLog : : LogFlags : : HTTP ) } ;
BOOST_CHECK ( http_it ! = category_levels . end ( ) ) ;
BOOST_CHECK_EQUAL ( http_it - > second , BCLog : : Level : : Info ) ;
}
}
2019-09-19 13:59:49 -04:00
BOOST_AUTO_TEST_SUITE_END ( )