IAP GITLAB

Skip to content
Snippets Groups Projects
Commit 70a70e39 authored by ralfulrich's avatar ralfulrich
Browse files

refactoredd logging into sub-files

parent 3f8e64dd
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,7 @@
#include <string>
#include <iostream>
#include <fstream>
#include <boost/format.hpp>
......@@ -13,10 +14,10 @@ main()
{
cout << "writing to \"another.log\"" << endl;
ofstream logfile("another.log");
typedef Sink<ofstream, StdBuffer> SinkFile;
SinkFile sink(logfile, StdBuffer(10000));
logger<SinkFile, messageconst> info("\033[32m", "info", sink);
logger<SinkFile, messageconst> err("\033[31m", "error", sink);
logger::sink::SinkStream unbuffered_sink(logfile);
logger::sink::BufferedSinkStream sink(logfile, logger::sink::StdBuffer(10000));
logger::Logger<logger::MessageOn, logger::sink::BufferedSinkStream> info("\033[32m", "info", sink);
logger::Logger<logger::MessageOn, logger::sink::BufferedSinkStream> err("\033[31m", "error", sink);
//logger<ostream,messageconst,StdBuffer> info(std::cout, StdBuffer(10000));
/*
......@@ -26,14 +27,14 @@ main()
*/
for (int i=0; i<100000; ++i) {
LOG(info, "irgendwas"," ", string("and more")," ", boost::format("error: %i message: %s. done."), i, "stupido");
LOG(err, "Fehler");
LOG(info, "irgendwas"," ", string("and more")," ", boost::format("error: %i message: %s. done."), i, "stupido");
LOG(err, "Fehler");
}
}
{
NoSink off;
logger<NoSink, MessageOff> info("", "", off);
logger::sink::NoSink off;
logger::Logger<logger::MessageOff> info("", "", off);
for (int i=0; i<100000; ++i) {
LOG(info, "irgendwas", string("and more"), boost::format("error: %i message: %s. done."), i, "stupido", "a-number:", 8.99, "ENDE" );
......
#ifndef _include_BufferedSink_h_
#define _include_BufferedSink_h_
namespace logger {
namespace sink {
/**
Output buffer template. NoBuffer does nothingk.
*/
/*
struct NoBuffer {
inline bool Test(const std::string&) const { return false; }
inline std::string GetString() const { return std::string(""); }
inline void Clear() {}
inline void Add(const std::string&) {}
};
*/
/**
Output buffer template. StdBuffer records fSize characters in
local memeory before passing it on to further output stages.
*/
struct StdBuffer {
StdBuffer(const int size) : fSize(size) {}
inline bool Test(const std::string& s) { return int(fBuffer.tellp())+s.length() < fSize; }
inline std::string GetString() const { return fBuffer.str(); }
inline void Clear() { fBuffer.str(""); }
inline void Add(const std::string& s) { fBuffer << s; }
private:
int fSize;
std::ostringstream fBuffer;
};
/**
Definition of Sink for log output.
*/
template<typename TStream, typename TBuffer=StdBuffer>
class BufferedSink {
public:
BufferedSink(TStream& out, TBuffer buffer = {} ) : fOutput(out), fBuffer(std::move(buffer)) {}
void operator<<(const std::string& msg) {
if (!fBuffer.Test(msg)) {
fOutput << fBuffer.GetString();
fBuffer.Clear();
}
if (!fBuffer.Test(msg))
fOutput << msg;
else
fBuffer.Add(msg);
}
void Close() { fOutput << fBuffer.GetString(); }
private:
TStream& fOutput;
TBuffer fBuffer;
};
typedef BufferedSink<std::ostream, StdBuffer> BufferedSinkStream;
}// end namespace
} // end namespace
#endif
......@@ -8,6 +8,6 @@ target_include_directories (CORSIKAlogging INTERFACE $<BUILD_INTERFACE:${PROJECT
$<INSTALL_INTERFACE:include/Framework>
)
install (FILES Logger.h
install (FILES Logger.h Sink.h MessageOn.h MessageOff.h NoSink.h Sink.h BufferedSink.h
DESTINATION include/Logging)
#ifndef _include_logger_h_
#define _include_logger_h_
#include <iosfwd>
#include <string>
#include <sstream>
#include <iostream>
#include <typeinfo>
#include <fstream>
#include <boost/format.hpp>
using namespace std;
using namespace boost;
class MessageOff {
protected:
template<typename First, typename ... Strings> std::string message(const First& arg, const Strings&... rest) {
return "";
}
};
class messageconst {
protected:
std::string message() { return "\n"; }
template<typename First, typename ... Strings> std::string message(const First& arg, const Strings&... rest) {
std::ostringstream ss;
ss << arg << message(rest...);
return ss.str();
}
template<typename ... Strings> std::string message(const int& arg, const Strings&... rest) {
return std::to_string(arg) + message(rest...);
}
template<typename ... Strings> std::string message(const double& arg, const Strings&... rest) {
return std::to_string(arg) + message(rest...);
}
template<typename ... Strings> std::string message(char const * arg, const Strings&... rest) {
return std::string(arg) + message(rest...);
}
template<typename ... Strings> std::string message(const std::string& arg, const Strings&... rest) {
return arg + message(rest...);
}
// ----------------------
// boost format
template<typename ... Strings> std::string message(const boost::format& fmt, const Strings&... rest) {
boost::format FMT(fmt);
return bformat(FMT, rest...);
}
template<typename Arg, typename ... Strings> std::string bformat(boost::format& fmt, const Arg& arg, const Strings&... rest) {
fmt % arg;
return bformat(fmt, rest...);
}
std::string bformat(boost::format& fmt) { return fmt.str() + "\n"; }
};
struct NoBuffer {
inline bool Test(const std::string&) const { return false; }
inline std::string GetString() const { return std::string(""); }
inline void Clear() {}
inline void Add(const std::string&) {}
};
struct StdBuffer {
StdBuffer(const int size) : fSize(size) {}
inline bool Test(const std::string& s) { return int(fBuffer.tellp())+s.length() < fSize; }
inline std::string GetString() const { return fBuffer.str(); }
inline void Clear() { fBuffer.str(""); }
inline void Add(const std::string& s) { fBuffer << s; }
private:
int fSize;
std::ostringstream fBuffer;
};
template<typename TStream, typename TBuffer=StdBuffer>
class Sink {
public:
Sink(TStream& out, TBuffer buffer = {} ) : fOutput(out), fBuffer(std::move(buffer)) {}
void operator<<(const std::string& msg) {
if (!fBuffer.Test(msg)) {
fOutput << fBuffer.GetString();
fBuffer.Clear();
}
if (!fBuffer.Test(msg))
fOutput << msg;
else
fBuffer.Add(msg);
}
void Close() { fOutput << fBuffer.GetString(); }
private:
TStream& fOutput;
TBuffer fBuffer;
};
#include <Logging/MessageOn.h>
#include <Logging/MessageOff.h>
#include <Logging/Sink.h>
#include <Logging/NoSink.h>
#include <Logging/BufferedSink.h>
struct NoSink { inline void operator<<(const std::string&) {} inline void Close() {} };
using namespace std;
using namespace boost;
template<typename TSink=NoSink,typename M=messageconst>
class logger : private M {
using M::message;
/**
Everything around logfile generation and text output.
*/
public:
// logger() : fName("") {}
logger(const std::string color, const std::string name, TSink& sink) : fSink(sink), fName(color+"["+name+"]\033[39m ") {}
~logger() { fSink.Close(); }
namespace logger {
// logger(const logger&) = delete;
template<typename ... Strings>
void log(const Strings&... inputs) {
fSink << M::message(inputs...);
}
const std::string& GetName() const { return fName; }
private:
TSink& fSink;
std::string fName;
};
#define LOG(__LOGGER,...) \
__LOGGER.log(__LOGGER.GetName(), __FILE__,":", __LINE__, " (", __func__, ") -> ", ##__VA_ARGS__);
/**
Defines one stream to accept messages, and to wrote those into
TSink. The helper class MessageOn will convert input at
compile-time into message strings. The helper class MessageOff,
will just do nothing and will be optimized away at compile time.
*/
template<typename MSG=MessageOn, typename TSink=sink::NoSink>
class Logger : private MSG {
using MSG::Message;
public:
// Logger() : fName("") {}
Logger(const std::string color, const std::string name, TSink& sink) : fSink(sink), fName(color+"["+name+"]\033[39m ") {}
~Logger() { fSink.Close(); }
// Logger(const Logger&) = delete;
/**
Function to add string-concatenation of all inputs to output
sink.
*/
template<typename ... Strings>
void Log(const Strings&... inputs) {
fSink << MSG::Message(inputs...);
}
const std::string& GetName() const { return fName; }
private:
TSink& fSink;
std::string fName;
};
} // end namesapce
#define LOG(__LOGGER,...) \
__LOGGER.Log(__LOGGER.GetName(), __FILE__,":", __LINE__, " (", __func__, ") -> ", ##__VA_ARGS__);
#endif
#ifndef _include_MessageOff_h_
#define _include_MessageOff_h_
namespace logger {
/**
Helper class to ignore all arguments to MessagesOn::Message and
always return empty string "".
*/
class MessageOff {
protected:
template<typename First, typename ... Strings> std::string Message(const First& arg, const Strings&... rest) {
return "";
}
};
} // end namespace
#endif
#ifndef _include_MessageOn_h_
#define _include_MessageOn_h_
namespace logger {
/**
Helper class to convert all input arguments of MessageOn::Message
into string-concatenated version and return this as string.
*/
class MessageOn {
protected:
std::string Message() { return "\n"; }
template<typename First, typename ... Strings> std::string Message(const First& arg, const Strings&... rest) {
std::ostringstream ss;
ss << arg << Message(rest...);
return ss.str();
}
template<typename ... Strings> std::string Message(const int& arg, const Strings&... rest) {
return std::to_string(arg) + Message(rest...);
}
template<typename ... Strings> std::string Message(const double& arg, const Strings&... rest) {
return std::to_string(arg) + Message(rest...);
}
template<typename ... Strings> std::string Message(char const * arg, const Strings&... rest) {
return std::string(arg) + Message(rest...);
}
template<typename ... Strings> std::string Message(const std::string& arg, const Strings&... rest) {
return arg + Message(rest...);
}
// ----------------------
// boost format
template<typename ... Strings> std::string Message(const boost::format& fmt, const Strings&... rest) {
boost::format FMT(fmt);
return bformat(FMT, rest...);
}
template<typename Arg, typename ... Strings> std::string bformat(boost::format& fmt, const Arg& arg, const Strings&... rest) {
fmt % arg;
return bformat(fmt, rest...);
}
std::string bformat(boost::format& fmt) { return fmt.str() + "\n"; }
};
}// end namesapce
#endif
#ifndef _include_NoSink_h_
#define _include_NoSink_h_
namespace logger {
namespace sink {
struct NoSink {
inline void operator<<(const std::string&) {}
inline void Close() {}
};
}// end namespace
} // end namespace
#endif
#ifndef _include_Sink_h_
#define _include_Sink_h_
namespace logger {
/**
a sink for the logger must implement the two functions
operator<<(const std::string&)
and
Close()
See example: NoSink
*/
namespace sink {
/**
Definition of Sink for log output.
*/
template<typename TStream>
class Sink {
public:
Sink(TStream& out) : fOutput(out) {}
void operator<<(const std::string& msg) {
fOutput << msg;
}
void Close() {}
private:
TStream& fOutput;
};
typedef Sink<std::ostream> SinkStream;
}// end namespace
} // end namespace
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment