mirror of
https://github.com/KjellKod/g3log.git
synced 2025-03-02 20:30:12 +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
|
||||
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)
|
||||
list(REMOVE_ITEM SRC_FILES ${LOG_SRC}/crashhandler_unix.cpp)
|
||||
else()
|
||||
|
@ -4,7 +4,7 @@
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================*/
|
||||
|
||||
#include "crashhandler.h"
|
||||
#include "crashhandler.hpp"
|
||||
#include "g2log.h"
|
||||
|
||||
#include <csignal>
|
||||
|
@ -4,7 +4,7 @@
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================*/
|
||||
|
||||
#include "crashhandler.h"
|
||||
#include "crashhandler.hpp"
|
||||
#include "g2log.h"
|
||||
|
||||
#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 "g2logworker.h"
|
||||
#include "crashhandler.h"
|
||||
#include "crashhandler.hpp"
|
||||
#include <signal.h>
|
||||
#include <thread>
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <iostream>
|
||||
#include <cstdarg>
|
||||
#include <chrono>
|
||||
#include "g2logmessage.h"
|
||||
#include "g2logmessage.hpp"
|
||||
|
||||
|
||||
class g2LogWorker;
|
||||
|
@ -1,98 +1,109 @@
|
||||
/** ==========================================================================
|
||||
* 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
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================
|
||||
* Filename:g2LogWorker.cpp Framework for Logging and Design By Contract
|
||||
* Created: 2011 by Kjell Hedström
|
||||
*
|
||||
* PUBLIC DOMAIN and Not under copywrite protection. First published at KjellKod.cc
|
||||
* ********************************************* */
|
||||
* 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
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================
|
||||
* Filename:g2LogWorker.cpp Framework for Logging and Design By Contract
|
||||
* Created: 2011 by Kjell Hedström
|
||||
*
|
||||
* PUBLIC DOMAIN and Not under copywrite protection. First published at KjellKod.cc
|
||||
* ********************************************* */
|
||||
|
||||
#include "g2logworker.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <functional>
|
||||
|
||||
|
||||
|
||||
#include "active.h"
|
||||
#include "g2log.h"
|
||||
#include "crashhandler.h"
|
||||
#include "g2time.h"
|
||||
#include "g2time.hpp"
|
||||
#include "g2future.h"
|
||||
#include "g2filesink.h"
|
||||
#include "std2_make_unique.hpp"
|
||||
#include "crashhandler.hpp"
|
||||
|
||||
|
||||
using namespace g2;
|
||||
using namespace g2::internal;
|
||||
|
||||
struct g2LogWorkerImpl
|
||||
{
|
||||
typedef std::shared_ptr<g2::internal::SinkWrapper> SinkWrapperPtr;
|
||||
|
||||
g2LogWorkerImpl(){}
|
||||
~g2LogWorkerImpl(){ _bg.reset(); _sinks.clear(); }
|
||||
|
||||
struct g2LogWorkerImpl {
|
||||
typedef std::shared_ptr<g2::internal::SinkWrapper> SinkWrapperPtr;
|
||||
std::unique_ptr<kjellkod::Active> _bg;
|
||||
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) {
|
||||
for(auto& sink : _sinks) {
|
||||
for (auto& sink : _sinks) {
|
||||
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_;
|
||||
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
|
||||
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.
|
||||
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()
|
||||
{
|
||||
_pimpl.reset();
|
||||
g2LogWorker::g2LogWorker()
|
||||
: _pimpl(std2::make_unique<g2LogWorkerImpl>()) {
|
||||
}
|
||||
|
||||
void g2LogWorker::save(g2::internal::LogEntry msg)
|
||||
{
|
||||
_pimpl->_bg->send([this, msg]{ _pimpl->bgSave(msg); });
|
||||
//std::bind(&g2LogWorkerImpl::backgroundFileWrite, _pimpl.get(), msg));
|
||||
g2LogWorker::~g2LogWorker() { _pimpl.reset(); }
|
||||
|
||||
void g2LogWorker::save(g2::internal::LogEntry msg) {
|
||||
_pimpl->_bg->send([this, msg] { _pimpl->bgSave(msg); });
|
||||
}
|
||||
|
||||
void g2LogWorker::fatal(g2::internal::FatalMessage fatal_message)
|
||||
{
|
||||
_pimpl->_bg->send([this, fatal_message]{ _pimpl->bgFatal(fatal_message); });
|
||||
//std::bind(&g2LogWorkerImpl::backgroundExitFatal, _pimpl.get(), fatal_message));
|
||||
void g2LogWorker::fatal(g2::internal::FatalMessage fatal_message) {
|
||||
_pimpl->_bg->send([this, fatal_message] {_pimpl->bgFatal(fatal_message); });
|
||||
//OR: td::bind(&g2LogWorkerImpl::backgroundExitFatal, _pimpl.get(), fatal_message));
|
||||
}
|
||||
|
||||
|
||||
void g2LogWorker::addWrappedSink(std::shared_ptr<g2::internal::SinkWrapper> sink) {
|
||||
auto bg_addsink_call = [this, sink] { _pimpl->_sinks.push_back(sink); };
|
||||
auto token_done = g2::spawn_task(bg_addsink_call, _pimpl->_bg.get());
|
||||
token_done.wait();
|
||||
auto bg_addsink_call = [this, sink] { _pimpl->_sinks.push_back(sink); };
|
||||
auto token_done = g2::spawn_task(bg_addsink_call, _pimpl->_bg.get());
|
||||
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_
|
||||
#define G2_LOG_WORKER_H_
|
||||
/** ==========================================================================
|
||||
* 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
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================
|
||||
* Filename:g2logworker.h Framework for Logging and Design By Contract
|
||||
* Created: 2011 by Kjell Hedström
|
||||
*
|
||||
* PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
|
||||
* ********************************************* */
|
||||
* 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
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================
|
||||
* Filename:g2logworker.h Framework for Logging and Design By Contract
|
||||
* Created: 2011 by Kjell Hedström
|
||||
*
|
||||
* PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
|
||||
* ********************************************* */
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include <string>
|
||||
#include "std2_make_unique.hpp"
|
||||
#include <utility>
|
||||
|
||||
#include "g2log.h"
|
||||
#include "g2sinkwrapper.h"
|
||||
#include "g2sinkhandle.h"
|
||||
|
||||
#include "g2filesink.hpp"
|
||||
#include "std2_make_unique.hpp"
|
||||
|
||||
struct g2LogWorkerImpl;
|
||||
struct g2FileSink;
|
||||
|
||||
/**
|
||||
* \param log_prefix is the 'name' of the binary, this give the log name 'LOG-'name'-...
|
||||
* \param log_directory gives the directory to put the log files */
|
||||
class g2LogWorker
|
||||
{
|
||||
class g2LogWorker {
|
||||
g2LogWorker(); // Create only through factory
|
||||
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;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
g2LogWorker(const std::string& log_prefix, const std::string& log_directory);
|
||||
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
|
||||
void save(g2::internal::LogEntry entry);
|
||||
|
||||
@ -43,35 +51,14 @@ public:
|
||||
void fatal(g2::internal::FatalMessage fatal_message);
|
||||
|
||||
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::internal;
|
||||
auto shared_sink = std::shared_ptr<T>(real_sink.release());
|
||||
auto sink = std::make_shared<Sink<T>>(shared_sink, call);
|
||||
auto add_result = addWrappedSink(sink);
|
||||
return std2::make_unique<SinkHandle<T>>(sink);
|
||||
auto sink = std::make_shared < Sink < T >> (shared_sink, call);
|
||||
addWrappedSink(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
|
||||
#define G2SINKWRAPPER_IPP
|
||||
|
||||
#include "g2logmessage.h"
|
||||
#include "g2logmessage.hpp"
|
||||
|
||||
namespace g2 {
|
||||
namespace internal {
|
||||
|
@ -1,79 +1,84 @@
|
||||
/** ==========================================================================
|
||||
* 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
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================
|
||||
* Filename:g2time.cpp cross-platform, thread-safe replacement for C++11 non-thread-safe
|
||||
* localtime (and similar)
|
||||
* Created: 2012 by Kjell Hedström
|
||||
*
|
||||
* PUBLIC DOMAIN and Not under copywrite protection. First published for g2log at KjellKod.cc
|
||||
* ********************************************* */
|
||||
* 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
|
||||
* strings attached and no restrictions or obligations.
|
||||
* ============================================================================
|
||||
* Filename:g2time.cpp cross-platform, thread-safe replacement for C++11 non-thread-safe
|
||||
* localtime (and similar)
|
||||
* Created: 2012 by Kjell Hedström
|
||||
*
|
||||
* PUBLIC DOMAIN and Not under copywrite protection. First published for g2log at KjellKod.cc
|
||||
* ********************************************* */
|
||||
|
||||
#include "g2time.h"
|
||||
#include "g2time.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
namespace g2 { namespace internal {
|
||||
// This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)"
|
||||
// This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet.
|
||||
// return value is SIMPLIFIED to only return a std::string
|
||||
std::string put_time(const struct tm* tmb, const char* c_time_format)
|
||||
{
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(__MINGW32__)
|
||||
std::ostringstream oss;
|
||||
oss.fill('0');
|
||||
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* "
|
||||
return oss.str();
|
||||
namespace g2 {
|
||||
namespace internal {
|
||||
// This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)"
|
||||
// This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet.
|
||||
// return value is SIMPLIFIED to only return a std::string
|
||||
|
||||
std::string put_time(const struct tm* tmb, const char* c_time_format) {
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||
std::ostringstream oss;
|
||||
oss.fill('0');
|
||||
// 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
|
||||
const size_t size = 1024;
|
||||
char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time finns.
|
||||
// ... also ... This is way more buffer space then we need
|
||||
auto success = std::strftime(buffer, size, c_time_format, tmb);
|
||||
if (0 == success)
|
||||
return c_time_format; // For this hack it is OK but in case of more permanent we really should throw here, or even assert
|
||||
return buffer;
|
||||
const size_t size = 1024;
|
||||
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
|
||||
|
||||
auto success = std::strftime(buffer, size, c_time_format, tmb);
|
||||
if (0 == success)
|
||||
{
|
||||
assert((0 != success) && "strftime fails with illegal formatting");
|
||||
return c_time_format;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
#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
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
tm localtime(const std::time_t& time)
|
||||
{
|
||||
struct tm tm_snapshot;
|
||||
#if !(defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||
localtime_r(&time, &tm_snapshot); // POSIX
|
||||
tm localtime(const std::time_t& time) {
|
||||
struct tm tm_snapshot;
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__))
|
||||
localtime_s(&tm_snapshot, &time); // windsows
|
||||
#else
|
||||
localtime_s(&tm_snapshot, &time); // windsows
|
||||
localtime_r(&time, &tm_snapshot); // POSIX
|
||||
#endif
|
||||
return tm_snapshot;
|
||||
}
|
||||
return tm_snapshot;
|
||||
}
|
||||
|
||||
/// returns a std::string with content of time_t as localtime formatted by input format string
|
||||
/// * format string must conform to std::put_time
|
||||
/// 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::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;
|
||||
buffer << g2::internal::put_time(&t, time_format.c_str()); // format example: //"%Y/%m/%d %H:%M:%S");
|
||||
return buffer.str();
|
||||
}
|
||||
/// returns a std::string with content of time_t as localtime formatted by input format string
|
||||
/// * format string must conform to std::put_time
|
||||
/// 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::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;
|
||||
buffer << g2::internal::put_time(&t, time_format.c_str()); // format example: //"%Y/%m/%d %H:%M:%S");
|
||||
return buffer.str();
|
||||
}
|
||||
} // g2
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef G2_TIME_H_
|
||||
#define G2_TIME_H_
|
||||
#ifndef G2_TIME_HPP_
|
||||
#define G2_TIME_HPP_
|
||||
/** ==========================================================================
|
||||
* 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
|
||||
@ -22,6 +22,12 @@
|
||||
|
||||
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::time_point<std::chrono::system_clock> system_time_point;
|
||||
typedef std::chrono::milliseconds milliseconds;
|
@ -13,7 +13,7 @@
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "g2time.h"
|
||||
#include "g2time.hpp"
|
||||
#include "g2future.h"
|
||||
|
||||
TEST(Configuration, LOG)
|
||||
|
@ -51,13 +51,15 @@
|
||||
// std::string changeDirectoryOrName(std::string new_file_to_create) {
|
||||
// static std::mutex m;
|
||||
// static int count;
|
||||
// std::string add_count;
|
||||
// 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();
|
||||
// if (!new_log.empty()) g_cleaner_ptr->addLogToClean(new_log);
|
||||
// return new_log;
|
||||
// }
|
||||
// return add_count;
|
||||
// }
|
||||
//} // anonymous
|
||||
//
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "g2sink.h"
|
||||
#include "g2sinkwrapper.h"
|
||||
#include "g2sinkhandle.h"
|
||||
#include "g2logmessage.h"
|
||||
#include "g2logmessage.hpp"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "testing_helpers.h"
|
||||
#include "g2log.h"
|
||||
#include "g2logworker.h"
|
||||
#include "g2filesink.h"
|
||||
#include "g2filesink.hpp"
|
||||
#include "std2_make_unique.hpp"
|
||||
|
||||
using namespace std;
|
||||
@ -21,14 +21,15 @@ ScopedCout::~ScopedCout() {
|
||||
}
|
||||
|
||||
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();
|
||||
g2::initializeLogging(logger_.get());
|
||||
g2::internal::changeFatalInitHandlerForUnitTesting();
|
||||
initializeLogging(logger_.get());
|
||||
internal::changeFatalInitHandlerForUnitTesting();
|
||||
|
||||
auto filehandler = logger_->getFileSinkHandle();
|
||||
auto filename = filehandler->call(&g2FileSink::logFileName);
|
||||
auto filename = filehandler->call(&g2FileSink::fileName);
|
||||
if (!filename.valid()) ADD_FAILURE();
|
||||
log_file_ = filename.get();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user