32#include <wx/datetime.h>
33#include <wx/filename.h>
37const wxLogLevel OcpnLog::LOG_BADLEVEL = wxLOG_Max + 1;
39const static std::map<wxLogLevel, const char*> name_by_level = {
40 {wxLOG_FatalError,
"FATALERR"}, {wxLOG_Error,
"ERROR"},
41 {wxLOG_Warning,
"WARNING"}, {wxLOG_Message,
"MESSAGE"},
42 {wxLOG_Status,
"STATUS"}, {wxLOG_Info,
"INFO"},
43 {wxLOG_Debug,
"DEBUG"}, {wxLOG_Trace,
"TRACE"},
44 {wxLOG_Progress,
"PROGRESS"}};
46static std::map<std::string, wxLogLevel> level_by_name;
48static std::string basename(
const std::string path) {
49 size_t pos = path.rfind(wxFileName::GetPathSeparator(), path.length());
50 return pos == std::string::npos ? path : path.substr(pos + 1);
53static void init_level_by_name() {
54 for (
auto it = name_by_level.begin(); it != name_by_level.end(); it++) {
55 level_by_name[std::string(it->second)] = it->first;
59static std::string timeStamp() {
60 wxDateTime now = wxDateTime::UNow();
61 std::stringstream stamp;
62 stamp << std::setfill(
'0') << std::setw(2) << now.GetHour() <<
":"
63 << std::setw(2) << now.GetMinute() <<
":" << std::setw(2)
64 << now.GetSecond() <<
"." << std::setw(3) << now.GetMillisecond();
68std::string OcpnLog::level2str(wxLogLevel level) {
69 auto search = name_by_level.find(level);
70 return search == name_by_level.end() ?
"Unknown level" : search->second;
73wxLogLevel OcpnLog::str2level(
const char*
string) {
74 if (level_by_name.size() == 0) {
77 std::string key(
string);
78 std::transform(key.begin(), key.end(), key.begin(), ::toupper);
79 auto search = level_by_name.find(key);
80 return search == level_by_name.end() ? LOG_BADLEVEL : search->second;
84 log.open(path, std::fstream::out | std::fstream::app);
87OcpnLog::~OcpnLog() { log.close(); }
89void OcpnLog::Flush() {
94void OcpnLog::DoLogRecord(wxLogLevel level,
const wxString& msg,
95 const wxLogRecordInfo& info) {
96 std::ostringstream oss;
97 oss << timeStamp() <<
" " << std::setw(7) << level2str(level) <<
" "
98 << basename(info.filename) <<
":" << info.line <<
" " << msg << std::endl;
102Logger::Logger() : info(
"", 0,
"",
""), level(wxLOG_Info) {};
105 wxString msg(os.str());
106 wxLog* log = wxLog::GetActiveTarget();
107 auto ocpnLog =
dynamic_cast<OcpnLog*
>(log);
109 ocpnLog->LogRecord(level, msg, info);
113std::ostream& Logger::get(wxLogLevel l,
const char* path,
int line) {
114 info.filename = path;
121 const wxLogRecordInfo info) {
122 wxLog* log = wxLog::GetActiveTarget();
123 auto ocpnLog =
dynamic_cast<OcpnLog*
>(log);
125 ocpnLog->LogRecord(level, wxString(msg), info);
129void Logger::logMessage(wxLogLevel level,
const char* path,
int line,
130 const char* fmt, ...) {
131 wxLogRecordInfo info(__FILE__, __LINE__,
"",
"");
135 vsnprintf(buf,
sizeof(buf), fmt, ap);
137 auto log =
dynamic_cast<OcpnLog*
>(wxLog::GetActiveTarget());
139 log->LogRecord(level, buf, info);
145 if (m_not_logged < m_count)
return;
147 wxLogGeneric(m_level, message.c_str());
148 wxLogGeneric(m_level,
"Previous message suppressed %d times", m_count);
153 auto now = std::chrono::steady_clock::now();
155 if (now - m_last_logged < m_interval)
return;
157 wxLogGeneric(m_level, message.c_str());
158 wxLogGeneric(m_level,
"Previous message suppressed %d times", m_not_logged);
void Log(const std::string &message)
Log a repeated message after suppressing n ones.
void logRecord(wxLogLevel level, const char *msg, const wxLogRecordInfo info)
DoLogRecord public wrapper.
Customized logger class appending to a file providing:
OcpnLog(const char *path)
Create logger appending to given filename.
void Log(const std::string &message)
Log a repeated message after interval seconds.
Enhanced logging interface on top of wx/log.h.