Skip to content
Snippets Groups Projects
Commit 4846846a authored by Perttu Ahola's avatar Perttu Ahola
Browse files

Initially add small and tight logging facility

parent 414c6148
Branches
Tags
No related merge requests found
......@@ -90,6 +90,7 @@ configure_file(
)
set(common_SRCS
log.cpp
content_sao.cpp
mapgen.cpp
content_inventory.cpp
......
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "log.h"
#include <map>
#include <list>
#include <sstream>
#include "threads.h"
#include "debug.h"
#include "gettime.h"
std::list<ILogOutput*> log_outputs[LMT_NUM_VALUES];
std::map<threadid_t, std::string> log_threadnames;
void log_add_output(ILogOutput *out, enum LogMessageLevel lev)
{
log_outputs[lev].push_back(out);
}
void log_add_output_maxlev(ILogOutput *out, enum LogMessageLevel lev)
{
for(int i=0; i<=lev; i++)
log_outputs[i].push_back(out);
}
void log_add_output_all_levs(ILogOutput *out)
{
for(int i=0; i<LMT_NUM_VALUES; i++)
log_outputs[i].push_back(out);
}
void log_register_thread(const std::string &name)
{
threadid_t id = get_current_thread_id();
log_threadnames[id] = name;
}
static std::string get_lev_string(enum LogMessageLevel lev)
{
switch(lev){
case LMT_ERROR:
return "ERROR";
case LMT_ACTION:
return "ACTION";
case LMT_INFO:
return "INFO";
case LMT_VERBOSE:
return "VERBOSE";
case LMT_NUM_VALUES:
break;
}
return "(unknown level)";
}
void log_printline(enum LogMessageLevel lev, const std::string &text)
{
std::string threadname = "(unknown thread)";
std::map<threadid_t, std::string>::const_iterator i;
i = log_threadnames.find(get_current_thread_id());
if(i != log_threadnames.end())
threadname = i->second;
std::string levelname = get_lev_string(lev);
std::ostringstream os(std::ios_base::binary);
os<<getTimestamp()<<": "<<levelname<<"["<<threadname<<"]: "<<text;
for(std::list<ILogOutput*>::iterator i = log_outputs[lev].begin();
i != log_outputs[lev].end(); i++){
ILogOutput *out = *i;
out->printLog(os.str());
out->printLog(lev, text);
}
}
class Logbuf : public std::streambuf
{
public:
Logbuf(enum LogMessageLevel lev):
m_lev(lev)
{
}
~Logbuf()
{
}
int overflow(int c)
{
bufchar(c);
return c;
}
std::streamsize xsputn(const char *s, std::streamsize n)
{
for(int i=0; i<n; i++)
bufchar(s[i]);
return n;
}
void printbuf()
{
log_printline(m_lev, m_buf);
}
void bufchar(char c)
{
if(c == '\n' || c == '\r'){
if(m_buf != "")
printbuf();
m_buf = "";
return;
}
m_buf += c;
}
private:
enum LogMessageLevel m_lev;
std::string m_buf;
};
Logbuf errorbuf(LMT_ERROR);
Logbuf actionbuf(LMT_ACTION);
Logbuf infobuf(LMT_INFO);
Logbuf verbosebuf(LMT_VERBOSE);
std::ostream errorstream(&errorbuf);
std::ostream actionstream(&actionbuf);
std::ostream infostream(&infobuf);
std::ostream verbosestream(&verbosebuf);
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef LOG_HEADER
#define LOG_HEADER
#include <string>
/*
Use this for logging everything.
If you need to explicitly print something, use dstream or cout or cerr.
*/
enum LogMessageLevel {
LMT_ERROR, /* Something failed ("invalid map data on disk, block (2,2,1)") */
LMT_ACTION, /* In-game actions ("celeron55 placed block at (12,4,-5)") */
LMT_INFO, /* More deep info ("saving map on disk (only_modified=true)") */
LMT_VERBOSE, /* Flood-style ("loaded block (2,2,2) from disk") */
LMT_NUM_VALUES,
};
class ILogOutput
{
public:
/* line: Full line with timestamp, level and thread */
virtual void printLog(const std::string &line){};
/* line: Only actual printed text */
virtual void printLog(enum LogMessageLevel lev, const std::string &line){};
};
void log_add_output(ILogOutput *out, enum LogMessageLevel lev);
void log_add_output_maxlev(ILogOutput *out, enum LogMessageLevel lev);
void log_add_output_all_levs(ILogOutput *out);
void log_register_thread(const std::string &name);
void log_printline(enum LogMessageLevel lev, const std::string &text);
#define LOGLINEF(lev, ...)\
{\
char buf[10000];\
snprintf(buf, 10000, __VA_ARGS__);\
log_printline(lev, buf);\
}
extern std::ostream errorstream;
extern std::ostream actionstream;
extern std::ostream infostream;
extern std::ostream verbosestream;
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment