forked from X-Profiler/xprofiler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogger.cc
200 lines (172 loc) · 5.53 KB
/
logger.cc
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include <stdarg.h>
#include <fstream>
#include "uv.h"
#ifdef _WIN32
#include <time.h>
#endif
#include "configure.h"
#include "platform/platform.h"
namespace xprofiler {
using Nan::New;
using Nan::ThrowTypeError;
using Nan::To;
using Nan::Utf8String;
using std::string;
using std::to_string;
using v8::Local;
using v8::String;
#define WRITET_TO_FILE(type) \
uv_mutex_lock(&logger_mutex); \
type##_stream.open(filepath, std::ios::app); \
type##_stream << log; \
type##_stream.close(); \
uv_mutex_unlock(&logger_mutex);
#define LOG_WITH_LEVEL(level) \
va_list args; \
va_start(args, format); \
Log(LOG_LEVEL::level, log_type, format, args); \
va_end(args);
#define JS_LOG_WITH_LEVEL(level) \
if (!info[0]->IsString() || !info[1]->IsString()) { \
ThrowTypeError( \
New<String>("log type and content must be string!").ToLocalChecked()); \
return; \
} \
Local<String> log_type_string = To<String>(info[0]).ToLocalChecked(); \
Utf8String log_type(log_type_string); \
Local<String> log_content_string = To<String>(info[1]).ToLocalChecked(); \
Utf8String log_content(log_content_string); \
Log(LOG_LEVEL::level, *log_type, *log_content);
static const int kMaxMessageLength = 2048;
static const int kMaxFormatLength = 2048;
static uv_mutex_t logger_mutex;
// output
static std::ofstream info_stream;
static std::ofstream error_stream;
static std::ofstream debug_stream;
static void WriteToFile(const LOG_LEVEL output_level, char *log) {
// get time of date
char time_string_day[32];
time_t tt = time(NULL);
struct tm *ptm = localtime(&tt);
strftime(time_string_day, sizeof(time_string_day), "%Y%m%d", ptm);
// get filepath and write to file
string log_dir = GetLogDir();
string filepath = log_dir + GetSep();
bool log_format_alinode = GetFormatAsAlinode();
string file_prefix = "xprofiler-";
if (log_format_alinode) {
file_prefix = "node-";
}
switch (output_level) {
case LOG_LEVEL::LOG_INFO:
filepath += file_prefix + time_string_day + ".log";
WRITET_TO_FILE(info)
break;
case LOG_LEVEL::LOG_ERROR:
filepath += file_prefix + "error-" + time_string_day + ".log";
WRITET_TO_FILE(error)
break;
case LOG_LEVEL::LOG_DEBUG:
filepath += file_prefix + "debug-" + time_string_day + ".log";
WRITET_TO_FILE(debug)
break;
default:
break;
}
}
static void Log(const LOG_LEVEL output_level, const char *type,
const char *format, va_list arglist = nullptr) {
LOG_LEVEL level = GetLogLevel();
if (level < output_level) {
return;
}
// check if alinode
bool log_format_alinode = GetFormatAsAlinode();
// time of day
char time_string_ms[64];
char time_string_ms_alinode[64];
time_t tt = time(NULL);
struct tm *ptm = localtime(&tt);
strftime(time_string_ms, sizeof(time_string_ms), "%Y-%m-%d %H:%M:%S", ptm);
if (log_format_alinode) {
uv_timeval64_t tv;
uv_gettimeofday(&tv);
snprintf(time_string_ms_alinode, sizeof(time_string_ms_alinode), "%s.%06d",
time_string_ms, tv.tv_usec);
}
// log level
string level_string = "";
switch (output_level) {
case LOG_LEVEL::LOG_INFO:
level_string = "info";
break;
case LOG_LEVEL::LOG_ERROR:
level_string = "error";
break;
case LOG_LEVEL::LOG_DEBUG:
level_string = "debug";
break;
default:
level_string = "unknown";
break;
}
// get pid
string pid = to_string(GetPid());
// add log prefix
char tmp_format[kMaxFormatLength];
if (log_format_alinode) {
snprintf(tmp_format, sizeof(tmp_format), "[%s] [%s] [%s] [%s] %s\n",
time_string_ms_alinode, level_string.c_str(), type, pid.c_str(),
format);
} else {
snprintf(tmp_format, sizeof(tmp_format), "[%s] [%s] [%s] [%s] [%s] %s\n",
time_string_ms, level_string.c_str(), type, pid.c_str(),
XPROFILER_VERSION, format);
}
// compose log
char tmp_log[kMaxMessageLength];
if (arglist != nullptr)
vsnprintf(tmp_log, sizeof(tmp_log), tmp_format, arglist);
else
snprintf(tmp_log, sizeof(tmp_log), "%s", tmp_format);
// get log type
switch (GetLogType()) {
// tty
case LOG_TYPE::LOG_TO_TTL:
printf("%s", tmp_log);
WriteToFile(output_level, tmp_log);
break;
// file
case LOG_TYPE::LOG_TO_FILE:
WriteToFile(output_level, tmp_log);
break;
default:
break;
}
}
int InitLogger() {
int rc = uv_mutex_init(&logger_mutex);
return rc;
}
/* native logger */
void Info(const char *log_type, const char *format, ...) {
LOG_WITH_LEVEL(LOG_INFO)
}
void Error(const char *log_type, const char *format, ...) {
LOG_WITH_LEVEL(LOG_ERROR)
}
void Debug(const char *log_type, const char *format, ...) {
LOG_WITH_LEVEL(LOG_DEBUG)
}
/* js binding logger */
void JsInfo(const FunctionCallbackInfo<Value> &info) {
JS_LOG_WITH_LEVEL(LOG_INFO)
}
void JsError(const FunctionCallbackInfo<Value> &info) {
JS_LOG_WITH_LEVEL(LOG_ERROR)
}
void JsDebug(const FunctionCallbackInfo<Value> &info) {
JS_LOG_WITH_LEVEL(LOG_DEBUG)
}
}; // namespace xprofiler