Add LogManager and add log messages for the detection process
Commit amended for code style and to remove unrelated changes by Adam Honse <calcprogrammer1@gmail.com>
This commit is contained in:
parent
78ea2ee8f0
commit
ca11939277
4 changed files with 328 additions and 1 deletions
246
LogManager.cpp
Normal file
246
LogManager.cpp
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
#include "LogManager.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "ResourceManager.h"
|
||||
|
||||
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
|
||||
#include <experimental/filesystem>
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
LogManager::LogManager()
|
||||
{
|
||||
}
|
||||
|
||||
LogManager* LogManager::get()
|
||||
{
|
||||
static LogManager* _instance = nullptr;
|
||||
static std::mutex instance_mutex;
|
||||
std::lock_guard<std::mutex> grd(instance_mutex);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Create a new instance if one does not exist |
|
||||
\*-------------------------------------------------*/
|
||||
if(!_instance)
|
||||
{
|
||||
_instance = new LogManager();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void LogManager::configure(json config, const std::string &defaultDir)
|
||||
{
|
||||
std::lock_guard<std::mutex> grd(entry_mutex);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If the log is not open, create a new log file |
|
||||
\*-------------------------------------------------*/
|
||||
if(!log_stream.is_open())
|
||||
{
|
||||
std::string logname = "OpenRGB_#.log";
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If the logfile is defined in the configuration, |
|
||||
| use the configured name |
|
||||
\*-------------------------------------------------*/
|
||||
if(config.contains("logfile"))
|
||||
{
|
||||
const json& logfile_obj = config["logfile"];
|
||||
if(logfile_obj.is_string())
|
||||
{
|
||||
std::string tmpname = config["logfile"];
|
||||
if(!tmpname.empty())
|
||||
{
|
||||
logname = tmpname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If the # symbol is found in the log file name, |
|
||||
| replace it with a timestamp |
|
||||
\*-------------------------------------------------*/
|
||||
size_t oct = logname.find("#");
|
||||
if(oct != logname.npos)
|
||||
{
|
||||
time_t t = time(0);
|
||||
struct tm* tmp = localtime(&t);
|
||||
char buf[64];
|
||||
snprintf(buf, 64, "%04d%02d%02d_%02d%02d%02d", 1900 + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
|
||||
logname.replace(oct, 1, buf);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If the path is relative, use configuration dir |
|
||||
\*-------------------------------------------------*/
|
||||
fs::path p = logname;
|
||||
if(p.is_relative())
|
||||
{
|
||||
p = defaultDir;
|
||||
p.append(logname);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Open the logfile |
|
||||
\*-------------------------------------------------*/
|
||||
log_stream.open(p);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Check loglevel configuration |
|
||||
\*-------------------------------------------------*/
|
||||
if(config.contains("loglevel"))
|
||||
{
|
||||
const json& loglevel_obj = config["loglevel"];
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If the log level is configured per section, set |
|
||||
| loglevel for each section |
|
||||
\*-------------------------------------------------*/
|
||||
if(loglevel_obj.is_object())
|
||||
{
|
||||
for(size_t section = 0; section < sections.size(); ++section)
|
||||
{
|
||||
if(loglevel_obj.contains(sections[section]))
|
||||
{
|
||||
const json& val = loglevel_obj[sections[section]];
|
||||
|
||||
if(val.is_number_integer())
|
||||
{
|
||||
loglevels[section] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If the log level is configured globally, set same |
|
||||
| loglevel for each section |
|
||||
\*-------------------------------------------------*/
|
||||
else if(loglevel_obj.is_number_integer())
|
||||
{
|
||||
int l = loglevel_obj;
|
||||
for(size_t section = 0; section < sections.size(); ++section)
|
||||
{
|
||||
loglevels[section] = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Flush the log |
|
||||
\*-------------------------------------------------*/
|
||||
_flush();
|
||||
}
|
||||
|
||||
void LogManager::_flush()
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| If the log is open, write out buffered messages |
|
||||
\*-------------------------------------------------*/
|
||||
if(log_stream.is_open())
|
||||
{
|
||||
for(size_t msg = 0; msg < temp_messages.size(); ++msg)
|
||||
{
|
||||
int sec = temp_sections[msg];
|
||||
if(temp_levels[msg] <= loglevels[sec])
|
||||
{
|
||||
log_stream << temp_messages[msg] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Clear temp message buffers after writing them out |
|
||||
\*-------------------------------------------------*/
|
||||
temp_messages.clear();
|
||||
temp_levels.clear();
|
||||
temp_sections.clear();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Flush the stream |
|
||||
\*-------------------------------------------------*/
|
||||
log_stream.flush();
|
||||
}
|
||||
|
||||
void LogManager::flush()
|
||||
{
|
||||
std::lock_guard<std::mutex> grd(entry_mutex);
|
||||
_flush();
|
||||
}
|
||||
|
||||
void LogManager::append(int section, int level, const char* fmt, ...)
|
||||
{
|
||||
std::lock_guard<std::mutex> grd(entry_mutex);
|
||||
|
||||
char buf[1024];
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Start the variable argument list |
|
||||
\*-------------------------------------------------*/
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Return if the log is already open |
|
||||
\*-------------------------------------------------*/
|
||||
if(!log_stream.is_open() && level > loglevels[section])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Print the section to the log entry |
|
||||
\*-------------------------------------------------*/
|
||||
int off = sprintf(buf, "[%s]: ", sections[section].c_str());
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Print the log text to the log entry |
|
||||
\*-------------------------------------------------*/
|
||||
vsnprintf(buf + off, 1024 - off, fmt, va);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Write the log entry |
|
||||
\*-------------------------------------------------*/
|
||||
if(log_stream.is_open())
|
||||
{
|
||||
log_stream << buf << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_levels.push_back(level);
|
||||
temp_messages.push_back(buf);
|
||||
temp_sections.push_back(section);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| End the variable argument list |
|
||||
\*-------------------------------------------------*/
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
int LogManager::registerSection(const char* name, int loglevel)
|
||||
{
|
||||
std::lock_guard<std::mutex> grd(section_mutex);
|
||||
size_t section;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Check to see if section already exists, if so, |
|
||||
| return the existing section value |
|
||||
\*-------------------------------------------------*/
|
||||
for(section = 0; section < sections.size(); section++)
|
||||
{
|
||||
if(sections[section] == name)
|
||||
{
|
||||
return section;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If section does not already exist, create it |
|
||||
\*-------------------------------------------------*/
|
||||
sections.push_back(name);
|
||||
loglevels.push_back(loglevel);
|
||||
|
||||
return section;
|
||||
}
|
||||
49
LogManager.h
Normal file
49
LogManager.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef LOGMANAGER_H
|
||||
#define LOGMANAGER_H
|
||||
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "json.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
enum
|
||||
{
|
||||
LL_CRITICAL,
|
||||
LL_ERROR,
|
||||
LL_WARNING,
|
||||
LL_NOTICE,
|
||||
LL_VERBOSE,
|
||||
LL_DEBUG
|
||||
};
|
||||
|
||||
class LogManager
|
||||
{
|
||||
private:
|
||||
LogManager();
|
||||
LogManager(const LogManager&) = delete;
|
||||
LogManager(LogManager&&) = delete;
|
||||
~LogManager();
|
||||
std::mutex entry_mutex;
|
||||
std::mutex section_mutex;
|
||||
std::vector<std::string> sections;
|
||||
std::vector<int> loglevels;
|
||||
std::ofstream log_stream;
|
||||
std::vector<std::string> temp_messages;
|
||||
std::vector<int> temp_levels;
|
||||
std::vector<int> temp_sections;
|
||||
void _flush();
|
||||
|
||||
public:
|
||||
static LogManager* get();
|
||||
void configure(json config, const std::string& defaultDir);
|
||||
void flush();
|
||||
void append(int section, int level, const char* fmt, ...);
|
||||
int registerSection(const char* name, int loglevel);
|
||||
};
|
||||
|
||||
#define LogSection(name,level) LogManager::get()->registerSection(name, level)
|
||||
#define LogAppend LogManager::get()->append
|
||||
|
||||
#endif // LOGMANAGER_H
|
||||
|
|
@ -116,6 +116,7 @@ INCLUDEPATH +=
|
|||
HEADERS += \
|
||||
dependencies/ColorWheel/ColorWheel.h \
|
||||
dependencies/json/json.hpp \
|
||||
LogManager.h \
|
||||
NetworkClient.h \
|
||||
NetworkProtocol.h \
|
||||
NetworkServer.h \
|
||||
|
|
@ -329,6 +330,7 @@ SOURCES +=
|
|||
dependencies/libe131/src/e131.c \
|
||||
main.cpp \
|
||||
cli.cpp \
|
||||
LogManager.cpp \
|
||||
NetworkClient.cpp \
|
||||
NetworkServer.cpp \
|
||||
PluginManager.cpp \
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "ResourceManager.h"
|
||||
#include "ProfileManager.h"
|
||||
#include "LogManager.h"
|
||||
|
||||
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
|
||||
#include <experimental/filesystem>
|
||||
|
|
@ -59,6 +60,11 @@ ResourceManager::ResourceManager()
|
|||
\*-------------------------------------------------------------------------*/
|
||||
settings_manager = new SettingsManager();
|
||||
settings_manager->LoadSettings(GetConfigurationDirectory() + "OpenRGB.json");
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
| Configure the log manager |
|
||||
\*-------------------------------------------------------------------------*/
|
||||
LogManager::get()->configure(settings_manager->GetSettings("Client"), GetConfigurationDirectory());
|
||||
}
|
||||
|
||||
ResourceManager::~ResourceManager()
|
||||
|
|
@ -78,6 +84,7 @@ std::vector<i2c_smbus_interface*> & ResourceManager::GetI2CBusses()
|
|||
|
||||
void ResourceManager::RegisterRGBController(RGBController *rgb_controller)
|
||||
{
|
||||
LogAppend(LogSection("Detection", LL_DEBUG), LL_DEBUG, "Registering RGB controller: %s", rgb_controller->name.c_str());
|
||||
rgb_controllers_hw.push_back(rgb_controller);
|
||||
|
||||
DeviceListChanged();
|
||||
|
|
@ -424,6 +431,14 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
unsigned int prev_count = 0;
|
||||
bool save_settings = false;
|
||||
std::vector<bool> size_used;
|
||||
int detection_section;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Create a log debug section named Detection |
|
||||
\*-------------------------------------------------*/
|
||||
detection_section = LogSection("Detection", LL_DEBUG);
|
||||
|
||||
LogAppend(detection_section, LL_NOTICE, "Detection started" );
|
||||
|
||||
size_used.resize(rgb_controllers_sizes.size());
|
||||
|
||||
|
|
@ -478,6 +493,8 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
/*-------------------------------------------------*\
|
||||
| Detect i2c busses |
|
||||
\*-------------------------------------------------*/
|
||||
LogAppend(detection_section, LL_DEBUG, "Detecting I2C/SMBus busses");
|
||||
|
||||
for(unsigned int i2c_bus_detector_idx = 0; i2c_bus_detector_idx < i2c_bus_detectors.size() && detection_is_required.load(); i2c_bus_detector_idx++)
|
||||
{
|
||||
i2c_bus_detectors[i2c_bus_detector_idx](busses);
|
||||
|
|
@ -487,6 +504,8 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
/*-------------------------------------------------*\
|
||||
| Detect i2c devices |
|
||||
\*-------------------------------------------------*/
|
||||
LogAppend(detection_section, LL_DEBUG, "Detecting I2C/SMBus devices");
|
||||
|
||||
for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < i2c_device_detectors.size() && detection_is_required.load(); i2c_detector_idx++)
|
||||
{
|
||||
detection_string = i2c_device_detector_strings[i2c_detector_idx].c_str();
|
||||
|
|
@ -563,6 +582,8 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
|
||||
if(hid_safe_mode)
|
||||
{
|
||||
LogAppend(detection_section, LL_NOTICE, "Detecting HID devices in safe mode");
|
||||
|
||||
/*-----------------------------------------------------------------------------*\
|
||||
| Loop through all available detectors. If all required information matches, |
|
||||
| run the detector |
|
||||
|
|
@ -571,6 +592,8 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
{
|
||||
hid_devices = hid_enumerate(hid_device_detectors[hid_detector_idx].address >> 16, hid_device_detectors[hid_detector_idx].address & 0x0000FFFF);
|
||||
|
||||
LogAppend(detection_section, LL_NOTICE, "Trying to run detector for [%s] (for 0x%08hx)", hid_device_detectors[hid_detector_idx].name.c_str(), hid_device_detectors[hid_detector_idx].address);
|
||||
|
||||
current_hid_device = hid_devices;
|
||||
|
||||
while(current_hid_device)
|
||||
|
|
@ -639,6 +662,8 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
}
|
||||
else
|
||||
{
|
||||
LogAppend(detection_section, LL_NOTICE, "Detecting HID devices");
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Iterate through all devices in list and run |
|
||||
| detectors |
|
||||
|
|
@ -719,6 +744,8 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
/*-------------------------------------------------*\
|
||||
| Detect other devices |
|
||||
\*-------------------------------------------------*/
|
||||
LogAppend(detection_section, LL_NOTICE, "Detecting other devices");
|
||||
|
||||
for(unsigned int detector_idx = 0; detector_idx < device_detectors.size() && detection_is_required.load(); detector_idx++)
|
||||
{
|
||||
detection_string = device_detector_strings[detector_idx].c_str();
|
||||
|
|
@ -775,7 +802,6 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
| Make sure that when the detection is done, |
|
||||
| progress bar is set to 100% |
|
||||
\*-------------------------------------------------*/
|
||||
|
||||
detection_is_required = false;
|
||||
detection_percent = 100;
|
||||
detection_string = "";
|
||||
|
|
@ -786,10 +812,14 @@ void ResourceManager::DetectDevicesThreadFunction()
|
|||
|
||||
if(save_settings)
|
||||
{
|
||||
LogAppend(detection_section, LL_NOTICE, "Saving detector settings");
|
||||
|
||||
settings_manager->SetSettings("Detectors", detector_settings);
|
||||
|
||||
settings_manager->SaveSettings();
|
||||
}
|
||||
|
||||
LogAppend(detection_section, LL_NOTICE, "Detection completed");
|
||||
}
|
||||
|
||||
void ResourceManager::StopDeviceDetection()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue