mirror of
https://github.com/KjellKod/g3log.git
synced 2025-03-03 12:58:04 +01:00
Corrected the merging compile errors...
--HG-- rename : g2log/src/crashhandler.h => g2log/src/crashhandler.hpp rename : g2log/src/g2logmessage.h => g2log/src/g2logmessage.hpp rename : g2log/src/g2time.h => g2log/src/g2time.hpp
This commit is contained in:
parent
05018e389a
commit
ab07e5978d
@ -99,7 +99,7 @@ ENDIF(MSVC)
|
|||||||
|
|
||||||
|
|
||||||
# GENERIC STEPS
|
# GENERIC STEPS
|
||||||
file(GLOB SRC_FILES ${LOG_SRC}/*.h ${LOG_SRC}/*.hpp ${LOG_SRC}/*.cpp)
|
file(GLOB SRC_FILES ${LOG_SRC}/*.h ${LOG_SRC}/*.hpp ${LOG_SRC}/*.cpp ${LOG_SRC}/*.ipp)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
list(REMOVE_ITEM SRC_FILES ${LOG_SRC}/crashhandler_unix.cpp)
|
list(REMOVE_ITEM SRC_FILES ${LOG_SRC}/crashhandler_unix.cpp)
|
||||||
else()
|
else()
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* strings attached and no restrictions or obligations.
|
* strings attached and no restrictions or obligations.
|
||||||
* ============================================================================*/
|
* ============================================================================*/
|
||||||
|
|
||||||
#include "crashhandler.h"
|
#include "crashhandler.hpp"
|
||||||
#include "g2log.h"
|
#include "g2log.h"
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* strings attached and no restrictions or obligations.
|
* strings attached and no restrictions or obligations.
|
||||||
* ============================================================================*/
|
* ============================================================================*/
|
||||||
|
|
||||||
#include "crashhandler.h"
|
#include "crashhandler.hpp"
|
||||||
#include "g2log.h"
|
#include "g2log.h"
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
99
g2log/src/g2filesink.cpp
Normal file
99
g2log/src/g2filesink.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "g2filesink.hpp"
|
||||||
|
#include "g2filesinkhelper.ipp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace g2 {
|
||||||
|
using namespace internal;
|
||||||
|
|
||||||
|
g2FileSink::g2FileSink(const std::string& log_prefix, const std::string& log_directory)
|
||||||
|
: _log_file_with_path(log_directory)
|
||||||
|
, _log_prefix_backup(log_prefix)
|
||||||
|
, _outptr(new std::ofstream)
|
||||||
|
, _steady_start_time(std::chrono::steady_clock::now()) // TODO: ha en timer function steadyTimer som har koll på start
|
||||||
|
{
|
||||||
|
_log_prefix_backup = prefixSanityFix(log_prefix);
|
||||||
|
if (!isValidFilename(_log_prefix_backup)) {
|
||||||
|
std::cerr << "g2log: forced abort due to illegal log prefix [" << log_prefix << "]" << std::endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string file_name = createLogFileName(_log_prefix_backup);
|
||||||
|
_log_file_with_path = pathSanityFix(_log_file_with_path, file_name);
|
||||||
|
_outptr = createLogFile(_log_file_with_path);
|
||||||
|
|
||||||
|
if (!_outptr) {
|
||||||
|
std::cerr << "Cannot write log file to location, attempting current directory" << std::endl;
|
||||||
|
_log_file_with_path = file_name;
|
||||||
|
_outptr = createLogFile(_log_file_with_path);
|
||||||
|
}
|
||||||
|
assert(_outptr && "cannot open log file at startup");
|
||||||
|
addLogFileHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
g2FileSink::~g2FileSink() {
|
||||||
|
|
||||||
|
std::ostringstream ss_exit;
|
||||||
|
ss_exit << "\n\t\tg2log g2FileSink shutdown at: " << localtime_formatted(systemtime_now(), internal::time_formatted);
|
||||||
|
filestream() << ss_exit.str() << std::flush;
|
||||||
|
ss_exit << "\nLog file at: [" << _log_file_with_path << "]\n" << std::endl;
|
||||||
|
std::cerr << ss_exit << std::flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
void g2FileSink::fileWrite(internal::LogEntry message) {
|
||||||
|
std::ofstream & out(filestream());
|
||||||
|
auto system_time = systemtime_now();
|
||||||
|
auto steady_time = std::chrono::steady_clock::now();
|
||||||
|
out << "\n" << localtime_formatted(system_time, date_formatted);
|
||||||
|
out << " " << localtime_formatted(system_time, time_formatted); // TODO: time kommer från LogEntry
|
||||||
|
out << "." << std::chrono::duration_cast<std::chrono::microseconds>(steady_time - _steady_start_time).count();
|
||||||
|
out << "\t" << message << std::flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void g2FileSink::backgroundExitFatal(internal::FatalMessage fatal_message) {
|
||||||
|
//
|
||||||
|
// backgroundFileWrite(fatal_message.message_);
|
||||||
|
// backgroundFileWrite("Log flushed successfully to disk \nExiting");
|
||||||
|
// std::cerr << "g2log exiting after receiving fatal event" << std::endl;
|
||||||
|
// std::cerr << "Log file at: [" << log_file_with_path_ << "]\n" << std::endl << std::flush;
|
||||||
|
// filestream().close();
|
||||||
|
// exitWithDefaultSignalHandler(fatal_message.signal_id_);
|
||||||
|
// perror("g2log exited after receiving FATAL trigger. Flush message status: "); // should never reach this point
|
||||||
|
// }
|
||||||
|
|
||||||
|
std::string g2FileSink::changeLogFile(const std::string& directory) {
|
||||||
|
std::string file_name = createLogFileName(_log_prefix_backup);
|
||||||
|
std::string prospect_log = directory + file_name;
|
||||||
|
std::unique_ptr<std::ofstream> log_stream = createLogFile(prospect_log);
|
||||||
|
if (nullptr == log_stream) {
|
||||||
|
fileWrite("Unable to change log file. Illegal filename or busy? Unsuccessful log name was:" + prospect_log);
|
||||||
|
return ""; // no success
|
||||||
|
}
|
||||||
|
|
||||||
|
addLogFileHeader();
|
||||||
|
std::ostringstream ss_change;
|
||||||
|
ss_change << "\n\tChanging log file from : " << _log_file_with_path;
|
||||||
|
ss_change << "\n\tto new location: " << prospect_log << "\n";
|
||||||
|
fileWrite(ss_change.str().c_str());
|
||||||
|
ss_change.str("");
|
||||||
|
|
||||||
|
std::string old_log = _log_file_with_path;
|
||||||
|
_log_file_with_path = prospect_log;
|
||||||
|
_outptr = std::move(log_stream);
|
||||||
|
ss_change << "\n\tNew log file. The previous log file was at: ";
|
||||||
|
ss_change << old_log;
|
||||||
|
fileWrite(ss_change.str());
|
||||||
|
return _log_file_with_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string g2FileSink::fileName() {
|
||||||
|
return _log_file_with_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void g2FileSink::addLogFileHeader() {
|
||||||
|
filestream() << header();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // g2
|
64
g2log/src/g2filesink.hpp
Normal file
64
g2log/src/g2filesink.hpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef PRIVATE_G2_FILE_SINK_H_
|
||||||
|
#define PRIVATE_G2_FILE_SINK_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//struct g2FileSink {
|
||||||
|
// g2FileSink(const std::string& log_prefix, const std::string& log_directory) {
|
||||||
|
// std::string lg = log_prefix;
|
||||||
|
// lg.append(": directory->");
|
||||||
|
// lg.append(log_directory);
|
||||||
|
// std::cout << lg << std::endl;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// template<typename Arg>
|
||||||
|
// void writeToFile(Arg arg) {
|
||||||
|
// std::cout << arg << std::endl;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// std::string logFileName() { return ""; }
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "g2logmessage.hpp" // TODO refactoring, should include message instead
|
||||||
|
#include "g2time.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace g2 {
|
||||||
|
|
||||||
|
struct g2FileSink {
|
||||||
|
g2FileSink(const std::string& log_prefix, const std::string& log_directory);
|
||||||
|
virtual ~g2FileSink();
|
||||||
|
|
||||||
|
void fileWrite(internal::LogEntry message);
|
||||||
|
std::string changeLogFile(const std::string& directory);
|
||||||
|
std::string fileName();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//void backgroundExitFatal(internal::FatalMessage fatal_message);
|
||||||
|
void addLogFileHeader();
|
||||||
|
|
||||||
|
std::string _log_file_with_path;
|
||||||
|
std::string _log_prefix_backup; // needed in case of future log file changes of directory
|
||||||
|
std::unique_ptr<std::ofstream> _outptr;
|
||||||
|
g2::steady_time_point _steady_start_time;
|
||||||
|
|
||||||
|
|
||||||
|
g2FileSink& operator=(const g2FileSink&); // c++11 feature not yet in vs2010 = delete;
|
||||||
|
g2FileSink(const g2FileSink& other); // c++11 feature not yet in vs2010 = delete;
|
||||||
|
|
||||||
|
std::ofstream & filestream() {
|
||||||
|
return *(_outptr.get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // g2
|
||||||
|
#endif // pimple
|
@ -27,7 +27,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "g2logworker.h"
|
#include "g2logworker.h"
|
||||||
#include "crashhandler.h"
|
#include "crashhandler.hpp"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include "g2logmessage.h"
|
#include "g2logmessage.hpp"
|
||||||
|
|
||||||
|
|
||||||
class g2LogWorker;
|
class g2LogWorker;
|
||||||
|
@ -1,98 +1,109 @@
|
|||||||
/** ==========================================================================
|
/** ==========================================================================
|
||||||
* 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
* 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
||||||
* with no warranties. This code is yours to share, use and modify with no
|
* with no warranties. This code is yours to share, use and modify with no
|
||||||
* strings attached and no restrictions or obligations.
|
* strings attached and no restrictions or obligations.
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
* Filename:g2LogWorker.cpp Framework for Logging and Design By Contract
|
* Filename:g2LogWorker.cpp Framework for Logging and Design By Contract
|
||||||
* Created: 2011 by Kjell Hedström
|
* Created: 2011 by Kjell Hedström
|
||||||
*
|
*
|
||||||
* PUBLIC DOMAIN and Not under copywrite protection. First published at KjellKod.cc
|
* PUBLIC DOMAIN and Not under copywrite protection. First published at KjellKod.cc
|
||||||
* ********************************************* */
|
* ********************************************* */
|
||||||
|
|
||||||
#include "g2logworker.h"
|
#include "g2logworker.h"
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <chrono>
|
|
||||||
#include <future>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "active.h"
|
#include "active.h"
|
||||||
#include "g2log.h"
|
#include "g2log.h"
|
||||||
#include "crashhandler.h"
|
#include "g2time.hpp"
|
||||||
#include "g2time.h"
|
|
||||||
#include "g2future.h"
|
#include "g2future.h"
|
||||||
#include "g2filesink.h"
|
#include "crashhandler.hpp"
|
||||||
#include "std2_make_unique.hpp"
|
|
||||||
|
|
||||||
using namespace g2;
|
using namespace g2;
|
||||||
using namespace g2::internal;
|
using namespace g2::internal;
|
||||||
|
|
||||||
struct g2LogWorkerImpl
|
struct g2LogWorkerImpl {
|
||||||
{
|
typedef std::shared_ptr<g2::internal::SinkWrapper> SinkWrapperPtr;
|
||||||
typedef std::shared_ptr<g2::internal::SinkWrapper> SinkWrapperPtr;
|
|
||||||
|
|
||||||
g2LogWorkerImpl(){}
|
|
||||||
~g2LogWorkerImpl(){ _bg.reset(); _sinks.clear(); }
|
|
||||||
|
|
||||||
std::unique_ptr<kjellkod::Active> _bg;
|
std::unique_ptr<kjellkod::Active> _bg;
|
||||||
std::vector<SinkWrapperPtr> _sinks;
|
std::vector<SinkWrapperPtr> _sinks;
|
||||||
std::shared_ptr<g2::SinkHandle<g2FileSink>> _default_sink_handle;
|
|
||||||
|
g2LogWorkerImpl() : _bg(kjellkod::Active::createActive()) { }
|
||||||
|
|
||||||
|
~g2LogWorkerImpl() {
|
||||||
|
_bg.reset();
|
||||||
|
_sinks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void bgSave(g2::internal::LogEntry msg) {
|
void bgSave(g2::internal::LogEntry msg) {
|
||||||
for(auto& sink : _sinks) {
|
for (auto& sink : _sinks) {
|
||||||
sink->send(msg);
|
sink->send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_sinks.empty()) {
|
||||||
|
std::ostringstream err_msg;
|
||||||
|
err_msg << "g2logworker has no sinks. Message: [" << msg << "]" << std::endl;
|
||||||
|
std::cerr << err_msg.str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bgFatal(g2::internal::FatalMessage fatal_message){
|
void bgFatal(g2::internal::FatalMessage fatal_message) {
|
||||||
auto entry = fatal_message.message_;
|
auto entry = fatal_message.message_;
|
||||||
bgSave(entry);
|
bgSave(entry);
|
||||||
|
std::ostringstream end_message;
|
||||||
|
end_message << "Exiting after fatal event. Log flushed sucessfully t disk.\n";
|
||||||
|
bgSave(end_message.str());
|
||||||
|
std::cerr << "g2log sinks are flushed. Now exiting after receiving fatal event" << std::endl;
|
||||||
|
|
||||||
_sinks.clear(); // flush all queues
|
_sinks.clear(); // flush all queues
|
||||||
exitWithDefaultSignalHandler(fatal_message.signal_id_);
|
exitWithDefaultSignalHandler(fatal_message.signal_id_);
|
||||||
|
|
||||||
|
// should never reach this point
|
||||||
|
perror("g2log exited after receiving FATAL trigger. Flush message status: ");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Default constructor will have one sink: g2filesink.
|
// Default constructor will have one sink: g2filesink.
|
||||||
g2LogWorker::g2LogWorker(const std::string& log_prefix, const std::string& log_directory)
|
|
||||||
: _pimpl(std2::make_unique<g2LogWorkerImpl>())
|
|
||||||
{
|
|
||||||
// auto unique = std::unique_ptr<g2FileSink>(new g2FileSink(log_prefix, log_directory));
|
|
||||||
// auto handle = addSink<g2FileSink>(std::move(unique), &g2FileSink::writeToFile);
|
|
||||||
// _pimpl._file_handle.reset(handle.release());
|
|
||||||
}
|
|
||||||
|
|
||||||
g2LogWorker::~g2LogWorker()
|
g2LogWorker::g2LogWorker()
|
||||||
{
|
: _pimpl(std2::make_unique<g2LogWorkerImpl>()) {
|
||||||
_pimpl.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void g2LogWorker::save(g2::internal::LogEntry msg)
|
g2LogWorker::~g2LogWorker() { _pimpl.reset(); }
|
||||||
{
|
|
||||||
_pimpl->_bg->send([this, msg]{ _pimpl->bgSave(msg); });
|
void g2LogWorker::save(g2::internal::LogEntry msg) {
|
||||||
//std::bind(&g2LogWorkerImpl::backgroundFileWrite, _pimpl.get(), msg));
|
_pimpl->_bg->send([this, msg] { _pimpl->bgSave(msg); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void g2LogWorker::fatal(g2::internal::FatalMessage fatal_message)
|
void g2LogWorker::fatal(g2::internal::FatalMessage fatal_message) {
|
||||||
{
|
_pimpl->_bg->send([this, fatal_message] {_pimpl->bgFatal(fatal_message); });
|
||||||
_pimpl->_bg->send([this, fatal_message]{ _pimpl->bgFatal(fatal_message); });
|
//OR: td::bind(&g2LogWorkerImpl::backgroundExitFatal, _pimpl.get(), fatal_message));
|
||||||
//std::bind(&g2LogWorkerImpl::backgroundExitFatal, _pimpl.get(), fatal_message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void g2LogWorker::addWrappedSink(std::shared_ptr<g2::internal::SinkWrapper> sink) {
|
void g2LogWorker::addWrappedSink(std::shared_ptr<g2::internal::SinkWrapper> sink) {
|
||||||
auto bg_addsink_call = [this, sink] { _pimpl->_sinks.push_back(sink); };
|
auto bg_addsink_call = [this, sink] { _pimpl->_sinks.push_back(sink); };
|
||||||
auto token_done = g2::spawn_task(bg_addsink_call, _pimpl->_bg.get());
|
auto token_done = g2::spawn_task(bg_addsink_call, _pimpl->_bg.get());
|
||||||
token_done.wait();
|
token_done.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<g2::SinkHandle<g2FileSink>> g2LogWorker::getFileSinkHandle()
|
g2LogWorker::DefaultWorkerPair g2LogWorker::createWithDefaultFileSink(const std::string& log_prefix, const std::string& log_directory)
|
||||||
{
|
{
|
||||||
return _pimpl->_default_sink_handle;
|
auto logger = g2LogWorker::createWithNoSink();
|
||||||
|
auto handle = logger->addSink(std2::make_unique<g2::g2FileSink>(log_prefix, log_directory), &g2FileSink::fileWrite);
|
||||||
|
|
||||||
|
auto pair = std::pair<std::unique_ptr<g2LogWorker>, std::unique_ptr<g2::SinkHandle<g2FileSink>> >(std::move(logger), std::move(handle));
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<g2LogWorker> g2LogWorker::createWithNoSink()
|
||||||
|
{
|
||||||
|
std::unique_ptr<g2LogWorker> logger(new g2LogWorker());
|
||||||
|
return logger;
|
||||||
}
|
}
|
@ -1,39 +1,47 @@
|
|||||||
#ifndef G2_LOG_WORKER_H_
|
#ifndef G2_LOG_WORKER_H_
|
||||||
#define G2_LOG_WORKER_H_
|
#define G2_LOG_WORKER_H_
|
||||||
/** ==========================================================================
|
/** ==========================================================================
|
||||||
* 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
* 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
||||||
* with no warranties. This code is yours to share, use and modify with no
|
* with no warranties. This code is yours to share, use and modify with no
|
||||||
* strings attached and no restrictions or obligations.
|
* strings attached and no restrictions or obligations.
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
* Filename:g2logworker.h Framework for Logging and Design By Contract
|
* Filename:g2logworker.h Framework for Logging and Design By Contract
|
||||||
* Created: 2011 by Kjell Hedström
|
* Created: 2011 by Kjell Hedström
|
||||||
*
|
*
|
||||||
* PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
|
* PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
|
||||||
* ********************************************* */
|
* ********************************************* */
|
||||||
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "std2_make_unique.hpp"
|
#include <utility>
|
||||||
|
|
||||||
#include "g2log.h"
|
#include "g2log.h"
|
||||||
#include "g2sinkwrapper.h"
|
#include "g2sinkwrapper.h"
|
||||||
#include "g2sinkhandle.h"
|
#include "g2sinkhandle.h"
|
||||||
|
#include "g2filesink.hpp"
|
||||||
|
#include "std2_make_unique.hpp"
|
||||||
|
|
||||||
struct g2LogWorkerImpl;
|
struct g2LogWorkerImpl;
|
||||||
struct g2FileSink;
|
|
||||||
|
|
||||||
/**
|
class g2LogWorker {
|
||||||
* \param log_prefix is the 'name' of the binary, this give the log name 'LOG-'name'-...
|
g2LogWorker(); // Create only through factory
|
||||||
* \param log_directory gives the directory to put the log files */
|
void addWrappedSink(std::shared_ptr<g2::internal::SinkWrapper> wrapper);
|
||||||
class g2LogWorker
|
|
||||||
{
|
std::unique_ptr<g2LogWorkerImpl> _pimpl;
|
||||||
|
g2LogWorker(const g2LogWorker&); // c++11 feature not yet in vs2010 = delete;
|
||||||
|
g2LogWorker& operator=(const g2LogWorker&); // c++11 feature not yet in vs2010 = delete;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
g2LogWorker(const std::string& log_prefix, const std::string& log_directory);
|
|
||||||
virtual ~g2LogWorker();
|
virtual ~g2LogWorker();
|
||||||
|
typedef std::pair<std::unique_ptr<g2LogWorker>, std::unique_ptr<g2::SinkHandle<g2::g2FileSink>> > DefaultWorkerPair;
|
||||||
|
static DefaultWorkerPair createWithDefaultFileSink(const std::string& log_prefix, const std::string& log_directory);
|
||||||
|
static std::unique_ptr<g2LogWorker> createWithNoSink();
|
||||||
|
|
||||||
|
|
||||||
/// pushes in background thread (asynchronously) input messages to log file
|
/// pushes in background thread (asynchronously) input messages to log file
|
||||||
void save(g2::internal::LogEntry entry);
|
void save(g2::internal::LogEntry entry);
|
||||||
|
|
||||||
@ -43,35 +51,14 @@ public:
|
|||||||
void fatal(g2::internal::FatalMessage fatal_message);
|
void fatal(g2::internal::FatalMessage fatal_message);
|
||||||
|
|
||||||
template<typename T, typename DefaultLogCall>
|
template<typename T, typename DefaultLogCall>
|
||||||
std::unique_ptr<g2::SinkHandle<T>> addSink(std::unique_ptr<T> real_sink, DefaultLogCall call)
|
std::unique_ptr<g2::SinkHandle<T >> addSink(std::unique_ptr<T> real_sink, DefaultLogCall call) {
|
||||||
{
|
|
||||||
using namespace g2;
|
using namespace g2;
|
||||||
using namespace g2::internal;
|
using namespace g2::internal;
|
||||||
auto shared_sink = std::shared_ptr<T>(real_sink.release());
|
auto shared_sink = std::shared_ptr<T>(real_sink.release());
|
||||||
auto sink = std::make_shared<Sink<T>>(shared_sink, call);
|
auto sink = std::make_shared < Sink < T >> (shared_sink, call);
|
||||||
auto add_result = addWrappedSink(sink);
|
addWrappedSink(sink);
|
||||||
return std2::make_unique<SinkHandle<T>>(sink);
|
return std2::make_unique < SinkHandle < T >> (sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DEPRECATED - SHOULD BE Called through a sink handler instead
|
|
||||||
/// Attempt to change the current log file to another name/location.
|
|
||||||
/// returns filename with full path if successful, else empty string
|
|
||||||
//std::future<std::string> changeLogFile(const std::string& log_directory);
|
|
||||||
/// Probably only needed for unit-testing or specific log management post logging
|
|
||||||
/// request to get log name is processed in FIFO order just like any other background job.
|
|
||||||
//std::future<std::string> logFileName();
|
|
||||||
std::shared_ptr<g2::SinkHandle<g2FileSink>> getFileSinkHandle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addWrappedSink(std::shared_ptr<g2::internal::SinkWrapper> wrapper);
|
|
||||||
|
|
||||||
std::unique_ptr<g2LogWorkerImpl> _pimpl;
|
|
||||||
|
|
||||||
g2LogWorker(const g2LogWorker&); // c++11 feature not yet in vs2010 = delete;
|
|
||||||
g2LogWorker& operator=(const g2LogWorker&); // c++11 feature not yet in vs2010 = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#ifndef G2SINKWRAPPER_IPP
|
#ifndef G2SINKWRAPPER_IPP
|
||||||
#define G2SINKWRAPPER_IPP
|
#define G2SINKWRAPPER_IPP
|
||||||
|
|
||||||
#include "g2logmessage.h"
|
#include "g2logmessage.hpp"
|
||||||
|
|
||||||
namespace g2 {
|
namespace g2 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -1,79 +1,84 @@
|
|||||||
/** ==========================================================================
|
/** ==========================================================================
|
||||||
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
||||||
* with no warranties. This code is yours to share, use and modify with no
|
* with no warranties. This code is yours to share, use and modify with no
|
||||||
* strings attached and no restrictions or obligations.
|
* strings attached and no restrictions or obligations.
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
* Filename:g2time.cpp cross-platform, thread-safe replacement for C++11 non-thread-safe
|
* Filename:g2time.cpp cross-platform, thread-safe replacement for C++11 non-thread-safe
|
||||||
* localtime (and similar)
|
* localtime (and similar)
|
||||||
* Created: 2012 by Kjell Hedström
|
* Created: 2012 by Kjell Hedström
|
||||||
*
|
*
|
||||||
* PUBLIC DOMAIN and Not under copywrite protection. First published for g2log at KjellKod.cc
|
* PUBLIC DOMAIN and Not under copywrite protection. First published for g2log at KjellKod.cc
|
||||||
* ********************************************* */
|
* ********************************************* */
|
||||||
|
|
||||||
#include "g2time.h"
|
#include "g2time.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <cassert>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
|
||||||
namespace g2 { namespace internal {
|
namespace g2 {
|
||||||
// This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)"
|
namespace internal {
|
||||||
// This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet.
|
// This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)"
|
||||||
// return value is SIMPLIFIED to only return a std::string
|
// This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet.
|
||||||
std::string put_time(const struct tm* tmb, const char* c_time_format)
|
// return value is SIMPLIFIED to only return a std::string
|
||||||
{
|
|
||||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(__MINGW32__)
|
std::string put_time(const struct tm* tmb, const char* c_time_format) {
|
||||||
std::ostringstream oss;
|
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||||
oss.fill('0');
|
std::ostringstream oss;
|
||||||
oss << std::put_time(const_cast<struct tm*>(tmb), c_time_format); // BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm* "
|
oss.fill('0');
|
||||||
return oss.str();
|
// BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm* "
|
||||||
|
oss << std::put_time(const_cast<struct tm*> (tmb), c_time_format);
|
||||||
|
return oss.str();
|
||||||
#else // LINUX
|
#else // LINUX
|
||||||
const size_t size = 1024;
|
const size_t size = 1024;
|
||||||
char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time finns.
|
char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time.
|
||||||
// ... also ... This is way more buffer space then we need
|
// ... also ... This is way more buffer space then we need
|
||||||
auto success = std::strftime(buffer, size, c_time_format, tmb);
|
|
||||||
if (0 == success)
|
auto success = std::strftime(buffer, size, c_time_format, tmb);
|
||||||
return c_time_format; // For this hack it is OK but in case of more permanent we really should throw here, or even assert
|
if (0 == success)
|
||||||
return buffer;
|
{
|
||||||
|
assert((0 != success) && "strftime fails with illegal formatting");
|
||||||
|
return c_time_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
} // internal
|
||||||
|
} // g2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace g2 {
|
||||||
|
|
||||||
|
std::time_t systemtime_now() {
|
||||||
|
system_time_point system_now = std::chrono::system_clock::now();
|
||||||
|
return std::chrono::system_clock::to_time_t(system_now);
|
||||||
}
|
}
|
||||||
} // internal
|
|
||||||
} // g2
|
|
||||||
|
|
||||||
|
tm localtime(const std::time_t& time) {
|
||||||
|
struct tm tm_snapshot;
|
||||||
namespace g2
|
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__))
|
||||||
{
|
localtime_s(&tm_snapshot, &time); // windsows
|
||||||
std::time_t systemtime_now()
|
|
||||||
{
|
|
||||||
system_time_point system_now = std::chrono::system_clock::now();
|
|
||||||
return std::chrono::system_clock::to_time_t(system_now);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tm localtime(const std::time_t& time)
|
|
||||||
{
|
|
||||||
struct tm tm_snapshot;
|
|
||||||
#if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
|
||||||
localtime_r(&time, &tm_snapshot); // POSIX
|
|
||||||
#else
|
#else
|
||||||
localtime_s(&tm_snapshot, &time); // windsows
|
localtime_r(&time, &tm_snapshot); // POSIX
|
||||||
#endif
|
#endif
|
||||||
return tm_snapshot;
|
return tm_snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns a std::string with content of time_t as localtime formatted by input format string
|
/// returns a std::string with content of time_t as localtime formatted by input format string
|
||||||
/// * format string must conform to std::put_time
|
/// * format string must conform to std::put_time
|
||||||
/// This is similar to std::put_time(std::localtime(std::time_t*), time_format.c_str());
|
/// This is similar to std::put_time(std::localtime(std::time_t*), time_format.c_str());
|
||||||
std::string localtime_formatted(const std::time_t& time_snapshot, const std::string& time_format)
|
|
||||||
{
|
std::string localtime_formatted(const std::time_t& time_snapshot, const std::string& time_format) {
|
||||||
std::tm t = localtime(time_snapshot); // could be const, but cannot due to VS2012 is non conformant for C++11's std::put_time (see above)
|
std::tm t = localtime(time_snapshot); // could be const, but cannot due to VS2012 is non conformant for C++11's std::put_time (see above)
|
||||||
std::stringstream buffer;
|
std::stringstream buffer;
|
||||||
buffer << g2::internal::put_time(&t, time_format.c_str()); // format example: //"%Y/%m/%d %H:%M:%S");
|
buffer << g2::internal::put_time(&t, time_format.c_str()); // format example: //"%Y/%m/%d %H:%M:%S");
|
||||||
return buffer.str();
|
return buffer.str();
|
||||||
}
|
}
|
||||||
} // g2
|
} // g2
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef G2_TIME_H_
|
#ifndef G2_TIME_HPP_
|
||||||
#define G2_TIME_H_
|
#define G2_TIME_HPP_
|
||||||
/** ==========================================================================
|
/** ==========================================================================
|
||||||
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
|
||||||
* with no warranties. This code is yours to share, use and modify with no
|
* with no warranties. This code is yours to share, use and modify with no
|
||||||
@ -22,6 +22,12 @@
|
|||||||
|
|
||||||
namespace g2
|
namespace g2
|
||||||
{
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
static const std::string date_formatted = "%Y/%m/%d";
|
||||||
|
static const std::string time_formatted = "%H:%M:%S";
|
||||||
|
}
|
||||||
|
|
||||||
typedef std::chrono::steady_clock::time_point steady_time_point;
|
typedef std::chrono::steady_clock::time_point steady_time_point;
|
||||||
typedef std::chrono::time_point<std::chrono::system_clock> system_time_point;
|
typedef std::chrono::time_point<std::chrono::system_clock> system_time_point;
|
||||||
typedef std::chrono::milliseconds milliseconds;
|
typedef std::chrono::milliseconds milliseconds;
|
@ -13,7 +13,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "g2time.h"
|
#include "g2time.hpp"
|
||||||
#include "g2future.h"
|
#include "g2future.h"
|
||||||
|
|
||||||
TEST(Configuration, LOG)
|
TEST(Configuration, LOG)
|
||||||
|
@ -51,13 +51,15 @@
|
|||||||
// std::string changeDirectoryOrName(std::string new_file_to_create) {
|
// std::string changeDirectoryOrName(std::string new_file_to_create) {
|
||||||
// static std::mutex m;
|
// static std::mutex m;
|
||||||
// static int count;
|
// static int count;
|
||||||
|
// std::string add_count;
|
||||||
// std::lock_guard<std::mutex> lock(m);
|
// std::lock_guard<std::mutex> lock(m);
|
||||||
// {
|
// {
|
||||||
// std::string add_count = std::to_string(++count) + "_";
|
// add_count = std::to_string(++count) + "_";
|
||||||
// auto new_log = g_logger_ptr->changeLogFile(new_file_to_create + add_count).get();
|
// auto new_log = g_logger_ptr->changeLogFile(new_file_to_create + add_count).get();
|
||||||
// if (!new_log.empty()) g_cleaner_ptr->addLogToClean(new_log);
|
// if (!new_log.empty()) g_cleaner_ptr->addLogToClean(new_log);
|
||||||
// return new_log;
|
// return new_log;
|
||||||
// }
|
// }
|
||||||
|
// return add_count;
|
||||||
// }
|
// }
|
||||||
//} // anonymous
|
//} // anonymous
|
||||||
//
|
//
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "g2sink.h"
|
#include "g2sink.h"
|
||||||
#include "g2sinkwrapper.h"
|
#include "g2sinkwrapper.h"
|
||||||
#include "g2sinkhandle.h"
|
#include "g2sinkhandle.h"
|
||||||
#include "g2logmessage.h"
|
#include "g2logmessage.hpp"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "testing_helpers.h"
|
#include "testing_helpers.h"
|
||||||
#include "g2log.h"
|
#include "g2log.h"
|
||||||
#include "g2logworker.h"
|
#include "g2logworker.h"
|
||||||
#include "g2filesink.h"
|
#include "g2filesink.hpp"
|
||||||
#include "std2_make_unique.hpp"
|
#include "std2_make_unique.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -21,14 +21,15 @@ ScopedCout::~ScopedCout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RestoreLogger::RestoreLogger(std::string directory)
|
RestoreLogger::RestoreLogger(std::string directory)
|
||||||
: logger_(std2::make_unique<g2LogWorker>("UNIT_TEST_LOGGER", directory)) {
|
: logger_(g2LogWorker::createWithNoSink()) {
|
||||||
|
using namespace g2;
|
||||||
|
auto filehandler = logger_->addSink(std2::make_unique<g2FileSink>("UNIT_TEST_LOGGER", directory), &g2FileSink::fileWrite);
|
||||||
|
|
||||||
oldworker = g2::shutDownLogging();
|
oldworker = g2::shutDownLogging();
|
||||||
g2::initializeLogging(logger_.get());
|
initializeLogging(logger_.get());
|
||||||
g2::internal::changeFatalInitHandlerForUnitTesting();
|
internal::changeFatalInitHandlerForUnitTesting();
|
||||||
|
|
||||||
auto filehandler = logger_->getFileSinkHandle();
|
auto filename = filehandler->call(&g2FileSink::fileName);
|
||||||
auto filename = filehandler->call(&g2FileSink::logFileName);
|
|
||||||
if (!filename.valid()) ADD_FAILURE();
|
if (!filename.valid()) ADD_FAILURE();
|
||||||
log_file_ = filename.get();
|
log_file_ = filename.get();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user