diff --git a/CMakeLists.txt b/CMakeLists.txt index 2db14613..15959caa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ list (APPEND opendht_HEADERS include/opendht/value.h include/opendht/dht.h include/opendht/securedht.h + include/opendht/log.h include/opendht.h ) diff --git a/include/opendht.h b/include/opendht.h index 29fab079..d7caf3dc 100644 --- a/include/opendht.h +++ b/include/opendht.h @@ -24,4 +24,5 @@ #include "opendht/infohash.h" #include "opendht/securedht.h" #include "opendht/dhtrunner.h" +#include "opendht/log.h" #include "opendht/default_types.h" diff --git a/include/opendht/log.h b/include/opendht/log.h new file mode 100644 index 00000000..0838ed6d --- /dev/null +++ b/include/opendht/log.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2014-2016 Savoir-faire Linux Inc. + * + * Author: Adrien Béraud + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "dhtrunner.h" + +#include +#include + +namespace dht { +namespace log { + +/** + * Terminal colors for logging + */ +namespace Color { + enum Code { + FG_RED = 31, + FG_GREEN = 32, + FG_YELLOW = 33, + FG_BLUE = 34, + FG_DEFAULT = 39, + BG_RED = 41, + BG_GREEN = 42, + BG_BLUE = 44, + BG_DEFAULT = 49 + }; + class Modifier { + const Code code; + public: + constexpr Modifier(Code pCode) : code(pCode) {} + friend std::ostream& + operator<<(std::ostream& os, const Modifier& mod) { + return os << "\033[" << mod.code << 'm'; + } + }; +} + +constexpr const Color::Modifier def(Color::FG_DEFAULT); +constexpr const Color::Modifier red(Color::FG_RED); +constexpr const Color::Modifier yellow(Color::FG_YELLOW); + +/** + * Print va_list to std::ostream (used for logging). + */ +void +printLog(std::ostream& s, char const* m, va_list args) { + static constexpr int BUF_SZ = 8192; + char buffer[BUF_SZ]; + int ret = vsnprintf(buffer, sizeof(buffer), m, args); + if (ret < 0) + return; + s.write(buffer, std::min(ret, BUF_SZ)); + if (ret >= BUF_SZ) + s << "[[TRUNCATED]]"; + s.put('\n'); +} + +void +enableLogging(dht::DhtRunner& dht) +{ + dht.setLoggers( + [](char const* m, va_list args){ std::cerr << red; printLog(std::cerr, m, args); std::cerr << def; }, + [](char const* m, va_list args){ std::cout << yellow; printLog(std::cout, m, args); std::cout << def; }, + [](char const* m, va_list args){ printLog(std::cout, m, args); } + ); +} + +void +enableFileLogging(dht::DhtRunner& dht, const std::string& path) +{ + auto logfile = std::make_shared(); + logfile->open(path, std::ios::out); + + dht.setLoggers( + [=](char const* m, va_list args){ printLog(*logfile, m, args); }, + [=](char const* m, va_list args){ printLog(*logfile, m, args); }, + [=](char const* m, va_list args){ printLog(*logfile, m, args); } + ); +} + +void +disableLogging(dht::DhtRunner& dht) +{ + dht.setLoggers(dht::NOLOG, dht::NOLOG, dht::NOLOG); +} + +} /* log */ +} /* dht */ + diff --git a/python/opendht_cpp.pxd b/python/opendht_cpp.pxd index 29f9f65a..f88797c3 100644 --- a/python/opendht_cpp.pxd +++ b/python/opendht_cpp.pxd @@ -153,3 +153,9 @@ cdef extern from "opendht/dhtrunner.h" namespace "dht": vector[unsigned] getNodeMessageStats(bool i) ctypedef DhtRunner.Config Config + +cdef extern from "opendht/log.h" namespace "dht::log": + void enableLogging(DhtRunner& dht) + void disableLogging(DhtRunner& dht) + void enableFileLogging(DhtRunner& dht, const string& path) + diff --git a/python/tools/benchmark.py b/python/tools/benchmark.py index 0d20a93a..ff98fbac 100755 --- a/python/tools/benchmark.py +++ b/python/tools/benchmark.py @@ -132,7 +132,6 @@ class WorkBench(): if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Run, test and benchmark a '\ 'DHT network on a local virtual network with simulated packet '\ 'loss and latency.') @@ -148,6 +147,7 @@ if __name__ == '__main__': ifConfArgs.add_argument('-no6', '--disable-ipv6', action="store_true", help='Enable IPv6') testArgs = parser.add_argument_group('Test arguments') + testArgs.add_argument('--bs-dht-log', action='store_true', default=False, help='Enables dht log in bootstrap.') testArgs.add_argument('-t', '--test', type=str, default=None, required=True, help='Specifies the test.') testArgs.add_argument('-o', '--opt', type=str, default=[], nargs='+', help='Options passed to tests routines.') @@ -164,16 +164,30 @@ if __name__ == '__main__': 'Use "-m" to specify the number of producers on the DHT.'\ 'Use "-e" to specify the number of values to put on the DHT.') - args = parser.parse_args() test_opt = { o : True for o in args.opt } wb = WorkBench(args.ifname, args.virtual_locs, args.node_num, loss=args.loss, delay=args.delay, disable_ipv4=args.disable_ipv4, disable_ipv6=args.disable_ipv6) - wb.create_virtual_net() - bootstrap = wb.get_bootstrap() + + bs_dht_log_enabled = False + def toggle_bs_dht_log(signum, frame): + global bs_dht_log_enabled, bootstrap + if bs_dht_log_enabled: + bootstrap.front().disableLogging() + bs_dht_log_enabled = False + else: + bootstrap.front().enableLogging() + bs_dht_log_enabled = True + signal.signal(signal.SIGUSR1, toggle_bs_dht_log) + + if args.bs_dht_log: + bs_dht_log_enabled = True + bootstrap.front().enableLogging() + + wb.create_virtual_net() bootstrap.resize(1) print("Launching", wb.node_num, "nodes (", wb.clusters, "clusters of", wb.node_per_loc, "nodes)") diff --git a/src/Makefile.am b/src/Makefile.am index d0666269..4a645504 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,4 +28,5 @@ nobase_include_HEADERS = \ ../include/opendht/securedht.h \ ../include/opendht/dhtrunner.h \ ../include/opendht/default_types.h \ + ../include/opendht/log.h \ ../include/opendht/rng.h diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp index 092bbd6b..718733bb 100644 --- a/tools/dhtnode.cpp +++ b/tools/dhtnode.cpp @@ -137,9 +137,9 @@ void cmd_loop(DhtRunner& dht, dht_params& params) } else if (op == "log") { params.log = !params.log; if (params.log) - enableLogging(dht); + log::enableLogging(dht); else - disableLogging(dht); + log::disableLogging(dht); continue; } @@ -261,9 +261,9 @@ main(int argc, char **argv) if (params.log) { if (not params.logfile.empty()) - enableFileLogging(dht, params.logfile); + log::enableFileLogging(dht, params.logfile); else - enableLogging(dht); + log::enableLogging(dht); } if (not params.bootstrap.first.empty()) {