1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
| #pragma once
// pour creer un logger sur un autre fichier faire
// extern Logger xlogger("nom du fichier");
// pour changer le format d'affichage de l'heure
// extern Logger xlogger("nom du fichier", "format"); ou
// extern logger xlogger(string(), "format");
// le format est au standard strftime
// http://www.cplusplus.com/reference/ctime/strftime/
// avec mmm pour les millisecondes
#include <iostream>
#include <iomanip>
#include <locale>
#include <vector>
#include <algorithm>
#include <functional>
#include <fstream>
#include <mutex>
#include <shared_mutex>
#include <ctime>
#include <string.h>
#include <sstream>
#define DEFAULT_LOGGER_FILE_NAME "c:\\test2.txt" // nom du fichier log par defaut
#define DEFAULT_FOMRAT_TC "%H:%M:%S.mmm" // format de la date/heure (ici juste heure.milliseconde)
#define FORMAT_MILL "mmm" // indicateur de format pour les milliseconde (NE PAS MODIFIER)
#ifdef WIN32
#define localtime_r(_Time, _Tm) localtime_s(_Tm, _Time)
#endif
// nom du fichier
#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
// nom de la fonction
#ifndef __FUNCTION_NAME__
#if defined __func__
// Undeclared
#define __FUNCTION_NAME__ __func__
#elif defined __FUNCTION__
// Undeclared
#define __FUNCTION_NAME__ __FUNCTION__
#elif defined __PRETTY_FUNCTION__
// Undeclared
#define __FUNCTION_NAME__ __PRETTY_FUNCTION__
#else
// Declared
#define __FUNCTION_NAME__ "N/A"
#endif // __func__
#endif // __FUNCTION_NAME__
// simplifications
#define _LI_ __LINE__ // numero de ligne dans le fichier
#define _FN_ __FUNCTION_NAME__ // nom de la fonction
#define _FI_ __FILENAME__ // nom du fichier
using namespace std;
using namespace std::chrono;
class Logger
{
#pragma region private
private:
int lockcount = 0;
ofstream ofs;
recursive_mutex m;
string format;
void open(string filename) {
// ce code append ne met pas a jour le fichier immediatement
//ofs.open(LOGGER_FILE_NAME, std::ofstream::out | std::ofstream::app);
ofs.open(filename, std::ofstream::out);
}
void close() {
ofs.close();
}
void lock() {
m.lock();
// ajoute la date et l'heure sur lockcount = 0
if (lockcount == 0)
{
ofs << "[" << getTime() << "] ";
}
lockcount++;
}
void unlock() {
for (; lockcount != 0; m.unlock(), --lockcount);
}
//says does b contain a
bool isPartOf(char *a, char *b) {
return (strstr(b, a) != NULL);
}
const long millisecond() {
tm localTime;
system_clock::time_point t = system_clock::now();
time_t now = system_clock::to_time_t(t);
localtime_r(&now, &localTime);
const duration<double> tse = t.time_since_epoch();
seconds::rep milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(tse).count() % 1000;
return milliseconds;
}
const string getTime() {
struct tm time_info;
time_t time_create = time(NULL);
localtime_s(&time_info, &time_create);
char timebuf[80];
strftime(timebuf, 80, format.c_str(), &time_info);
string time_ret(timebuf);
if (isPartOf((char*)FORMAT_MILL, timebuf))
{
auto milli = millisecond();
ostringstream stringStream;
stringStream << setfill('0') << setw(3) << milli;
time_ret.replace(time_ret.find(FORMAT_MILL), sizeof(FORMAT_MILL) - 1, stringStream.str());
}
return time_ret;
}
#pragma endregion private
#pragma region public
public:
Logger(string filename = DEFAULT_LOGGER_FILE_NAME,
string formatDateTime = DEFAULT_FOMRAT_TC) : format(formatDateTime){
if (filename.empty()) filename = DEFAULT_LOGGER_FILE_NAME;
open(filename);
}
inline Logger &operator<<(const char *val) {
return operator<<(std::string(val));
}
inline Logger &operator<<(const std::string &val) {
#ifdef LOGGER
lock();
ofs << val;
ofs.flush();
#endif
return *this;
}
inline Logger &operator<<(const int val) {
#ifdef LOGGER
lock();
ofs << val;
ofs.flush();
#endif
return *this;
}
inline Logger &operator<<(const bool val) {
#ifdef LOGGER
lock();
ofs << val;
ofs.flush();
#endif
return *this;
}
inline Logger &operator<<(std::ostream&(*val)(std::ostream&)) {
#ifdef LOGGER
lock();
ofs << val << flush;
//close();
//open();
unlock();
#endif
return *this;
}
#pragma endregion public
};
extern Logger clogger; |
Partager