Skip to content

Instantly share code, notes, and snippets.

@607011
Last active May 23, 2019 13:24
Show Gist options
  • Save 607011/c187ee1d9339055f8dd3f3812abbd7fc to your computer and use it in GitHub Desktop.
Save 607011/c187ee1d9339055f8dd3f3812abbd7fc to your computer and use it in GitHub Desktop.
Simple log-to-file singleton

Logging facility for C++

Implemented as a singleton (eager as well as lazy).

main.cpp shows how to use it.

Compile with

cmake .
make

Launch with

./loggerdemo
app.log
.vscode/
build/
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
Makefile
loggerdemo
cmake_minimum_required (VERSION 2.6)
project(loggerdemo)
set(CMAKE_CXX_FLAGS
"-O2 -std=c++11")
set(HEADER_FILES
lazylogger.hpp)
add_executable(loggerdemo
main.cpp
lazylogger.cpp
)
#include "lazylogger.hpp"
Logger *Logger::logger = nullptr;
#ifndef __LAZYLOGGER_HPP__
#define __LAZYLOGGER_HPP__
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
class Logger {
private:
ofstream f;
static Logger *logger;
Logger() { /* ... */ }
~Logger() {
f.close();
}
public:
static Logger *instance() {
static Cleaner cleaner;
if (logger == nullptr) {
logger = new Logger;
}
return logger;
}
static void init(const string &filename) {
if (instance()->f.is_open()) {
throw runtime_error{ "Logger already initialized" };
}
instance()->f.open(filename,
ios::binary | ios::app);
}
Logger(const Logger &) = delete;
Logger& operator=(const Logger &) = delete;
void out(const string &msg) {
if (!instance()->f.is_open()) {
throw runtime_error{ "Logger not initialized" };
}
time_t t = time(nullptr);
stringstream ss;
ss << put_time(localtime(&t),
"%Y-%m-%dT%H:%M:%S ")
<< msg << endl;
f << ss.str();
}
void flush() {
f.flush();
}
class Cleaner {
public:
~Cleaner() {
if (Logger::logger != nullptr) {
delete Logger::logger;
Logger::logger = nullptr;
}
}
};
};
#endif // __LAZYLOGGER_HPP__
#ifndef __LOGGER_HPP__
#define __LOGGER_HPP__
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <mutex>
using namespace std;
class Logger {
private:
mutex mtx;
ofstream f;
Logger() = default;
Logger(const Logger&)
= delete;
Logger& operator=(const Logger&)
= delete;
~Logger() {
f.close();
}
public:
static Logger &instance() {
static Logger logger;
return logger;
}
static void init(const string &filename) {
if (instance().f.is_open()) {
throw runtime_error{ "Logger already initialized" };
}
instance().f.open(filename,
ios::binary | ios::app);
}
void out(const string &msg) {
unique_lock<mutex> lock(mtx);
time_t t = time(nullptr);
stringstream ss;
ss << put_time(localtime(&t),
"%Y-%m-%dT%H:%M:%S ")
<< msg << endl;
f << ss.str();
}
void flush() {
f.flush();
}
};
#endif
#include "lazylogger.hpp"
#include <string>
int main(int argc, char *argv[]) {
std::string msg = (argc > 1)
? argv[1]
: "lorem ipsum ...";
Logger::init("app.log");
Logger *logger = Logger::instance();
logger->out(msg);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment