// $Id: logkit.cpp 1127 2012-12-04 12:54:33Z ulvmoen $ // Copyright (c) 2011, Norwegian Computing Center // All rights reserved. // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // • Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // • Redistributions in binary form must reproduce the above copyright notice, this list of // conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT // SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include #include "logkit.hpp" #include "../exception/exception.hpp" using namespace NRLib; std::vector LogKit::logstreams_(0); int LogKit::screenLog_ = -1; std::vector * LogKit::buffer_ = NULL; // Making a long table to allow direct access. std::vector LogKit::n_messages_(65, 0); std::vector LogKit::prefix_(65, ""); void LogKit::SetFileLog(const std::string & fileName, int levels, bool includeNRLibLogging) { std::ofstream * file = new std::ofstream(fileName.c_str()); if (!(*file)) { //NBNB-PAL: Tmp fix pfga. manglende feilhåndtering (catch) delete file; printf("Could not open file %s\n",fileName.c_str()); throw IOError("Error opening " + fileName); } LogStream * curStream; if (includeNRLibLogging == true) curStream = new LogStream(file, levels); else { std::vector phaseLevels; phaseLevels.push_back(0); //No logging in NRLib, phase 0. phaseLevels.push_back(levels); //This will be used for all other phases. curStream = new LogStream(file, phaseLevels); } logstreams_.push_back(curStream); DumpBuffer(curStream); } void LogKit::SetFileLog(const std::string & fileName, const std::vector & levels, bool ignore_general) { std::ofstream * file = new std::ofstream(fileName.c_str()); if (!(*file)) { delete file; throw IOError("Error opening " + fileName); } LogStream * curStream = new LogStream(file, levels, ignore_general); logstreams_.push_back(curStream); DumpBuffer(curStream); } void LogKit::SetFileLog(const std::string & fileName, int levels, int phase, bool ignore_general) { std::ofstream * file = new std::ofstream(fileName.c_str()); if (!(*file)) { delete file; throw IOError("Error opening " + fileName); } std::vector phaseLevels(1000,0); phaseLevels[phase] = levels; LogStream * curStream = new LogStream(file, phaseLevels, ignore_general); logstreams_.push_back(curStream); DumpBuffer(curStream); } void LogKit::SetScreenLog(int levels, bool includeNRLibLogging) { LogStream * curStream; if (includeNRLibLogging == true) curStream = new LogStream(NULL, levels); else { std::vector phaseLevels; phaseLevels.push_back(0); //No logging in NRLib, phase 0. phaseLevels.push_back(levels); //This will be used for all other phases. curStream = new LogStream(NULL, phaseLevels); } if (screenLog_ < 0) { screenLog_ = static_cast(logstreams_.size()); logstreams_.push_back(curStream); } else { delete logstreams_[screenLog_]; logstreams_[screenLog_] = curStream; } } void LogKit::SetScreenLog(const std::vector & levels, bool ignore_general) { LogStream * curStream = new LogStream(NULL, levels, ignore_general); if (screenLog_ < 0) { screenLog_ = static_cast(logstreams_.size()); logstreams_.push_back(curStream); } else { delete logstreams_[screenLog_]; logstreams_[screenLog_] = curStream; } } void LogKit::LogMessage(int level, const std::string & message) { unsigned int i; n_messages_[level]++; std::string new_message = prefix_[level] + message; for (i=0;iLogMessage(level, new_message); SendToBuffer(level,-1,new_message); } void LogKit::LogMessage(int level, int phase, const std::string & message) { unsigned int i; n_messages_[level]++; std::string new_message = prefix_[level] + message; for (i=0;iLogMessage(level, phase, new_message); SendToBuffer(level,phase,new_message); } void LogKit::LogFormatted(int level, std::string format, ...) { va_list ap; char message[5000]; va_start(ap, format); vsprintf(message, format.c_str(), ap); va_end(ap); LogMessage(level, std::string(message)); } void LogKit::LogFormatted(int level, int phase, std::string format, ...) { va_list ap; char message[1000]; va_start(ap, format); vsprintf(message, format.c_str(), ap); va_end(ap); LogMessage(level, phase, std::string(message)); } void LogKit::EndLog() { unsigned int i; for (i=0;i; } void LogKit::EndBuffering() { if (buffer_ != NULL) { for (unsigned int i=0;isize();i++) { delete (*buffer_)[i]; (*buffer_)[i] = NULL; } delete buffer_; buffer_ = NULL; } } void LogKit::SendToBuffer(int level, int phase, const std::string & message) { if (buffer_ != NULL) { BufferMessage * bm = new BufferMessage; bm->level_ = level; bm->phase_ = phase; bm->text_ = message; buffer_->push_back(bm); } } void LogKit::DumpBuffer(LogStream *logstream) { if (buffer_ != NULL) { for (unsigned int i=0;isize();i++) { if ((*buffer_)[i]->phase_ < 0) logstream->LogMessage((*buffer_)[i]->level_, (*buffer_)[i]->text_); else logstream->LogMessage((*buffer_)[i]->level_, (*buffer_)[i]->phase_, (*buffer_)[i]->text_); } } } void LogKit::SetPrefix(const std::string & prefix, int level) { prefix_[level] = prefix; } void LogKit::WriteHeader(const std::string & text, MessageLevels logLevel) { int width = 100; // Total width of header std::string ruler(width,'*'); std::string stars("*****"); LogFormatted(logLevel,"\n"+ruler+"\n"); int starLength = int(stars.length()); int textLength = int(text.length()); int blankLength = width - textLength - 2*starLength; std::string blanks(blankLength/2,' '); std::string center; if(blankLength % 2) center = stars + blanks + text + blanks + " " + stars; else center = stars + blanks + text + blanks +stars; LogFormatted(logLevel,center+"\n"); LogFormatted(logLevel,ruler+"\n"); } LogStream::LogStream(std::ostream * logstream, int level) { fullLevel_ = level; if (logstream != NULL) { logstream_ = logstream; deleteStream = true; } else { logstream_ = &(std::cout); deleteStream = false; } } LogStream::LogStream(std::ostream * logstream, const std::vector & levels, bool ignore_general) { unsigned int i; fullLevel_ = 0; for (i=0;i 0) { *logstream_ << message; logstream_->flush(); } } void LogStream::LogMessage(int level, int phase, const std::string & message) { if (phase < static_cast(levels_.size())) { if ((level & levels_[phase]) > 0) { *logstream_ << message; logstream_->flush(); } } else if ((level & fullLevel_) > 0) { *logstream_ << message; logstream_->flush(); } }