-
Notifications
You must be signed in to change notification settings - Fork 0
/
simple_log.hpp
151 lines (131 loc) · 3.52 KB
/
simple_log.hpp
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
#ifndef __SIMPLE_LOG_HPP__
#define __SIMPLE_LOG_HPP__
#ifdef SIMPLE_LOG_FILENAME
#define USER_DEFINE_SIMPLE_LOG_FILENAME SIMPLE_LOG_FILENAME
#endif
#ifdef SIMPLE_LOG_NO_PRINT
#define USE_DEFINE_SIMPLE_LOG_NO_PRINT
#else
#include <iostream>
#endif
#include <chrono>
#include <fstream>
#include <string>
#include <string_view>
#if defined(PLATFORM_POSIX) || defined(__linux__)
#include <mutex>
#endif
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <libloaderapi.h>
inline void localtime_r(const time_t* tp, tm* tm) { localtime_s(tm, tp); }
#endif
namespace simplelog {
class Log {
public:
static void FormatLog(std::string_view log_type, std::string_view log_content);
static void Info(std::string_view log_content);
static void Error(std::string_view log_content);
static void Debug(std::string_view log_content);
static bool IsOpen();
~Log();
protected:
Log();
static Log& Instance();
static constexpr std::string_view log_prefix_buffer_format = "[YYYY-mm-dd HH:MM:ss.";
static constexpr size_t log_prefix_buffer_size = log_prefix_buffer_format.size() + 1;
static constexpr std::string_view log_prefix_format = "[%Y-%m-%d %H:%M:%S.";
std::ofstream ofs_;
bool has_open_;
#if defined(PLATFORM_POSIX) || defined(__linux__)
std::mutex mu_;
#endif
};
inline std::string GetLogName()
{
#ifdef USER_DEFINE_SIMPLE_LOG_FILENAME
return USER_DEFINE_SIMPLE_LOG_FILENAME;
#endif
std::string log_filename;
#if defined(PLATFORM_POSIX) || defined(__linux__)
std::ifstream("/proc/self/comm") >> log_filename;
#elif defined(_WIN32)
char buf[MAX_PATH + 1];
GetModuleFileNameA(nullptr, buf, MAX_PATH);
log_filename = buf;
#else
static_assert(false, "unrecognized platform");
#endif
size_t pos = log_filename.find_last_of("\\/");
if (pos != std::string::npos)
log_filename = log_filename.substr(pos + 1);
pos = log_filename.rfind(".");
if (pos != std::string::npos)
log_filename = log_filename.substr(0, pos);
return log_filename + ".log";
}
inline void Log::FormatLog(std::string_view log_type, std::string_view log_content)
{
auto now = std::chrono::system_clock::now().time_since_epoch();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
auto s = std::chrono::duration_cast<std::chrono::seconds>(now).count();
tm tm;
localtime_r(&s, &tm);
char time_prefix_buffer[log_prefix_buffer_size];
strftime(time_prefix_buffer, log_prefix_buffer_size, log_prefix_format.data(), &tm);
std::string log_buffer(time_prefix_buffer);
ms -= s * 1000;
if (ms < 100)
log_buffer += '0';
if (ms < 10)
log_buffer += '0';
log_buffer += std::to_string(ms);
log_buffer += "] [";
log_buffer += log_type;
log_buffer += "] ";
log_buffer += log_content;
log_buffer += '\n';
#ifndef USE_DEFINE_SIMPLE_LOG_NO_PRINT
std::cout << log_buffer;
#endif
if (IsOpen()) {
#if defined(PLATFORM_POSIX) || defined(__linux__)
std::lock_guard<std::mutex> lg(Instance().mu_);
#endif
Instance().ofs_ << log_buffer;
}
}
inline void Log::Info(std::string_view log_content)
{
FormatLog("INFO", log_content);
}
inline void Log::Error(std::string_view log_content)
{
FormatLog("ERROR", log_content);
}
inline void Log::Debug(std::string_view log_content)
{
#ifndef NDEBUG
FormatLog("DEBUG", log_content);
#endif
}
inline bool Log::IsOpen()
{
return Instance().has_open_;
}
inline Log::Log()
: ofs_(GetLogName(), std::ios_base::app)
, has_open_(ofs_.is_open())
{
}
inline Log& Log::Instance()
{
static Log log;
return log;
}
inline Log::~Log()
{
}
}
#endif