-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathgemfield.h
151 lines (138 loc) · 5.53 KB
/
gemfield.h
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
/*
* Copyright (c) 2020 gemfield <gemfield@civilnet.cn>
* This file is part of libgemfield.so (https://github.com/civilnet/gemfield).
* Licensed under the GPLv3 (the "License")
* You may not use this file except in compliance with the License.
*/
#ifndef _GEMFIELD_H_
#define _GEMFIELD_H_
#include <initializer_list>
#include <iostream>
#include <sstream>
#include <mutex>
#include <thread>
#include <map>
#include <fstream>
namespace gemfield_org{
enum LOG_LEVEL{
STACK_INFO = 0,
DETAIL_INFO = 1,
INFO = 2,
WARNING = 5,
ERROR = 6
};
}
namespace gemfield_org{
const LOG_LEVEL global_log_level = DETAIL_INFO;
class LogFromFile{
public:
LogFromFile(){
std::cout<<"GEMFIELD INITIALIZATION ONLY ONCE!"<<std::endl;
try{
std::ifstream infile("gemfield.loglevel");
std::string line;
while (std::getline(infile, line)) {
std::istringstream iss(line);
std::string k;
int v;
if (!(iss >> k >> v)) {
break;
}
if(k == "LOGLEVEL"){
log_level_ = static_cast<LOG_LEVEL>(v);
break;
}
}
} catch(...){
std::cout<<"Warning: read log configuration failed."<<std::endl;
log_level_ = global_log_level;
}
}
LOG_LEVEL log_level_{global_log_level};
};
inline LOG_LEVEL getLogLevel(){
static LogFromFile log_from_file;
return log_from_file.log_level_;
}
}
#define GEMFIELDSTR_DETAIL(x) #x
#define GEMFIELDSTR(x) GEMFIELDSTR_DETAIL(x)
#ifdef GARRULOUS_GEMFIELD
#define GEMFIELD_SI gemfield_org::Gemfield gemfieldsi({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__}, gemfield_org::STACK_INFO)
#define GEMFIELD_DI(x) gemfield_org::Gemfield gemfielddi({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__,x}, gemfield_org::DETAIL_INFO)
#define GEMFIELD_DI2(x,y) gemfield_org::Gemfield gemfielddi2({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__,x,y}, gemfield_org::DETAIL_INFO)
#define GEMFIELD_I(x) gemfield_org::Gemfield gemfieldi({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__,x}, gemfield_org::INFO)
#define GEMFIELD_I2(x,y) gemfield_org::Gemfield gemfieldi2({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__,x,y}, gemfield_org::INFO)
#define GEMFIELD_W(x) gemfield_org::Gemfield gemfieldw({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__,x}, gemfield_org::WARNING)
#define GEMFIELD_W2(x,y) gemfield_org::Gemfield gemfieldw2({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__,x,y}, gemfield_org::WARNING)
#define GEMFIELD_E(x) gemfield_org::Gemfield gemfielde({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__,x}, gemfield_org::ERROR)
#define GEMFIELD_E2(x,y) gemfield_org::Gemfield gemfielde2({__FILE__, GEMFIELDSTR(__LINE__), __FUNCTION__,x,y}, gemfield_org::ERROR)
#else
#define GEMFIELD_SI
#define GEMFIELD_DI(x)
#define GEMFIELD_DI2(x,y)
#define GEMFIELD_I(x)
#define GEMFIELD_I2(x,y)
#define GEMFIELD_W(x)
#define GEMFIELD_W2(x,y)
#define GEMFIELD_E(x)
#define GEMFIELD_E2(x,y)
#endif
thread_local int __attribute__((weak)) gemfield_counter = 0;
//std::map<uint64_t, int> __attribute__((weak)) gemfield_counter_map;
namespace gemfield_org{
template<typename ... Args>
std::string format( const std::string& format, Args ... args ){
size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1;
std::unique_ptr<char[]> buf( new char[ size ] );
snprintf( buf.get(), size, format.c_str(), args ... );
return std::string( buf.get(), buf.get() + size - 1 );
}
class Gemfield{
public:
Gemfield(std::initializer_list<const char*> src, LOG_LEVEL level):level_(level){
if(level_ < getLogLevel()){
return;
}
std::stringstream ss;
ss << "["<<std::this_thread::get_id()<<"]";
for (auto s1: src){
ss << ":"<<s1;
}
s_ += ss.str();
if(level_ != STACK_INFO){
printMark('#', s_, level_);
}else{
printMark('+', s_, level_);
}
}
~Gemfield(){
if(level_ < getLogLevel() || level_ != STACK_INFO){
return;
}
printMark('-', s_, level_);
}
private:
static void printMark(char c, std::string& s, LOG_LEVEL level){
static std::mutex gemfield_lock;
std::lock_guard<std::mutex> lock(gemfield_lock);
std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t current_tid = std::stoull(ss.str());
if(c == '+'){
++gemfield_counter;
}
for(int i=0; i< gemfield_counter; i++){
std::cout<<c;
}
static std::map<LOG_LEVEL, std::string> log_token = {{STACK_INFO,""},{DETAIL_INFO," | DETAIL_INFO | "},{INFO," | INFO | "},{WARNING," | WARNING | "},{ERROR," | ERROR | "}};
std::cout<<s<<log_token[level]<<std::endl;
if(c == '-'){
--gemfield_counter;
}
}
std::string s_;
LOG_LEVEL level_{WARNING};
};
}
#endif