Add logging framework.

DEBUG messages are completely optimized out if NDEBUG is defined.
This commit is contained in:
Peter Johnson
2015-07-31 22:41:26 -07:00
parent afcfdb13a0
commit 4356e313ec
9 changed files with 143 additions and 25 deletions

View File

@@ -35,6 +35,19 @@ enum NT_EntryFlags {
NT_PERSISTENT = 0x01
};
/** NetworkTables logging levels. */
enum NT_LogLevel {
NT_LOG_CRITICAL = 50,
NT_LOG_ERROR = 40,
NT_LOG_WARNING = 30,
NT_LOG_INFO = 20,
NT_LOG_DEBUG = 10,
NT_LOG_DEBUG1 = 9,
NT_LOG_DEBUG2 = 8,
NT_LOG_DEBUG3 = 7,
NT_LOG_DEBUG4 = 6
};
/*
* Structures
*/
@@ -309,6 +322,11 @@ void NT_DisposeConnectionInfoArray(struct NT_ConnectionInfo *arr, size_t count);
/* timestamp */
unsigned long long NT_Now(void);
/* logging */
typedef void (*NT_LogFunc)(unsigned int level, const char *file,
unsigned int line, const char *msg);
void NT_SetLogger(NT_LogFunc func, unsigned int min_level);
#ifdef __cplusplus
}
#endif

View File

@@ -220,6 +220,11 @@ const char* LoadPersistent(
/* timestamp */
unsigned long long Now();
/* logging */
typedef std::function<void(unsigned int level, const char* file,
unsigned int line, const char* msg)> LogFunc;
void SetLogger(LogFunc func, unsigned int min_level);
} // namespace nt
#endif /* NTCORE_CPP_H_ */

View File

@@ -12,17 +12,10 @@
#include "tcpsockets/TCPAcceptor.h"
#include "tcpsockets/TCPConnector.h"
#include "Log.h"
using namespace nt;
inline void DEBUG(const char* str, ...) {
va_list args;
va_start(args, str);
vfprintf(stderr, str, args);
fputc('\n', stderr);
va_end(args);
}
ATOMIC_STATIC_INIT(Dispatcher)
Dispatcher::Dispatcher()
@@ -302,7 +295,7 @@ bool Dispatcher::ClientHandshake(
if (msg->Is(Message::kServerHelloDone)) break;
if (!msg->Is(Message::kEntryAssign)) {
// unexpected message
DEBUG("client: received message (%d) other than entry assignment during initial handshake", msg->type());
DEBUG("client: received message (" << msg->type() << ") other than entry assignment during initial handshake");
return false;
}
incoming.emplace_back(std::move(msg));
@@ -388,7 +381,7 @@ bool Dispatcher::ServerHandshake(
if (msg->Is(Message::kClientHelloDone)) break;
if (!msg->Is(Message::kEntryAssign)) {
// unexpected message
DEBUG("server: received message (%d) other than entry assignment during initial handshake", msg->type());
DEBUG("server: received message (" << msg->type() << ") other than entry assignment during initial handshake");
return false;
}
incoming.push_back(msg);

16
src/Log.cpp Normal file
View File

@@ -0,0 +1,16 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "Log.h"
using namespace nt;
ATOMIC_STATIC_INIT(Logger)
Logger::Logger() : m_min_level(100) {}
Logger::~Logger() {}

83
src/Log.h Normal file
View File

@@ -0,0 +1,83 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_LOG_H_
#define NT_LOG_H_
#include <functional>
#include <sstream>
#include <string>
#include "atomic_static.h"
#include "ntcore_c.h"
namespace nt {
class Logger {
public:
static Logger& GetInstance() {
ATOMIC_STATIC(Logger, instance);
return instance;
}
~Logger();
typedef std::function<void(unsigned int level, const char* file,
unsigned int line, const char* msg)> LogFunc;
void SetLogger(LogFunc func) { m_func = func; }
void set_min_level(unsigned int level) { m_min_level = level; }
unsigned int min_level() const { return m_min_level; }
void Log(unsigned int level, const char* file, unsigned int line,
const char* msg) {
if (!m_func || level < m_min_level) return;
m_func(level, file, line, msg);
}
bool HasLogger() const { return m_func != nullptr; }
private:
Logger();
LogFunc m_func;
unsigned int m_min_level;
ATOMIC_STATIC_DECL(Logger)
};
#define LOG(level, x) \
do { \
Logger& logger = Logger::GetInstance(); \
if (logger.min_level() <= level && logger.HasLogger()) { \
std::ostringstream oss; \
oss << x; \
logger.Log(level, __FILE__, __LINE__, oss.str().c_str()); \
} \
} while (0)
#define ERROR(x) LOG(NT_LOG_ERROR, x)
#define WARNING(x) LOG(NT_LOG_WARNING, x)
#define INFO(x) LOG(NT_LOG_INFO, x)
#ifdef NDEBUG
#define DEBUG(x)
#define DEBUG1(x)
#define DEBUG2(x)
#define DEBUG3(x)
#define DEBUG4(x)
#else
#define DEBUG(x) LOG(NT_LOG_DEBUG, x)
#define DEBUG1(x) LOG(NT_LOG_DEBUG1, x)
#define DEBUG2(x) LOG(NT_LOG_DEBUG2, x)
#define DEBUG3(x) LOG(NT_LOG_DEBUG3, x)
#define DEBUG4(x) LOG(NT_LOG_DEBUG4, x)
#endif
} // namespace nt
#endif // NT_LOG_H_

View File

@@ -8,20 +8,13 @@
#include "NetworkConnection.h"
#include "tcpsockets/TCPStream.h"
#include "Log.h"
#include "raw_socket_istream.h"
#include "WireDecoder.h"
#include "WireEncoder.h"
using namespace nt;
inline void DEBUG(const char* str, ...) {
va_list args;
va_start(args, str);
vfprintf(stderr, str, args);
fputc('\n', stderr);
va_end(args);
}
NetworkConnection::NetworkConnection(std::unique_ptr<TCPStream> stream,
HandshakeFunc handshake,
Message::GetEntryTypeFunc get_entry_type,
@@ -81,8 +74,8 @@ void NetworkConnection::ReadThreadMain() {
[&] {
decoder.set_proto_rev(m_proto_rev);
auto msg = Message::Read(decoder, m_get_entry_type);
if (!msg)
DEBUG("error reading in handshake: %s", decoder.error());
if (!msg && decoder.error())
DEBUG("error reading in handshake: " << decoder.error());
return msg;
},
[&](llvm::ArrayRef<std::shared_ptr<Message>> msgs) {
@@ -116,11 +109,11 @@ void NetworkConnection::WriteThreadMain() {
while (m_active) {
auto msgs = m_outgoing.pop();
DEBUG("write thread woke up");
DEBUG4("write thread woke up");
if (msgs.empty()) break;
encoder.set_proto_rev(m_proto_rev);
encoder.Reset();
DEBUG("sending %d messages", msgs.size());
DEBUG4("sending " << msgs.size() << " messages");
for (auto& msg : msgs) {
if (msg) msg->Write(encoder);
}
@@ -128,7 +121,7 @@ void NetworkConnection::WriteThreadMain() {
if (!m_stream) break;
if (encoder.size() == 0) continue;
if (m_stream->send(encoder.data(), encoder.size(), &err) == 0) break;
DEBUG("sent %d bytes", encoder.size());
DEBUG4("sent " << encoder.size() << " bytes");
}
m_state = static_cast<int>(kDead);
m_active = false;

View File

@@ -12,11 +12,10 @@
#include "llvm/StringExtras.h"
#include "Base64.h"
#include "Log.h"
using namespace nt;
#define DEBUG(str) puts(str)
ATOMIC_STATIC_INIT(Storage)
Storage::Storage() {}

View File

@@ -288,6 +288,10 @@ const char *NT_LoadPersistent(const char *filename,
* Utility Functions
*/
void NT_SetLogger(NT_LogFunc func, unsigned int min_level) {
nt::SetLogger(func, min_level);
}
void NT_DisposeValue(NT_Value *value) {
switch (value->type) {
case NT_UNASSIGNED:

View File

@@ -13,6 +13,7 @@
#include <fstream>
#include "Dispatcher.h"
#include "Log.h"
#include "Storage.h"
namespace nt {
@@ -173,4 +174,10 @@ const char* LoadPersistent(
return nullptr;
}
void SetLogger(LogFunc func, unsigned int min_level) {
Logger& logger = Logger::GetInstance();
logger.SetLogger(func);
logger.set_min_level(min_level);
}
} // namespace nt