mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
Add logging framework.
DEBUG messages are completely optimized out if NDEBUG is defined.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
16
src/Log.cpp
Normal 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
83
src/Log.h
Normal 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_
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user