#include "ofLog.h"
#include "ofConstants.h"
#include <ofUtils.h>
#include <map>
#include <cstdarg>
#ifdef TARGET_ANDROID
#include "ofxAndroidLogChannel.h"
#endif
using namespace std;
static ofLogLevel currentLogLevel = OF_LOG_NOTICE;
bool ofLog::bAutoSpace = false;
string & ofLog::getPadding() {
static string * padding = new string;
return *padding;
}
static map<string,ofLogLevel> & getModules(){
static map<string,ofLogLevel> * modules = new map<string,ofLogLevel>;
return *modules;
}
static void noopDeleter(ofBaseLoggerChannel*){}
shared_ptr<ofBaseLoggerChannel> & ofLog::channel(){
#ifdef TARGET_ANDROID
static shared_ptr<ofBaseLoggerChannel> channel = shared_ptr<ofxAndroidLogChannel>(new ofxAndroidLogChannel, std::function<void(ofBaseLoggerChannel *)>(noopDeleter));
#elif defined(TARGET_WIN32)
static shared_ptr<ofBaseLoggerChannel> channel = IsDebuggerPresent() ? shared_ptr<ofBaseLoggerChannel>(new ofDebugViewLoggerChannel, std::function<void(ofBaseLoggerChannel *)>(noopDeleter)) : shared_ptr<ofBaseLoggerChannel>(new ofConsoleLoggerChannel, std::function<void(ofBaseLoggerChannel *)>(noopDeleter));
#else
static shared_ptr<ofBaseLoggerChannel> channel = shared_ptr<ofConsoleLoggerChannel>(new ofConsoleLoggerChannel, std::function<void(ofBaseLoggerChannel *)>(noopDeleter));
#endif
return channel;
}
void ofSetLogLevel(ofLogLevel level){
currentLogLevel = level;
}
void ofSetLogLevel(string module, ofLogLevel level){
getModules()[module] = level;
}
ofLogLevel ofGetLogLevel(){
return currentLogLevel;
}
ofLogLevel ofGetLogLevel(string module){
if (getModules().find(module) == getModules().end()) {
return currentLogLevel;
} else {
return getModules()[module];
}
}
void ofLogToFile(const std::filesystem::path & path, bool append){
ofLog::setChannel(std::make_shared<ofFileLoggerChannel>(path,append));
}
void ofLogToConsole(){
ofLog::setChannel(shared_ptr<ofConsoleLoggerChannel>(new ofConsoleLoggerChannel, std::function<void(ofBaseLoggerChannel *)>(noopDeleter)));
}
#ifdef TARGET_WIN32
void ofLogToDebugView() {
ofLog::setChannel(shared_ptr<ofDebugViewLoggerChannel>(new ofDebugViewLoggerChannel, std::function<void(ofBaseLoggerChannel *)>(noopDeleter)));
}
#endif
ofLog::ofLog(){
level = OF_LOG_NOTICE;
module = "";
bPrinted = false;
}
ofLog::ofLog(ofLogLevel _level){
level = _level;
module = "";
bPrinted = false;
}
ofLog::ofLog(ofLogLevel level, const string & message){
_log(level,"",message);
bPrinted = true;
}
ofLog::ofLog(ofLogLevel level, const char* format, ...){
if(checkLog(level,"")){
va_list args;
va_start( args, format );
channel()->log(level,"",format,args);
va_end( args );
}
bPrinted = true;
}
void ofLog::setAutoSpace(bool autoSpace){
bAutoSpace = autoSpace;
if(bAutoSpace){
ofLog::getPadding() = " ";
}
else{
ofLog::getPadding() = "";
}
}
ofLog::~ofLog(){
if(!bPrinted){
_log(level,module,message.str());
}
}
bool ofLog::checkLog(ofLogLevel level, const string & module){
if(getModules().find(module)==getModules().end()){
if(level >= currentLogLevel) return true;
}else{
if(level >= getModules()[module]) return true;
}
return false;
}
void ofLog::_log(ofLogLevel level, const string & module, const string & message){
if(checkLog(level,module)){
channel()->log(level,module, message);
}
}
ofLogVerbose::ofLogVerbose(const string & _module){
level = OF_LOG_VERBOSE;
module = _module;
bPrinted=false;
}
ofLogVerbose::ofLogVerbose(const string & _module, const string & _message){
_log(OF_LOG_VERBOSE,_module,_message);
bPrinted = true;
}
ofLogVerbose::ofLogVerbose(const string & module, const char* format, ...){
if(checkLog(OF_LOG_VERBOSE, module)){
va_list args;
va_start(args, format);
channel()->log(OF_LOG_VERBOSE, module, format, args);
va_end(args);
}
bPrinted = true;
}
ofLogNotice::ofLogNotice(const string & _module){
level = OF_LOG_NOTICE;
module = _module;
bPrinted=false;
}
ofLogNotice::ofLogNotice(const string & _module, const string & _message){
_log(OF_LOG_NOTICE,_module,_message);
bPrinted = true;
}
ofLogNotice::ofLogNotice(const string & module, const char* format, ...){
if(checkLog(OF_LOG_NOTICE, module)){
va_list args;
va_start(args, format);
channel()->log(OF_LOG_NOTICE, module, format, args);
va_end(args);
}
bPrinted = true;
}
ofLogWarning::ofLogWarning(const string & _module){
level = OF_LOG_WARNING;
module = _module;
bPrinted=false;
}
ofLogWarning::ofLogWarning(const string & _module, const string & _message){
_log(OF_LOG_WARNING,_module,_message);
bPrinted = true;
}
ofLogWarning::ofLogWarning(const string & module, const char* format, ...){
if(checkLog(OF_LOG_WARNING, module)){
va_list args;
va_start(args, format);
channel()->log(OF_LOG_WARNING, module, format, args);
va_end(args);
}
bPrinted = true;
}
ofLogError::ofLogError(const string & _module){
level = OF_LOG_ERROR;
module = _module;
bPrinted=false;
}
ofLogError::ofLogError(const string & _module, const string & _message){
_log(OF_LOG_ERROR,_module,_message);
bPrinted = true;
}
ofLogError::ofLogError(const string & module, const char* format, ...){
if(checkLog(OF_LOG_ERROR, module)){
va_list args;
va_start(args, format);
channel()->log(OF_LOG_ERROR, module, format, args);
va_end(args);
}
bPrinted = true;
}
ofLogFatalError::ofLogFatalError(const string & _module){
level = OF_LOG_FATAL_ERROR;
module = _module;
bPrinted=false;
}
ofLogFatalError::ofLogFatalError(const string & _module, const string & _message){
_log(OF_LOG_FATAL_ERROR,_module,_message);
bPrinted = true;
}
ofLogFatalError::ofLogFatalError(const string & module, const char* format, ...){
if(checkLog(OF_LOG_FATAL_ERROR, module)){
va_list args;
va_start(args, format);
channel()->log(OF_LOG_FATAL_ERROR, module, format, args);
va_end(args);
}
bPrinted = true;
}
void ofLog::setChannel(shared_ptr<ofBaseLoggerChannel> _channel){
channel() = _channel;
}
void ofSetLoggerChannel(shared_ptr<ofBaseLoggerChannel> loggerChannel){
ofLog::setChannel(loggerChannel);
}
shared_ptr<ofBaseLoggerChannel> ofLog::getChannel(){
return channel();
}
shared_ptr<ofBaseLoggerChannel> ofGetLoggerChannel(){
return ofLog::getChannel();
}
string ofGetLogLevelName(ofLogLevel level, bool pad){
switch(level){
case OF_LOG_VERBOSE:
return "verbose";
case OF_LOG_NOTICE:
return pad ? "notice " : "notice";
case OF_LOG_WARNING:
return "warning";
case OF_LOG_ERROR:
return pad ? " error " : "error";
case OF_LOG_FATAL_ERROR:
return pad ? " fatal " : "fatal";
case OF_LOG_SILENT:
return pad ? "silent " : "silent";
default:
return "";
}
}
void ofConsoleLoggerChannel::log(ofLogLevel level, const string & module, const string & message){
ostream& out = level < OF_LOG_ERROR ? cout : cerr;
out << "[" << ofGetLogLevelName(level, true) << "] ";
if(module != ""){
out << module << ": ";
}
out << message << endl;
}
void ofConsoleLoggerChannel::log(ofLogLevel level, const string & module, const char* format, ...){
va_list args;
va_start(args, format);
log(level, module, format, args);
va_end(args);
}
void ofConsoleLoggerChannel::log(ofLogLevel level, const string & module, const char* format, va_list args){
FILE* out = level < OF_LOG_ERROR ? stdout : stderr;
fprintf(out, "[%s] ", ofGetLogLevelName(level, true).c_str());
if(module != ""){
fprintf(out, "%s: ", module.c_str());
}
vfprintf(out, format, args);
fprintf(out, "\n");
}
#ifdef TARGET_WIN32
#include <array>
void ofDebugViewLoggerChannel::log(ofLogLevel level, const string & module, const string & message) {
stringstream out;
out << "[" << ofGetLogLevelName(level, true) << "] ";
if (module != "") {
out << module << ": ";
}
out << message << endl;
OutputDebugStringA(out.str().c_str());
}
void ofDebugViewLoggerChannel::log(ofLogLevel level, const string & module, const char* format, ...) {
va_list args;
va_start(args, format);
log(level, module, format, args);
va_end(args);
}
void ofDebugViewLoggerChannel::log(ofLogLevel level, const string & module, const char* format, va_list args) {
std::string buffer;;
buffer = "[" + ofGetLogLevelName(level, true) + "] ";
if (module != "") {
buffer += module + ": ";
}
buffer += ofVAArgsToString(format, args);
buffer += "\n";
OutputDebugStringA(buffer.c_str());
}
#endif
ofFileLoggerChannel::ofFileLoggerChannel(){
}
ofFileLoggerChannel::ofFileLoggerChannel(const std::filesystem::path & path, bool append){
setFile(path,append);
}
ofFileLoggerChannel::~ofFileLoggerChannel(){
close();
}
void ofFileLoggerChannel::close(){
file.close();
}
void ofFileLoggerChannel::setFile(const std::filesystem::path & path,bool append){
file.open(path,append?ofFile::Append:ofFile::WriteOnly);
file << endl;
file << endl;
file << "--------------------------------------- " << ofGetTimestampString() << endl;
}
void ofFileLoggerChannel::log(ofLogLevel level, const string & module, const string & message){
file << "[" << ofGetLogLevelName(level, true) << "] ";
if(module != ""){
file << module << ": ";
}
file << message << endl;
}
void ofFileLoggerChannel::log(ofLogLevel level, const string & module, const char* format, ...){
va_list args;
va_start(args, format);
log(level, module, format, args);
va_end(args);
}
void ofFileLoggerChannel::log(ofLogLevel level, const string & module, const char* format, va_list args){
file << "[" << ofGetLogLevelName(level, true) << "] ";
if(module != ""){
file << module << ": ";
}
file << ofVAArgsToString(format,args) << endl;
}
Comments