mirror of
https://github.com/KjellKod/g3log.git
synced 2024-12-13 10:42:56 +01:00
Concentrated all files into src, previously it was under its own active-object sub-repository
This commit is contained in:
parent
b9459af2f3
commit
fa9e5b4adf
@ -1,70 +0,0 @@
|
||||
# ================WINDOWS==================
|
||||
# On Windows
|
||||
# mkdir build; cd build;
|
||||
# cmake -G "Visual Studio 10" ..
|
||||
# msbuild ActiveObj_by_KjellKod.sln
|
||||
# Debug\ActiveObj_by_KjellKod.exe
|
||||
#
|
||||
#
|
||||
# ================LINUX==================
|
||||
# On Linux, make sure that the environmental variables are set either in .profile or otherwise
|
||||
# PATH=$PATH:/usr/include/justthread
|
||||
# export PATH=/usr/lib/:$PATH
|
||||
#
|
||||
# from a++0x__active_object do
|
||||
# mkdir build; cd build; cmake ..; make
|
||||
#
|
||||
# In case of CMake problems, Compile command line
|
||||
#g++ src/main.cpp src/active.cpp -I /home/kjhm/Desktop/KjellKod/active-object_c++0x/src -o ActiveObj -std=c++0x -I/usr/include/justthread -pthread -ljustthread -lrt
|
||||
#
|
||||
# Or to simplify things even more, put all the source code in the same folder and run
|
||||
# g++ main.cpp active.cpp -o ActiveObj -std=c++0x -I/usr/include/justthread -pthread -ljustthread -lrt
|
||||
#
|
||||
#
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (ActiveObjCpp0x)
|
||||
|
||||
IF(UNIX)
|
||||
set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS_DEBUG} -pthread -I/usr/include/justthread")
|
||||
|
||||
# make the src directory available for test classes
|
||||
include_directories("/usr/include/justthread")
|
||||
include_directories(../src)
|
||||
|
||||
# create the test executable
|
||||
#add_executable(ActiveObjCpp0x ../src/main.cpp ../src/active.cpp )
|
||||
add_executable(ActiveObjCpp0x ../src/main.cpp ../src/active.cpp ../src/shared_queue.h ../src/active.h ../src/backgrounder.h)
|
||||
target_link_libraries(ActiveObjCpp0x justthread rt)
|
||||
|
||||
ENDIF(UNIX)
|
||||
|
||||
|
||||
IF(WIN32)
|
||||
include_directories("C:/program files/JustSoftwareSolutions/JustThread/include")
|
||||
include_directories(../src)
|
||||
add_executable(ActiveObjCpp0x ../src/main.cpp ../src/active.cpp )
|
||||
|
||||
#Visual Studio 2010
|
||||
IF(CMAKE_CXX_COMPILER STREQUAL "C:/Program Files/Microsoft Visual Studio 10.0/VC/bin/cl.exe")
|
||||
target_link_libraries(ActiveObjCpp0x $ENV{PROGRAMFILES}/JustSoftwareSolutions/JustThread/lib/justthread_vc10_mdd.lib)
|
||||
ENDIF(CMAKE_CXX_COMPILER STREQUAL "C:/Program Files/Microsoft Visual Studio 10.0/VC/bin/cl.exe")
|
||||
|
||||
# Visual Studio 2008 DOES NOT WORK
|
||||
# ===================================
|
||||
# 1. std::function must be std::tr1::function but
|
||||
# std::unique_ptr does not exist (ref C:\Program Files\Microsoft Visual Studio 9.0\VC\include\memory.h)
|
||||
# while it exist for Visual Studio 10 (ref C:\Program Files\Microsoft Visual Studio 10.0\VC\include\memory.h)
|
||||
# ...Also this bug was discovered...
|
||||
# Ref: https://connect.microsoft.com/VisualStudio/feedback/details/339810/tr1-functional-doesnt-work-when-compiled-with-fastcall
|
||||
#....
|
||||
# However if you decide to use it anyhow and replacing the unique_ptr for shared_ptr and using std::tr1 then the
|
||||
# following might be of use
|
||||
#IF(CMAKE_CXX_COMPILER STREQUAL "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin/cl.exe")
|
||||
# target_link_libraries(ActiveObjCpp0x $ENV{PROGRAMFILES}/JustSoftwareSolutions/JustThread/lib/justthread_vc90_mdd.lib)
|
||||
#ENDIF(CMAKE_CXX_COMPILER STREQUAL "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin/cl.exe")
|
||||
ENDIF(WIN32)
|
||||
|
||||
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
# ================WINDOWS==================
|
||||
# On Windows
|
||||
# mkdir build; cd build;
|
||||
# cmake -G "Visual Studio 10" ..
|
||||
# msbuild ActiveObj_by_KjellKod.sln
|
||||
# Debug\ActiveObj_by_KjellKod.exe
|
||||
#
|
||||
#
|
||||
# ================LINUX==================
|
||||
# On Linux, make sure that the environmental variables are set either in .profile or otherwise
|
||||
# PATH=$PATH:/usr/include/justthread
|
||||
# export PATH=/usr/lib/:$PATH
|
||||
#
|
||||
# from the top directory (active-object_c++0x)
|
||||
# mkdir build; cd build; cmake ..; make
|
||||
#
|
||||
# In case of CMake problems, Compile command line
|
||||
#g++ src/main.cpp src/active.cpp -I /home/kjhm/Desktop/KjellKod/active-object_c++0x/src -o ActiveObj -std=c++0x -I/usr/include/justthread -pthread -ljustthread -lrt
|
||||
#
|
||||
# Or to simplify things even more, put all the source code in the same folder and run
|
||||
# g++ main.cpp active.cpp -o ActiveObj -std=c++0x -I/usr/include/justthread -pthread -ljustthread -lrt
|
@ -1,59 +0,0 @@
|
||||
/** ==========================================================================
|
||||
* 2010 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.
|
||||
* ============================================================================
|
||||
*
|
||||
* Example of a Background worker that uses an Active object (by composition)
|
||||
* to process jobs in the background.
|
||||
* Calling the Background worker to do a job is an asynchronous call, returning
|
||||
* almost immediately. The Backgrounder will create a job and push it onto a
|
||||
* queue that is processed in FIFO order by the Active object. */
|
||||
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include "active.h"
|
||||
|
||||
|
||||
/// Silly test background worker that only receives dummy encapsuled data and stores them in a vector
|
||||
/// the worker eceives the "jobs" and sends them to a work queue to be asynchronously
|
||||
// executed in FIFO order by the background thread.
|
||||
template<typename T>
|
||||
class Backgrounder {
|
||||
private:
|
||||
std::unique_ptr<kjellkod::Active> active;
|
||||
std::vector<T>& receivedQ;
|
||||
unsigned int c_processTimeUs; // to fake processing time, in microseconds
|
||||
|
||||
// Container for faking some imporant stuff type instead of a dummy value
|
||||
// so that it 'makes sense' storing it in an unique_ptr
|
||||
struct Data {
|
||||
Data(T v_) :value(v_) {}
|
||||
const T value;
|
||||
};
|
||||
|
||||
// bg processing, FAKING that each job takes a few ms
|
||||
void bgStoreData(std::shared_ptr<Data> msg_){
|
||||
receivedQ.push_back(msg_->value);
|
||||
// fake processing time
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(c_processTimeUs));
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Backgrounder(std::vector<T>& saveQ_)
|
||||
: active(kjellkod::Active::createActive())
|
||||
, receivedQ(saveQ_)
|
||||
, c_processTimeUs(1){}
|
||||
|
||||
virtual ~Backgrounder(){}
|
||||
|
||||
// Asynchronous msg API, for sending jobs for bg thread processing
|
||||
void saveData(const T value_){
|
||||
using namespace kjellkod;
|
||||
std::shared_ptr<Data> ptrBg(new Data(value_));
|
||||
Callback func = std::bind(&Backgrounder::bgStoreData, this, ptrBg);
|
||||
active->send(func);
|
||||
}
|
||||
};
|
@ -1,130 +0,0 @@
|
||||
|
||||
/** ==========================================================================
|
||||
* 2010 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.
|
||||
* ============================================================================
|
||||
* Please See readme or CMakeList.txt for building instructions */
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
|
||||
#include "backgrounder.h"
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
void printPercentageLeft(const unsigned nbr_, unsigned & progress_, const unsigned max_){
|
||||
float percent = 100 * ((float)nbr_/max_);
|
||||
unsigned int rounded = ((int)percent/10)*10;
|
||||
if(rounded != progress_){
|
||||
std::cout << 100 - progress_ << " " << std::flush;
|
||||
progress_ = rounded;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void printProgress(const std::vector<T>& out_,const std::vector<T>& in_, const unsigned max_)
|
||||
{
|
||||
std::cout << "\nLeft to Process [%]: ";
|
||||
unsigned progress = 100;
|
||||
do{
|
||||
unsigned pSize = in_.size();
|
||||
unsigned remaining = pSize - out_.size();
|
||||
printPercentageLeft(remaining, progress, max_);
|
||||
}while((out_.size() < max_) && progress <= 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void runStrWorkers(const int c_nbrItems)
|
||||
{
|
||||
std::vector<std::string> saveToQ;
|
||||
std::vector<std::string> compareQ;
|
||||
const clock_t start = clock();
|
||||
{
|
||||
Backgrounder<std::string> worker(saveToQ);
|
||||
srand((unsigned)time(0));
|
||||
|
||||
for(int idx=0; idx < c_nbrItems; ++idx)
|
||||
{
|
||||
unsigned random = rand();
|
||||
std::ostringstream oss;
|
||||
oss << random;
|
||||
compareQ.push_back(oss.str());
|
||||
worker.saveData(oss.str());
|
||||
}
|
||||
double pushTime = ((clock() - start)/(double)CLOCKS_PER_SEC);
|
||||
std::cout<<"Finished pushing #"<<c_nbrItems<<" jobs to bg worker";
|
||||
std::cout<<" in "<<pushTime<<" [s]"<< std::endl;
|
||||
|
||||
printProgress(saveToQ, compareQ, c_nbrItems);
|
||||
} // Trigger Backgrounder to go out of scope
|
||||
double workTime = ((clock() - start)/(double)CLOCKS_PER_SEC);
|
||||
std::cout << "\nBackgrounder finished with processing jobs in ";
|
||||
std::cout <<workTime<<" [s]"<< std::endl;
|
||||
|
||||
// just dummy to make sure that nothing was lost
|
||||
assert(std::equal(compareQ.begin(), compareQ.end(), saveToQ.begin()));
|
||||
assert(saveToQ.size() == c_nbrItems);
|
||||
}
|
||||
|
||||
void runIntWorkers(const int c_nbrItems)
|
||||
{
|
||||
std::vector<int> saveToQ;
|
||||
std::vector<int> compareQ;
|
||||
const clock_t start = clock();
|
||||
{
|
||||
Backgrounder<int> worker(saveToQ);
|
||||
srand((unsigned)time(0));
|
||||
|
||||
// all except one is random, save space for "zero" after the
|
||||
// loop
|
||||
for(int idx=0; idx < c_nbrItems-1; ++idx)
|
||||
{
|
||||
unsigned random = rand();
|
||||
compareQ.push_back(random);
|
||||
worker.saveData(random);
|
||||
}
|
||||
// extra case for empty item
|
||||
compareQ.push_back(0);
|
||||
worker.saveData(0);
|
||||
|
||||
|
||||
double pushTime = ((clock() - start)/(double)CLOCKS_PER_SEC);
|
||||
std::cout<<"Finished pushing #"<<c_nbrItems<<" jobs to bg worker";
|
||||
std::cout<<" in "<<pushTime<<" [s]"<< std::endl;
|
||||
|
||||
printProgress(saveToQ, compareQ, c_nbrItems);
|
||||
} // Trigger Backgrounder to go out of scope
|
||||
double workTime = ((clock() - start)/(double)CLOCKS_PER_SEC);
|
||||
std::cout << "\nBackgrounder finished with processing jobs in ";
|
||||
std::cout<<" in "<<workTime<<" [s]"<< std::endl;
|
||||
|
||||
// just dummy to make sure that nothing was lost
|
||||
assert(std::equal(compareQ.begin(), compareQ.end(), saveToQ.begin()));
|
||||
assert(saveToQ.size() == c_nbrItems);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const int c_nbrItems = 100000;
|
||||
std::cout << c_nbrItems << " transactions of std::string/int" << std::endl;
|
||||
runStrWorkers(c_nbrItems);
|
||||
|
||||
std::cout << "\n\n" << c_nbrItems << " transactions of int" << std::endl;
|
||||
runIntWorkers(c_nbrItems);
|
||||
|
||||
return 0;
|
||||
}
|
@ -50,7 +50,7 @@ IF(UNIX)
|
||||
include_directories(/usr/include/justthread) #not necessarily needed if it's in the path
|
||||
|
||||
# add a ActiveObject library
|
||||
set(ACTIVE_DIR ${LOG_SRC}/../../active-object_c++0x/src)
|
||||
set(ACTIVE_DIR ${LOG_SRC})
|
||||
include_directories(${ACTIVE_DIR})
|
||||
MESSAGE(" ACTIVE_DIR = : ${ACTIVE_DIR}")
|
||||
SET(ACTIVE_CPP0xx_DIR "Release")
|
||||
@ -61,7 +61,7 @@ IF(UNIX)
|
||||
include_directories(src)
|
||||
include_directories(${LOG_SRC})
|
||||
#MESSAGE(" LOG_SRC = : ${LOG_SRC}")
|
||||
add_library(lib_logger ${LOG_SRC}/logworker.h ${LOG_SRC}/logworker.cpp ${LOG_SRC}/privatelogworker.cpp ${LOG_SRC}/privatelogworker.h ${LOG_SRC}/g2log.h ${LOG_SRC}/g2log.cpp )
|
||||
add_library(lib_logger ${LOG_SRC}/logworker.h ${LOG_SRC}/logworker.cpp ${LOG_SRC}/g2log.h ${LOG_SRC}/g2log.cpp )
|
||||
set_target_properties(lib_logger PROPERTIES LINKER_LANGUAGE CXX)
|
||||
target_link_libraries(lib_logger lib_activeobject)
|
||||
|
||||
|
@ -7,26 +7,149 @@
|
||||
|
||||
#include "logworker.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
|
||||
#include "privatelogworker.h"
|
||||
#include "active.h"
|
||||
#include "g2log.h"
|
||||
|
||||
using namespace g2::internal;
|
||||
namespace
|
||||
{
|
||||
struct LogTime
|
||||
{
|
||||
LogTime()
|
||||
{
|
||||
time_t current_time = time(nullptr);
|
||||
ctime(¤t_time); // fill with time right now
|
||||
struct tm* ptm = localtime(¤t_time); // fill time struct with data
|
||||
year = ptm->tm_year + 1900;
|
||||
month = (ptm->tm_mon) +1;
|
||||
day = ptm->tm_mday;
|
||||
hour = ptm->tm_hour;
|
||||
minute = ptm->tm_min;
|
||||
second = ptm->tm_sec;
|
||||
}
|
||||
int year; // Year - 1900
|
||||
int month; // [1-12]
|
||||
int day; // [1-31]
|
||||
int hour; // [0-23]
|
||||
int minute; // [0-59]
|
||||
int second; // [0-60], 1 leap second
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
|
||||
|
||||
/** The actual background worker, while LogWorker gives the
|
||||
* asynchronous API to put job in the background the LogWorkerImpl
|
||||
* does the actual background thread work */
|
||||
struct LogWorkerImpl
|
||||
{
|
||||
LogWorkerImpl(const std::string& log_prefix, const std::string& log_directory);
|
||||
~LogWorkerImpl();
|
||||
|
||||
void backgroundFileWrite(g2::internal::LogEntry message);
|
||||
|
||||
std::string log_file_with_path_;
|
||||
std::unique_ptr<kjellkod::Active> bg_;
|
||||
std::ofstream out;
|
||||
g2::internal::time_point start_time_;
|
||||
|
||||
private:
|
||||
LogWorkerImpl& operator=(const LogWorkerImpl&) = delete; // no assignment, no copy
|
||||
LogWorkerImpl(const LogWorkerImpl& other) = delete;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Private API implementation : LogWorkerImpl
|
||||
LogWorkerImpl::LogWorkerImpl(const std::string& log_prefix, const std::string& log_directory)
|
||||
: log_file_with_path_(log_directory)
|
||||
, bg_(kjellkod::Active::createActive())
|
||||
, start_time_(std::chrono::steady_clock::now())
|
||||
{
|
||||
using namespace std;
|
||||
LogTime t;
|
||||
ostringstream oss_name;
|
||||
oss_name.fill('0');
|
||||
oss_name << log_prefix << ".g2log.";
|
||||
oss_name << t.year << setw(2) << t.month << setw(2) << t.day;
|
||||
oss_name << "-" << setw(2) << t.hour << setw(2) << t.minute << setw(2) << t.second;
|
||||
oss_name << ".log";
|
||||
log_file_with_path_ += oss_name.str();
|
||||
|
||||
// open the log file
|
||||
std::ios_base::openmode mode = std::ios_base::out; // for clarity: it's really overkill since it's an ofstream
|
||||
mode |= std::ios_base::trunc;
|
||||
out.open(log_file_with_path_, mode);
|
||||
if(!out.is_open())
|
||||
{
|
||||
std::ostringstream ss_error;
|
||||
ss_error << "Fatal error could not open log file:[" << log_file_with_path_ << "]";
|
||||
ss_error << "\n\t\t std::ios_base state = " << out.rdstate();
|
||||
std::cerr << ss_error.str().c_str() << std::endl << std::flush;
|
||||
assert(false && "cannot open log file at startup");
|
||||
}
|
||||
std::ostringstream ss_entry;
|
||||
time_t creation_time;
|
||||
time(&creation_time);
|
||||
ss_entry << "\t\tg2log created log file at: " << ctime(&creation_time);
|
||||
ss_entry << "\t\tLOG format: [YYYY/MM/DD hh:mm:ss.uuu* LEVEL FILE:LINE] message\n\n";
|
||||
out << ss_entry.str() << std::flush;
|
||||
out.fill('0');
|
||||
}
|
||||
|
||||
LogWorkerImpl::~LogWorkerImpl()
|
||||
{
|
||||
std::ostringstream ss_exit;
|
||||
time_t exit_time;
|
||||
time(&exit_time);
|
||||
bg_.reset(); // flush the log queue
|
||||
ss_exit << "\n\t\tg2log file shutdown at: " << ctime(&exit_time);
|
||||
out << ss_exit.str() << std::flush;
|
||||
}
|
||||
|
||||
void LogWorkerImpl::backgroundFileWrite(LogEntry message)
|
||||
{
|
||||
using namespace std;
|
||||
LogTime t;
|
||||
auto timesnapshot = chrono::steady_clock::now();
|
||||
out << "\n" << t.year << "/" << setw(2) << t.month << "/" << setw(2) << t.day;
|
||||
out << " " << setw(2) << t.hour << ":"<< setw(2) << t.minute <<":"<< setw(2) << t.second;
|
||||
out << "." << chrono::duration_cast<microsecond>(timesnapshot - start_time_).count(); //microseconds
|
||||
out << "\t" << message;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// BELOW LogWorker
|
||||
// Public API implementation
|
||||
LogWorker::LogWorker(const std::string& log_prefix, const std::string& log_directory)
|
||||
: background_worker_(new PrivateLogWorker(log_prefix, log_directory))
|
||||
, log_file_with_path_(background_worker_->log_file_with_path_)
|
||||
: pimpl_(new LogWorkerImpl(log_prefix, log_directory))
|
||||
, log_file_with_path_(pimpl_->log_file_with_path_)
|
||||
{
|
||||
}
|
||||
|
||||
LogWorker::~LogWorker()
|
||||
{
|
||||
background_worker_.reset();
|
||||
pimpl_.reset();
|
||||
//std::cout << "\nLogWorker finished with log: " << log_file_with_path_ << std::endl << std::flush;
|
||||
}
|
||||
|
||||
void LogWorker::save(g2::internal::LogEntry msg)
|
||||
{
|
||||
background_worker_->bg_->send(std::tr1::bind(&PrivateLogWorker::backgroundFileWrite, background_worker_.get(), msg));
|
||||
pimpl_->bg_->send(std::tr1::bind(&LogWorkerImpl::backgroundFileWrite, pimpl_.get(), msg));
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,13 +7,10 @@
|
||||
*
|
||||
* PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
|
||||
* ********************************************* */
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "g2log.h"
|
||||
|
||||
class PrivateLogWorker;
|
||||
class LogWorkerImpl;
|
||||
|
||||
/**
|
||||
* \param log_prefix is the 'name' of the binary, this give the log name 'LOG-'name'-...
|
||||
@ -31,7 +28,7 @@ public:
|
||||
std::string logFileName() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<PrivateLogWorker> background_worker_;
|
||||
std::unique_ptr<LogWorkerImpl> pimpl_;
|
||||
const std::string log_file_with_path_;
|
||||
|
||||
LogWorker(const LogWorker&) = delete; // no assignment, no copy
|
||||
|
@ -1,101 +0,0 @@
|
||||
/* *************************************************
|
||||
* Filename: privatelogworker.cpp Framework for Logging and Design By Contract
|
||||
* Created: 2011 by Kjell Hedström
|
||||
*
|
||||
* PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
|
||||
* ********************************************* */
|
||||
|
||||
#include "privatelogworker.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
|
||||
using namespace g2::internal;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct LogTime
|
||||
{
|
||||
LogTime()
|
||||
{
|
||||
time_t current_time = time(nullptr);
|
||||
ctime(¤t_time); // fill with time right now
|
||||
struct tm* ptm = localtime(¤t_time); // fill time struct with data
|
||||
year = ptm->tm_year + 1900;
|
||||
month = (ptm->tm_mon) +1;
|
||||
day = ptm->tm_mday;
|
||||
hour = ptm->tm_hour;
|
||||
minute = ptm->tm_min;
|
||||
second = ptm->tm_sec;
|
||||
}
|
||||
int year; // Year - 1900
|
||||
int month; // [1-12]
|
||||
int day; // [1-31]
|
||||
int hour; // [0-23]
|
||||
int minute; // [0-59]
|
||||
int second; // [0-60], 1 leap second
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
|
||||
PrivateLogWorker::PrivateLogWorker(const std::string& log_prefix, const std::string& log_directory)
|
||||
: log_file_with_path_(log_directory)
|
||||
, bg_(kjellkod::Active::createActive())
|
||||
, start_time_(std::chrono::steady_clock::now())
|
||||
{
|
||||
using namespace std;
|
||||
LogTime t;
|
||||
ostringstream oss_name;
|
||||
oss_name.fill('0');
|
||||
oss_name << log_prefix << ".g2log.";
|
||||
oss_name << t.year << setw(2) << t.month << setw(2) << t.day;
|
||||
oss_name << "-" << setw(2) << t.hour << setw(2) << t.minute << setw(2) << t.second;
|
||||
oss_name << ".log";
|
||||
log_file_with_path_ += oss_name.str();
|
||||
|
||||
// open the log file
|
||||
std::ios_base::openmode mode = std::ios_base::out; // for clarity: it's really overkill since it's an ofstream
|
||||
mode |= std::ios_base::trunc;
|
||||
out.open(log_file_with_path_, mode);
|
||||
if(!out.is_open())
|
||||
{
|
||||
std::ostringstream ss_error;
|
||||
ss_error << "Fatal error could not open log file:[" << log_file_with_path_ << "]";
|
||||
ss_error << "\n\t\t std::ios_base state = " << out.rdstate();
|
||||
std::cerr << ss_error.str().c_str() << std::endl << std::flush;
|
||||
assert(false && "cannot open log file at startup");
|
||||
}
|
||||
std::ostringstream ss_entry;
|
||||
time_t creation_time;
|
||||
time(&creation_time);
|
||||
ss_entry << "\t\tg2log created log file at: " << ctime(&creation_time);
|
||||
ss_entry << "\t\tLOG format: [YYYY/MM/DD hh:mm:ss.uuu* LEVEL FILE:LINE] message\n\n";
|
||||
out << ss_entry.str() << std::flush;
|
||||
out.fill('0');
|
||||
}
|
||||
|
||||
PrivateLogWorker::~PrivateLogWorker()
|
||||
{
|
||||
std::ostringstream ss_exit;
|
||||
time_t exit_time;
|
||||
time(&exit_time);
|
||||
bg_.reset(); // flush the log queue
|
||||
ss_exit << "\n\t\tg2log file shutdown at: " << ctime(&exit_time);
|
||||
out << ss_exit.str() << std::flush;
|
||||
}
|
||||
|
||||
void PrivateLogWorker::backgroundFileWrite(LogEntry message)
|
||||
{
|
||||
using namespace std;
|
||||
LogTime t;
|
||||
auto timesnapshot = chrono::steady_clock::now();
|
||||
out << "\n" << t.year << "/" << setw(2) << t.month << "/" << setw(2) << t.day;
|
||||
out << " " << setw(2) << t.hour << ":"<< setw(2) << t.minute <<":"<< setw(2) << t.second;
|
||||
out << "." << chrono::duration_cast<microsecond>(timesnapshot - start_time_).count(); //microseconds
|
||||
out << "\t" << message;
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
/* *************************************************
|
||||
* Filename: privatelogworker.h Framework for Logging and Design By Contract
|
||||
* Created: 2011 by Kjell Hedström
|
||||
*
|
||||
* PUBLIC DOMAIN and Not copywrited. First published at KjellKod.cc
|
||||
* ********************************************* */
|
||||
|
||||
|
||||
#ifndef PRIVATE_LOG_WORKER_H_
|
||||
#define PRIVATE_LOG_WORKER_H_
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
#include "active.h"
|
||||
#include "g2log.h"
|
||||
|
||||
|
||||
|
||||
/** The actual background worker, while LogWorker gives the
|
||||
* asynchronous API to put job in the background the PrivateLogWorker
|
||||
* does the actual background thread work */
|
||||
struct PrivateLogWorker
|
||||
{
|
||||
PrivateLogWorker(const std::string& log_prefix, const std::string& log_directory);
|
||||
~PrivateLogWorker();
|
||||
|
||||
void backgroundFileWrite(g2::internal::LogEntry message);
|
||||
|
||||
std::string log_file_with_path_;
|
||||
std::unique_ptr<kjellkod::Active> bg_;
|
||||
std::ofstream out;
|
||||
g2::internal::time_point start_time_;
|
||||
|
||||
private:
|
||||
PrivateLogWorker& operator=(const PrivateLogWorker&) = delete; // no assignment, no copy
|
||||
PrivateLogWorker(const PrivateLogWorker& other) = delete;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -96,7 +96,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
oss.str("");
|
||||
oss << "Number of values rounded to tenths of ms dumped to file: " << g_measurement_bucket_dump << std::endl;
|
||||
oss << "Number of values rounted to milliseconds and put to [millisecond bucket] were dumped to file: " << g_measurement_bucket_dump << std::endl;
|
||||
oss << "Format: bucket_of_ms, number_of_values_in_bucket";
|
||||
std::cout << oss.str() << std::endl;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user