Compare commits

..

No commits in common. "dev" and "v0.3" have entirely different histories.
dev ... v0.3

13 changed files with 49 additions and 333 deletions

3
.gitignore vendored
View File

@ -1,4 +1,3 @@
.vscode .vscode
example example/*
test/*.o test/*.o
build

View File

@ -5,9 +5,6 @@
"fstream": "cpp", "fstream": "cpp",
"*.tcc": "cpp", "*.tcc": "cpp",
"ostream": "cpp", "ostream": "cpp",
"mutex": "cpp", "mutex": "cpp"
"queue": "cpp",
"array": "cpp",
"string_view": "cpp"
} }
} }

View File

@ -1,30 +0,0 @@
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)
#

View File

@ -1,60 +1,5 @@
# A simple Logging library for C++ programs # A simple Logging library for C++
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
example/2023-05-21.log Normal file
View File

@ -0,0 +1 @@
23:08:58 [EVENT] Start loging

3
example/2023-07-27.log Normal file
View File

@ -0,0 +1,3 @@
18:29:30 [EVENT] Start loging
18:29:44 [EVENT] Start loging
18:29:47 [EVENT] Start loging

5
example/2023-5-20.log Normal file
View File

@ -0,0 +1,5 @@
[EVENT] Start loging
[EVENT] Start loging
10:58:12 [EVENT] Start loging
10:59:19 [EVENT] Start loging
11:00:17 [EVENT] Start loging

2
example/2023-5-21.log Normal file
View File

@ -0,0 +1,2 @@
11:00:58 [EVENT] Start loging
13:02:17 [EVENT] Start loging

View File

@ -4,35 +4,18 @@
#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;
@ -40,100 +23,20 @@ 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();
/**
* Opens the log file
*/
bool open(); bool open();
/**
* Closes the log file
*/
void loose(); void loose();
/**
* Get time
*/
void setMoment(); void setMoment();
/**
* Generate full log file path
*/
void setPath(); void setPath();
void put(string logline);
void setPrefix(string &logline);
/**
* 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

View File

@ -1,14 +1,9 @@
#include "../lib/log.hpp" #include "../lib/log.hpp"
namespace marcelb { marcelb::log::log(string _dir, bool _isKeepOpen, bool _printInConsole) {
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 ");
@ -16,9 +11,6 @@ log::log(string _dir, Level _loglevel, bool _isKeepOpen, bool _printInConsole, u
setMoment(); setMoment();
day = moment->tm_mday; day = moment->tm_mday;
if (groupedWriting) {
lastWriting = timelocal(moment);
}
setPath(); setPath();
if (isKeepOpen) { if (isKeepOpen) {
@ -29,72 +21,37 @@ log::log(string _dir, Level _loglevel, bool _isKeepOpen, bool _printInConsole, u
} }
bool log::isdir() { bool marcelb::log::isdir() {
struct stat sb; struct stat sb;
return stat(dir.c_str(), &sb) == 0; return stat(dir.c_str(), &sb) == 0;
} }
bool log::open() { bool marcelb::log::open() {
logfile = ofstream (path, ios_base::app); logfile = ofstream (path, ios_base::app);
return logfile.is_open(); return logfile.is_open();
} }
void log::loose() { void marcelb::log::loose() {
logfile.close(); logfile.close();
} }
void log::setMoment() { void marcelb::log::setMoment() {
time_t rawtime; time_t rawtime;
time (&rawtime); time (&rawtime);
moment = localtime (&rawtime); moment = localtime (&rawtime);
} }
void log::put(string logline, Level _level) { void marcelb::log::put(string logline) {
if (_level < loglevel) {
return;
}
io.lock(); io.lock();
if (printInConsole) { if (printInConsole) {
cout << logline << endl; cout << logline << endl;
} }
setMoment(); setMoment();
setPrefix(logline, _level); setPrefix(logline);
midnight();
if (groupedWriting) {
toWrite.push(logline);
if (writableQueue()) {
writeQueue();
}
} else {
write(logline);
}
io.unlock();
}
void log::write(string logline) {
if (!isKeepOpen || !logfile.is_open()) {
if (!open()) {
throw string("[ERROR] Opening log file! ");
}
}
logfile << logline << endl;
if (!isKeepOpen && logfile.is_open()) {
loose();
}
}
void log::midnight() {
if (day != moment->tm_mday) { if (day != moment->tm_mday) {
if (groupedWriting && !toWrite.empty()) {
writeQueue();
}
if (isKeepOpen && logfile.is_open()) { if (isKeepOpen && logfile.is_open()) {
loose(); loose();
} }
@ -106,33 +63,23 @@ void log::midnight() {
} }
} }
} }
}
void log::writeQueue() { if (!isKeepOpen || !logfile.is_open()) {
string lines; if (!open()) {
bool notEmpty = !toWrite.empty(); throw string("[ERROR] Opening log file! ");
}
while (notEmpty) {
lines += toWrite.front();
toWrite.pop();
notEmpty = !toWrite.empty();
if (notEmpty) lines += "\n";
} }
write(lines); logfile << logline << endl;
}
bool log::writableQueue() { if (!isKeepOpen && logfile.is_open()) {
bool _writable = false; loose();
auto _time = timelocal(moment);
if (_time > lastWriting + groupedWriting) {
_writable = true;
lastWriting = _time;
} }
return _writable; io.unlock();
} }
void log::setPath() { void marcelb::log::setPath() {
if (dir[dir.length()-1] != '/') { if (dir[dir.length()-1] != '/') {
dir.push_back('/'); dir.push_back('/');
} }
@ -143,62 +90,17 @@ void 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 log::setPrefix(string &logline, Level &_level) { void marcelb::log::setPrefix(string &logline) {
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;
switch (_level) { logline = _logline;
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;
} }
void log::debug(string logline) { marcelb::log::~log() {
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();
} }
}
}

View File

@ -1,3 +0,0 @@
add_executable(log_test test.cpp)
target_link_libraries(log_test log)

View File

@ -1,25 +1,17 @@
#include <iostream> #include <iostream>
#include <unistd.h>
#include "../lib/log.hpp" #include "../lib/log.hpp"
using namespace std; using namespace std;
using namespace marcelb::logging; using namespace marcelb;
log mylog("../example", Level::DEBUG, true, false, 5); log mylog("../example", false);
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");
int i = 0; // log mylog("../example", false);
while(true) {
mylog.fatal("Test fatal error: "+ to_string(i++)); mylog.put("[EVENT] Start loging");
sleep(2);
}
return 0; return 0;
} }

BIN
test/test.o Executable file

Binary file not shown.