Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/cpp/webdriver-server/logging.h
2867 views
1
/*
2
Licensed to the Software Freedom Conservancy (SFC) under one
3
or more contributor license agreements. See the NOTICE file
4
distributed with this work for additional information
5
regarding copyright ownership. The SFC licenses this file
6
to you under the Apache License, Version 2.0 (the "License");
7
you may not use this file except in compliance with the License.
8
You may obtain a copy of the License at
9
10
http://www.apache.org/licenses/LICENSE-2.0
11
12
Unless required by applicable law or agreed to in writing, software
13
distributed under the License is distributed on an "AS IS" BASIS,
14
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
See the License for the specific language governing permissions and
16
limitations under the License.
17
*/
18
19
#ifndef logging_h
20
#define logging_h
21
22
#ifdef _WIN32
23
#pragma warning(push)
24
#pragma warning(disable:4996 4717)
25
#define fileno _fileno
26
#define isatty _isatty
27
#define lseek _lseek
28
#ifdef _ftime
29
#define ftime _ftime
30
#endif
31
#endif
32
33
#ifdef unix
34
#include <sys/types.h>
35
#include <unistd.h>
36
#else
37
#include <io.h>
38
#include <comdef.h>
39
#endif
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <sys/timeb.h>
43
#include <time.h>
44
#include <sstream>
45
#include <string>
46
#include <iostream>
47
48
template <class _LOGGER> class Logger {
49
public:
50
Logger() : fatal_(false) {}
51
52
enum LogLevel {
53
logFATAL = 0, logERROR, logWARN, logINFO, logDEBUG, logTRACE };
54
55
~Logger() {
56
os_ << std::endl, _LOGGER::Log(os_.str(), fatal_);
57
if (fatal_) {
58
exit(EXIT_FAILURE);
59
}
60
}
61
62
static void Level(const std::string& level) {
63
Level() = ToLogLevel(level);
64
}
65
66
static LogLevel& Level() {
67
static LogLevel level = GetLogLevelEnv();
68
return level;
69
}
70
71
std::ostringstream& Stream(LogLevel level) {
72
static char severity[] = { 'F', 'E', 'W', 'I', 'D', 'T' };
73
os_ << severity[level] << ' ' << Time();
74
if (level == logFATAL)
75
fatal_ = true, os_ << L"FATAL ";
76
return os_;
77
}
78
79
static std::string Time() {
80
struct timeb tb; ftime(&tb);
81
82
char time[26];
83
size_t length = strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S:",
84
localtime(reinterpret_cast<const time_t*>(&tb.time)));
85
sprintf(time + length, "%03u ", tb.millitm);
86
87
return time;
88
}
89
90
private:
91
92
static LogLevel ToLogLevel(const std::string& level) {
93
if (level == "ERROR") {
94
return logERROR;
95
} else if (level == "WARN" ) {
96
return logWARN;
97
} else if (level == "INFO" ) {
98
return logINFO;
99
} else if (level == "DEBUG") {
100
return logDEBUG;
101
} else if (level == "TRACE") {
102
return logTRACE;
103
} else {
104
return logFATAL;
105
}
106
}
107
108
static LogLevel GetLogLevelEnv() {
109
char* tmp = getenv("SELENIUM_LOG_LEVEL");
110
return tmp ? ToLogLevel(std::string(tmp)) : logFATAL;
111
}
112
113
std::ostringstream os_;
114
bool fatal_;
115
};
116
117
class LOG : public Logger<LOG> {
118
public:
119
static void File(const std::string& name, const char* openMode = "w") {
120
const std::string& file = Name(name);
121
if (file == "stdout") {
122
LOG::File() = stdout;
123
} else if (file == "stderr") {
124
LOG::File() = stderr;
125
} else {
126
LOG::File() = fopen(file.c_str(), openMode);
127
}
128
}
129
130
static void Limit(off_t size) {
131
LOG::Limit() = size;
132
}
133
134
private:
135
static std::string& Name(const std::string& name) {
136
static std::string file_name = "stdout";
137
if (!name.empty())
138
file_name.assign(name);
139
return file_name;
140
}
141
142
static FILE*& File() {
143
static FILE* file = stdout;
144
return file;
145
}
146
147
static off_t& Limit() {
148
static off_t size_limit = 0;
149
return size_limit;
150
}
151
152
static void Log(const std::string& str, bool fatal) {
153
if (fatal) Limit() = 0;
154
155
FILE* output = File();
156
if (output) {
157
fwrite(str.data(), sizeof(char), str.size(), output);
158
fflush(output);
159
160
if (Limit() && !isatty(fileno(output))) {
161
if (lseek(fileno(output), 0, SEEK_END) > Limit()) {
162
fclose(output), File("");
163
}
164
}
165
}
166
167
if (fatal && !isatty(fileno(output))) {
168
fputs(str.c_str(), stderr);
169
}
170
}
171
172
friend class Logger<LOG>;
173
};
174
175
#ifdef _WIN32
176
#pragma warning(pop)
177
#endif
178
179
180
#define LOG(LEVEL) \
181
if (LOG::log ## LEVEL > LOG::Level()) ; \
182
else LOG().Stream(LOG::log ## LEVEL) << __FILE__ << "(" << __LINE__ << ") " /* << stuff here */
183
184
#ifdef _WIN32
185
#define LOGHR(LEVEL,HR) LOG( ## LEVEL) << HR << " [" << (_bstr_t(_com_error((DWORD) HR).ErrorMessage())) << "]: "
186
#define LOGERR(LEVEL) LOG( ## LEVEL) << " [Windows Error " << (::GetLastError()) << "]: "
187
#define LOGWSTRING(STR) _bstr_t( (## STR).c_str())
188
#endif
189
190
191
#endif // logging_h
192
193