Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
108e42ce1f | ||
|
cef9c64e86 | ||
|
f6f7853062 | ||
|
b06129f345 | ||
ffc53a7ad5 | |||
|
db7f8ebd92 | ||
|
3a2f9fa12e | ||
|
b0dab7ac6e |
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
.vscode
|
.vscode
|
||||||
example/*
|
example
|
||||||
test/*.o
|
test/*.o
|
||||||
|
build
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -5,6 +5,9 @@
|
|||||||
"fstream": "cpp",
|
"fstream": "cpp",
|
||||||
"*.tcc": "cpp",
|
"*.tcc": "cpp",
|
||||||
"ostream": "cpp",
|
"ostream": "cpp",
|
||||||
"mutex": "cpp"
|
"mutex": "cpp",
|
||||||
|
"queue": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"string_view": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
30
CMakeLists.txt
Normal file
30
CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(log)
|
||||||
|
|
||||||
|
# Postavi verziju projekta
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Pronađi Boost biblioteku (ako nije uobičajeni direktorijum, postavi put)
|
||||||
|
# find_package(Boost REQUIRED COMPONENTS system)
|
||||||
|
|
||||||
|
# Dodaj direktorijume sa zaglavljima
|
||||||
|
include_directories(lib)
|
||||||
|
|
||||||
|
# Dodaj biblioteku
|
||||||
|
add_library(log STATIC
|
||||||
|
src/log.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# # Linkaj log biblioteku sa Boost-om
|
||||||
|
# target_link_libraries(log Boost::system)
|
||||||
|
|
||||||
|
# Dodaj testove
|
||||||
|
add_subdirectory(test)
|
||||||
|
|
||||||
|
|
||||||
|
# Instaliraj biblioteku
|
||||||
|
# install(TARGETS log DESTINATION lib)
|
||||||
|
# install(FILES lib/log.hpp lib/define.hpp lib/engine.hpp lib/filesystem.hpp lib/timers.hpp lib/trigger.hpp DESTINATION include/log)
|
||||||
|
#
|
57
README.md
57
README.md
@ -1,5 +1,60 @@
|
|||||||
|
|
||||||
# A simple Logging library for C++
|
# A simple Logging library for C++ programs
|
||||||
|
|
||||||
Logging errors to a file, daily file rotation, date and time stamps. Configurable record structure etc.
|
Logging errors to a file, daily file rotation, date and time stamps. Configurable record structure etc.
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Object oriented
|
||||||
|
- Customizable directory for files
|
||||||
|
- Daily file rotation
|
||||||
|
- Protection of recording consecutive errors
|
||||||
|
- Log levels
|
||||||
|
- Thread safe
|
||||||
|
- Exceptions
|
||||||
|
- The possibility of printing logs in the console
|
||||||
|
- Ability to keep log file open for faster speed
|
||||||
|
- Supports multiple simultaneous log files by custom directories
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Just download the latest release and unzip it into your project. You can turn it on with:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include "log/lib/log.hpp"
|
||||||
|
using namespace marcelb;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```c++
|
||||||
|
/**
|
||||||
|
* Initialization and declaration
|
||||||
|
*/
|
||||||
|
log mylog("../log", Level::INFO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put log in file
|
||||||
|
*/
|
||||||
|
mylog.debug("Debug loging");
|
||||||
|
mylog.info("Info loging");
|
||||||
|
mylog.warning("Warning loging");
|
||||||
|
mylog.error("Error loging");
|
||||||
|
mylog.fatal("Fatal loging");
|
||||||
|
```
|
||||||
|
## License
|
||||||
|
|
||||||
|
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)
|
||||||
|
|
||||||
|
|
||||||
|
## Support & Feedback
|
||||||
|
|
||||||
|
For support and any feedback, contact the address: marcelb96@yahoo.com.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are always welcome!
|
||||||
|
|
||||||
|
Feel free to fork and start working with or without a later pull request. Or contact for suggest and request an option.
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
23:08:58 [EVENT] Start loging
|
|
@ -1,3 +0,0 @@
|
|||||||
18:29:30 [EVENT] Start loging
|
|
||||||
18:29:44 [EVENT] Start loging
|
|
||||||
18:29:47 [EVENT] Start loging
|
|
@ -1,5 +0,0 @@
|
|||||||
[EVENT] Start loging
|
|
||||||
[EVENT] Start loging
|
|
||||||
10:58:12 [EVENT] Start loging
|
|
||||||
10:59:19 [EVENT] Start loging
|
|
||||||
11:00:17 [EVENT] Start loging
|
|
@ -1,2 +0,0 @@
|
|||||||
11:00:58 [EVENT] Start loging
|
|
||||||
13:02:17 [EVENT] Start loging
|
|
115
lib/log.hpp
115
lib/log.hpp
@ -4,18 +4,35 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
typedef unsigned int uint;
|
||||||
|
#endif
|
||||||
namespace marcelb {
|
namespace marcelb {
|
||||||
|
namespace logging {
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DEBUG = 0,
|
||||||
|
INFO,
|
||||||
|
WARNING,
|
||||||
|
ERROR,
|
||||||
|
FATAL,
|
||||||
|
} Level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log class - used at the level of one log directory
|
||||||
|
*/
|
||||||
class log {
|
class log {
|
||||||
public:
|
|
||||||
string dir;
|
string dir;
|
||||||
|
Level loglevel;
|
||||||
bool isKeepOpen;
|
bool isKeepOpen;
|
||||||
bool printInConsole;
|
bool printInConsole;
|
||||||
ofstream logfile;
|
ofstream logfile;
|
||||||
@ -23,20 +40,100 @@ class log {
|
|||||||
uint day;
|
uint day;
|
||||||
string path;
|
string path;
|
||||||
mutex io;
|
mutex io;
|
||||||
|
uint32_t groupedWriting;
|
||||||
|
time_t lastWriting;
|
||||||
|
queue<string> toWrite;
|
||||||
|
|
||||||
log (string _dir, bool _isKeepOpen = true, bool _printInConsole = false);
|
/**
|
||||||
|
* Checking if the path is in the string dir directory
|
||||||
|
*/
|
||||||
bool isdir();
|
bool isdir();
|
||||||
bool open();
|
|
||||||
void loose();
|
|
||||||
void setMoment();
|
|
||||||
void setPath();
|
|
||||||
void put(string logline);
|
|
||||||
void setPrefix(string &logline);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the log file
|
||||||
|
*/
|
||||||
|
bool open();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the log file
|
||||||
|
*/
|
||||||
|
void loose();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get time
|
||||||
|
*/
|
||||||
|
void setMoment();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate full log file path
|
||||||
|
*/
|
||||||
|
void setPath();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set log line time prefix
|
||||||
|
*/
|
||||||
|
void setPrefix(string &logline, Level &_level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put string log in file
|
||||||
|
*/
|
||||||
|
void put(string logline, Level _level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to log file
|
||||||
|
*/
|
||||||
|
|
||||||
|
void write(string logline);
|
||||||
|
|
||||||
|
void midnight();
|
||||||
|
|
||||||
|
void writeQueue();
|
||||||
|
|
||||||
|
bool writableQueue();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor,
|
||||||
|
* receives the log directory path,
|
||||||
|
* optional: a bool variable if it keeps the file open,
|
||||||
|
* and a bool variable if it prints log lines to the console
|
||||||
|
*/
|
||||||
|
log (string _dir, Level loglevel = WARNING, bool _isKeepOpen = true, bool _printInConsole = false, uint32_t groupedWriting = 0);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug log line
|
||||||
|
*/
|
||||||
|
void debug(string logline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Info log line
|
||||||
|
*/
|
||||||
|
void info(string logline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning log line
|
||||||
|
*/
|
||||||
|
void warning(string logline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error log line
|
||||||
|
*/
|
||||||
|
void error(string logline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fatal log line
|
||||||
|
*/
|
||||||
|
void fatal(string logline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destruktor, close log files
|
||||||
|
*/
|
||||||
~log();
|
~log();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
146
src/log.cpp
146
src/log.cpp
@ -1,9 +1,14 @@
|
|||||||
#include "../lib/log.hpp"
|
#include "../lib/log.hpp"
|
||||||
|
|
||||||
marcelb::log::log(string _dir, bool _isKeepOpen, bool _printInConsole) {
|
namespace marcelb {
|
||||||
|
namespace logging {
|
||||||
|
|
||||||
|
log::log(string _dir, Level _loglevel, bool _isKeepOpen, bool _printInConsole, uint32_t _groupedWriting) {
|
||||||
dir = _dir;
|
dir = _dir;
|
||||||
|
loglevel = _loglevel;
|
||||||
isKeepOpen = _isKeepOpen;
|
isKeepOpen = _isKeepOpen;
|
||||||
printInConsole = _printInConsole;
|
printInConsole = _printInConsole;
|
||||||
|
groupedWriting = _groupedWriting;
|
||||||
|
|
||||||
if (!isdir()) {
|
if (!isdir()) {
|
||||||
throw string("[ERROR] Log dir path invalid ");
|
throw string("[ERROR] Log dir path invalid ");
|
||||||
@ -11,6 +16,9 @@ marcelb::log::log(string _dir, bool _isKeepOpen, bool _printInConsole) {
|
|||||||
|
|
||||||
setMoment();
|
setMoment();
|
||||||
day = moment->tm_mday;
|
day = moment->tm_mday;
|
||||||
|
if (groupedWriting) {
|
||||||
|
lastWriting = timelocal(moment);
|
||||||
|
}
|
||||||
setPath();
|
setPath();
|
||||||
|
|
||||||
if (isKeepOpen) {
|
if (isKeepOpen) {
|
||||||
@ -21,49 +29,53 @@ marcelb::log::log(string _dir, bool _isKeepOpen, bool _printInConsole) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool marcelb::log::isdir() {
|
bool log::isdir() {
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
return stat(dir.c_str(), &sb) == 0;
|
return stat(dir.c_str(), &sb) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool marcelb::log::open() {
|
bool log::open() {
|
||||||
logfile = ofstream (path, ios_base::app);
|
logfile = ofstream (path, ios_base::app);
|
||||||
return logfile.is_open();
|
return logfile.is_open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void marcelb::log::loose() {
|
void log::loose() {
|
||||||
logfile.close();
|
logfile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void marcelb::log::setMoment() {
|
void log::setMoment() {
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
time (&rawtime);
|
time (&rawtime);
|
||||||
moment = localtime (&rawtime);
|
moment = localtime (&rawtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void marcelb::log::put(string logline) {
|
void log::put(string logline, Level _level) {
|
||||||
|
if (_level < loglevel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
io.lock();
|
io.lock();
|
||||||
if (printInConsole) {
|
if (printInConsole) {
|
||||||
cout << logline << endl;
|
cout << logline << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMoment();
|
setMoment();
|
||||||
setPrefix(logline);
|
setPrefix(logline, _level);
|
||||||
|
midnight();
|
||||||
|
|
||||||
if (day != moment->tm_mday) {
|
if (groupedWriting) {
|
||||||
if (isKeepOpen && logfile.is_open()) {
|
toWrite.push(logline);
|
||||||
loose();
|
if (writableQueue()) {
|
||||||
}
|
writeQueue();
|
||||||
day = moment->tm_mday;
|
|
||||||
setPath();
|
|
||||||
if (isKeepOpen) {
|
|
||||||
if (!open()) {
|
|
||||||
throw string("[ERROR] Opening log file! ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
write(logline);
|
||||||
}
|
}
|
||||||
|
io.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void log::write(string logline) {
|
||||||
if (!isKeepOpen || !logfile.is_open()) {
|
if (!isKeepOpen || !logfile.is_open()) {
|
||||||
if (!open()) {
|
if (!open()) {
|
||||||
throw string("[ERROR] Opening log file! ");
|
throw string("[ERROR] Opening log file! ");
|
||||||
@ -75,11 +87,52 @@ void marcelb::log::put(string logline) {
|
|||||||
if (!isKeepOpen && logfile.is_open()) {
|
if (!isKeepOpen && logfile.is_open()) {
|
||||||
loose();
|
loose();
|
||||||
}
|
}
|
||||||
io.unlock();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void marcelb::log::setPath() {
|
void log::midnight() {
|
||||||
|
if (day != moment->tm_mday) {
|
||||||
|
if (groupedWriting && !toWrite.empty()) {
|
||||||
|
writeQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isKeepOpen && logfile.is_open()) {
|
||||||
|
loose();
|
||||||
|
}
|
||||||
|
day = moment->tm_mday;
|
||||||
|
setPath();
|
||||||
|
if (isKeepOpen) {
|
||||||
|
if (!open()) {
|
||||||
|
throw string("[ERROR] Opening log file! ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void log::writeQueue() {
|
||||||
|
string lines;
|
||||||
|
bool notEmpty = !toWrite.empty();
|
||||||
|
|
||||||
|
while (notEmpty) {
|
||||||
|
lines += toWrite.front();
|
||||||
|
toWrite.pop();
|
||||||
|
notEmpty = !toWrite.empty();
|
||||||
|
if (notEmpty) lines += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
write(lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool log::writableQueue() {
|
||||||
|
bool _writable = false;
|
||||||
|
auto _time = timelocal(moment);
|
||||||
|
if (_time > lastWriting + groupedWriting) {
|
||||||
|
_writable = true;
|
||||||
|
lastWriting = _time;
|
||||||
|
}
|
||||||
|
return _writable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log::setPath() {
|
||||||
if (dir[dir.length()-1] != '/') {
|
if (dir[dir.length()-1] != '/') {
|
||||||
dir.push_back('/');
|
dir.push_back('/');
|
||||||
}
|
}
|
||||||
@ -90,17 +143,62 @@ void marcelb::log::setPath() {
|
|||||||
path = dir + to_string(moment->tm_year+1900) + '-' + mon.str() + '-' + _day.str() + ".log";
|
path = dir + to_string(moment->tm_year+1900) + '-' + mon.str() + '-' + _day.str() + ".log";
|
||||||
}
|
}
|
||||||
|
|
||||||
void marcelb::log::setPrefix(string &logline) {
|
void log::setPrefix(string &logline, Level &_level) {
|
||||||
stringstream hour, min, sec;
|
stringstream hour, min, sec;
|
||||||
hour << setw(2) << setfill('0') << moment->tm_hour;
|
hour << setw(2) << setfill('0') << moment->tm_hour;
|
||||||
min << setw(2) << setfill('0') << moment->tm_min;
|
min << setw(2) << setfill('0') << moment->tm_min;
|
||||||
sec << setw(2) << setfill('0') << moment->tm_sec;
|
sec << setw(2) << setfill('0') << moment->tm_sec;
|
||||||
|
|
||||||
string _logline = hour.str() + ':' + min.str() + ':' + sec.str() + ' ' + logline;
|
string _logline = hour.str() + ':' + min.str() + ':' + sec.str();// + logline;
|
||||||
logline = _logline;
|
switch (_level) {
|
||||||
|
case DEBUG:
|
||||||
|
_logline += " [DEBUG] ";
|
||||||
|
break;
|
||||||
|
case INFO:
|
||||||
|
_logline += " [INFO] ";
|
||||||
|
break;
|
||||||
|
case WARNING:
|
||||||
|
_logline += " [WARNING] ";
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
_logline += " [ERROR] ";
|
||||||
|
break;
|
||||||
|
case FATAL:
|
||||||
|
_logline += " [FATAL] ";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_logline += " [UNAKOWN] ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
logline = _logline + logline;
|
||||||
}
|
}
|
||||||
|
|
||||||
marcelb::log::~log() {
|
void log::debug(string logline) {
|
||||||
|
put(logline, DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log::info(string logline) {
|
||||||
|
put(logline, INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log::warning(string logline) {
|
||||||
|
put(logline, WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log::error(string logline) {
|
||||||
|
put(logline, ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log::fatal(string logline) {
|
||||||
|
put(logline, FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
log::~log() {
|
||||||
loose();
|
loose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3
test/CMakeLists.txt
Normal file
3
test/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
add_executable(log_test test.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(log_test log)
|
@ -1,17 +1,25 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "../lib/log.hpp"
|
#include "../lib/log.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace marcelb;
|
using namespace marcelb::logging;
|
||||||
|
|
||||||
log mylog("../example", false);
|
log mylog("../example", Level::DEBUG, true, false, 5);
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
// mylog.debug("Start debug loging");
|
||||||
|
// mylog.info("Start info loging");
|
||||||
|
// mylog.warning("Start warning loging");
|
||||||
|
// mylog.error("Start error loging");
|
||||||
|
// mylog.fatal("Start fatal loging");
|
||||||
|
|
||||||
// log mylog("../example", false);
|
int i = 0;
|
||||||
|
while(true) {
|
||||||
mylog.put("[EVENT] Start loging");
|
mylog.fatal("Test fatal error: "+ to_string(i++));
|
||||||
|
sleep(2);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
BIN
test/test.o
BIN
test/test.o
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user