citra/src/common/logging/backend.cpp

140 lines
3.8 KiB
C++
Raw Normal View History

2014-10-28 07:36:00 +00:00
// Copyright 2014 Citra Emulator Project
2014-12-17 05:38:14 +00:00
// Licensed under GPLv2 or any later version
2014-10-28 07:36:00 +00:00
// Refer to the license.txt file included.
#include <algorithm>
#include <array>
#include <cstdio>
2014-10-28 07:36:00 +00:00
#include "common/assert.h"
#include "common/common_funcs.h" // snprintf compatibility define
2014-10-28 07:36:00 +00:00
#include "common/logging/backend.h"
#include "common/logging/filter.h"
2014-10-28 07:36:00 +00:00
#include "common/logging/log.h"
#include "common/logging/text_formatter.h"
namespace Log {
/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this.
#define ALL_LOG_CLASSES() \
CLS(Log) \
CLS(Common) \
SUB(Common, Filesystem) \
SUB(Common, Memory) \
CLS(Core) \
SUB(Core, ARM11) \
SUB(Core, Timing) \
2014-10-28 07:36:00 +00:00
CLS(Config) \
CLS(Debug) \
SUB(Debug, Emulated) \
SUB(Debug, GPU) \
SUB(Debug, Breakpoint) \
2015-09-02 12:56:38 +00:00
SUB(Debug, GDBStub) \
2014-10-28 07:36:00 +00:00
CLS(Kernel) \
SUB(Kernel, SVC) \
CLS(Service) \
SUB(Service, SRV) \
SUB(Service, FS) \
SUB(Service, ERR) \
2014-10-28 07:36:00 +00:00
SUB(Service, APT) \
SUB(Service, GSP) \
SUB(Service, AC) \
SUB(Service, AM) \
2014-10-28 07:36:00 +00:00
SUB(Service, PTM) \
SUB(Service, LDR) \
2015-03-08 01:54:16 +00:00
SUB(Service, NIM) \
SUB(Service, NWM) \
SUB(Service, CAM) \
2014-10-28 07:36:00 +00:00
SUB(Service, CFG) \
SUB(Service, DSP) \
SUB(Service, HID) \
SUB(Service, SOC) \
2016-02-21 11:48:28 +00:00
SUB(Service, IR) \
SUB(Service, Y2R) \
2014-10-28 07:36:00 +00:00
CLS(HW) \
SUB(HW, Memory) \
SUB(HW, LCD) \
2014-10-28 07:36:00 +00:00
SUB(HW, GPU) \
CLS(Frontend) \
CLS(Render) \
SUB(Render, Software) \
SUB(Render, OpenGL) \
CLS(Audio) \
SUB(Audio, DSP) \
2014-10-28 07:36:00 +00:00
CLS(Loader)
// GetClassName is a macro defined by Windows.h, grrr...
const char* GetLogClassName(Class log_class) {
2014-10-28 07:36:00 +00:00
switch (log_class) {
#define CLS(x) case Class::x: return #x;
#define SUB(x, y) case Class::x##_##y: return #x "." #y;
ALL_LOG_CLASSES()
#undef CLS
#undef SUB
case Class::Count:
UNREACHABLE();
2014-10-28 07:36:00 +00:00
}
}
const char* GetLevelName(Level log_level) {
2014-10-28 07:36:00 +00:00
#define LVL(x) case Level::x: return #x
switch (log_level) {
LVL(Trace);
LVL(Debug);
LVL(Info);
LVL(Warning);
LVL(Error);
LVL(Critical);
case Level::Count:
UNREACHABLE();
2014-10-28 07:36:00 +00:00
}
#undef LVL
}
Entry CreateEntry(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
const char* format, va_list args) {
using std::chrono::steady_clock;
using std::chrono::duration_cast;
static steady_clock::time_point time_origin = steady_clock::now();
std::array<char, 4 * 1024> formatting_buffer;
Entry entry;
entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
entry.log_class = log_class;
entry.log_level = log_level;
snprintf(formatting_buffer.data(), formatting_buffer.size(), "%s:%s:%u", filename, function, line_nr);
entry.location = std::string(formatting_buffer.data());
vsnprintf(formatting_buffer.data(), formatting_buffer.size(), format, args);
entry.message = std::string(formatting_buffer.data());
return std::move(entry);
}
static Filter* filter = nullptr;
void SetFilter(Filter* new_filter) {
filter = new_filter;
}
2014-10-28 07:36:00 +00:00
void LogMessage(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
const char* format, ...) {
if (filter != nullptr && !filter->CheckMessage(log_class, log_level))
return;
2014-10-28 07:36:00 +00:00
va_list args;
va_start(args, format);
Entry entry = CreateEntry(log_class, log_level,
filename, line_nr, function, format, args);
va_end(args);
PrintColoredMessage(entry);
2014-10-28 07:36:00 +00:00
}
}