25
25
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
26
#pragma once
27
27
28
+ #include < array>
28
29
#include < cerrno>
29
30
#include < cstring>
30
31
#include < fstream>
33
34
#include < string>
34
35
#include < vector>
35
36
36
- namespace triton { namespace common {
37
-
38
- // A log message.
39
- class LogMessage {
40
- public:
41
- // Log levels.
42
- enum Level { kERROR = 0 , kWARNING = 1 , kINFO = 2 };
37
+ #include " table_printer.h"
38
+ #ifdef _WIN32
39
+ // suppress the min and max definitions in Windef.h.
40
+ #define NOMINMAX
41
+ #include < Windows.h>
42
+ #else
43
+ #include < sys/time.h>
44
+ #include < sys/types.h>
45
+ #include < time.h>
46
+ #include < unistd.h>
47
+ #endif
43
48
44
- LogMessage (const char * file, int line, uint32_t level);
45
- ~LogMessage ();
46
49
47
- std::stringstream& stream () { return stream_; }
50
+ namespace triton { namespace common {
48
51
49
- private:
50
- static const std::vector<char > level_name_;
51
- std::stringstream stream_;
52
- };
53
52
54
53
// Global logger for messages. Controls how log messages are reported.
55
54
class Logger {
56
55
public:
56
+ // Log Formats.
57
57
enum class Format { kDEFAULT , kISO8601 };
58
58
59
+ // Log levels.
60
+ enum class Level : uint8_t { kERROR = 0 , kWARNING = 1 , kINFO = 2 , kEND };
61
+
62
+ inline static const std::array<const char *, static_cast <uint8_t >(Level::kEND )>
63
+ LEVEL_NAMES{" E" , " W" , " I" };
64
+
59
65
Logger ();
60
66
61
67
// Is a log level enabled.
62
- bool IsEnabled (LogMessage::Level level) const { return enables_[level]; }
68
+ bool IsEnabled (Level level) const
69
+ {
70
+ return enables_[static_cast <uint8_t >(level)];
71
+ }
63
72
64
73
// Set enable for a log Level.
65
- void SetEnabled (LogMessage:: Level level, bool enable)
74
+ void SetEnabled (Level level, bool enable)
66
75
{
67
- enables_[level] = enable;
76
+ enables_[static_cast < uint8_t >( level) ] = enable;
68
77
}
69
78
70
79
// Get the current verbose logging level.
@@ -73,6 +82,16 @@ class Logger {
73
82
// Set the current verbose logging level.
74
83
void SetVerboseLevel (uint32_t vlevel) { vlevel_ = vlevel; }
75
84
85
+ // Whether to escape log messages
86
+ // using JSON string escaping rules.
87
+ // Default is true but can be disabled by setting
88
+ // the following environment variable to '0'.
89
+ // If the variable is unset or set to any value !='0'
90
+ // log messages will be escaped
91
+ //
92
+ // TRITON_SERVER_ESCAPE_LOG_MESSAGES=0
93
+ bool EscapeLogMessages () const { return escape_log_messages_; };
94
+
76
95
// Get the logging format.
77
96
Format LogFormat () { return format_; }
78
97
@@ -126,7 +145,10 @@ class Logger {
126
145
void Flush ();
127
146
128
147
private:
129
- std::vector<bool > enables_;
148
+ inline static const char * ESCAPE_ENVIRONMENT_VARIABLE =
149
+ " TRITON_SERVER_ESCAPE_LOG_MESSAGES" ;
150
+ bool escape_log_messages_;
151
+ std::array<bool , static_cast <uint8_t >(Level::kEND )> enables_;
130
152
uint32_t vlevel_;
131
153
Format format_;
132
154
std::mutex mutex_;
@@ -136,15 +158,60 @@ class Logger {
136
158
137
159
extern Logger gLogger_ ;
138
160
139
- #define LOG_ENABLE_INFO (E ) \
140
- triton::common::gLogger_ .SetEnabled( \
141
- triton::common::LogMessage::Level::kINFO , (E))
161
+ // A log message.
162
+ class LogMessage {
163
+ public:
164
+ LogMessage (
165
+ const char * file, int line, Logger::Level level,
166
+ const char * heading = nullptr ,
167
+ bool escape_log_messages = gLogger_ .EscapeLogMessages())
168
+ : path_(file), line_(line), level_(level), pid_(GetProcessId()),
169
+ heading_ (heading), escape_log_messages_(escape_log_messages)
170
+ {
171
+ SetTimestamp ();
172
+ size_t path_start = path_.rfind (' /' );
173
+ if (path_start != std::string::npos) {
174
+ path_ = path_.substr (path_start + 1 , std::string::npos);
175
+ }
176
+ }
177
+
178
+ ~LogMessage ();
179
+
180
+ std::stringstream& stream () { return message_; }
181
+
182
+ private:
183
+ std::string path_;
184
+ const int line_;
185
+ const Logger::Level level_;
186
+ const uint32_t pid_;
187
+ void LogPreamble (std::stringstream& stream);
188
+ void LogTimestamp (std::stringstream& stream);
189
+
190
+ #ifdef _WIN32
191
+ SYSTEMTIME timestamp_;
192
+ void SetTimestamp () { GetSystemTime (×tamp_); }
193
+ static uint32_t GetProcessId ()
194
+ {
195
+ return static_cast <uint32_t >(GetCurrentProcessId ());
196
+ };
197
+ #else
198
+ struct timeval timestamp_;
199
+ void SetTimestamp () { gettimeofday (×tamp_, NULL ); }
200
+ static uint32_t GetProcessId () { return static_cast <uint32_t >(getpid ()); };
201
+ #endif
202
+ std::stringstream message_;
203
+ const char * heading_;
204
+ bool escape_log_messages_;
205
+ };
206
+
207
+ #define LOG_ENABLE_INFO (E ) \
208
+ triton::common::gLogger_ .SetEnabled(triton::common::Logger::Level::kINFO , (E))
142
209
#define LOG_ENABLE_WARNING (E ) \
143
210
triton::common::gLogger_ .SetEnabled( \
144
- triton::common::LogMessage ::Level::kWARNING , (E))
211
+ triton::common::Logger ::Level::kWARNING , (E))
145
212
#define LOG_ENABLE_ERROR (E ) \
146
213
triton::common::gLogger_ .SetEnabled( \
147
- triton::common::LogMessage ::Level::kERROR , (E))
214
+ triton::common::Logger ::Level::kERROR , (E))
148
215
#define LOG_SET_VERBOSE (L ) \
149
216
triton::common::gLogger_ .SetVerboseLevel( \
150
217
static_cast <uint32_t >(std::max(0 , (L))))
@@ -159,12 +226,11 @@ extern Logger gLogger_;
159
226
#ifdef TRITON_ENABLE_LOGGING
160
227
161
228
#define LOG_INFO_IS_ON \
162
- triton::common::gLogger_ .IsEnabled(triton::common::LogMessage::Level::kINFO )
163
- #define LOG_WARNING_IS_ON \
164
- triton::common::gLogger_ .IsEnabled( \
165
- triton::common::LogMessage::Level::kWARNING )
229
+ triton::common::gLogger_ .IsEnabled(triton::common::Logger::Level::kINFO )
230
+ #define LOG_WARNING_IS_ON \
231
+ triton::common::gLogger_ .IsEnabled(triton::common::Logger::Level::kWARNING )
166
232
#define LOG_ERROR_IS_ON \
167
- triton::common::gLogger_ .IsEnabled(triton::common::LogMessage ::Level::kERROR )
233
+ triton::common::gLogger_ .IsEnabled(triton::common::Logger ::Level::kERROR )
168
234
#define LOG_VERBOSE_IS_ON (L ) (triton::common::gLogger_ .VerboseLevel() >= (L))
169
235
170
236
#else
@@ -178,25 +244,25 @@ extern Logger gLogger_;
178
244
#endif // TRITON_ENABLE_LOGGING
179
245
180
246
// Macros that use explicitly given filename and line number.
181
- #define LOG_INFO_FL (FN, LN ) \
182
- if (LOG_INFO_IS_ON) \
183
- triton::common::LogMessage ( \
184
- (char *)(FN), LN, triton::common::LogMessage ::Level::kINFO) \
247
+ #define LOG_INFO_FL (FN, LN ) \
248
+ if (LOG_INFO_IS_ON) \
249
+ triton::common::LogMessage ( \
250
+ (char *)(FN), LN, triton::common::Logger ::Level::kINFO) \
185
251
.stream()
186
- #define LOG_WARNING_FL (FN, LN ) \
187
- if (LOG_WARNING_IS_ON) \
188
- triton::common::LogMessage ( \
189
- (char *)(FN), LN, triton::common::LogMessage ::Level::kWARNING) \
252
+ #define LOG_WARNING_FL (FN, LN ) \
253
+ if (LOG_WARNING_IS_ON) \
254
+ triton::common::LogMessage ( \
255
+ (char *)(FN), LN, triton::common::Logger ::Level::kWARNING) \
190
256
.stream()
191
- #define LOG_ERROR_FL (FN, LN ) \
192
- if (LOG_ERROR_IS_ON) \
193
- triton::common::LogMessage ( \
194
- (char *)(FN), LN, triton::common::LogMessage ::Level::kERROR) \
257
+ #define LOG_ERROR_FL (FN, LN ) \
258
+ if (LOG_ERROR_IS_ON) \
259
+ triton::common::LogMessage ( \
260
+ (char *)(FN), LN, triton::common::Logger ::Level::kERROR) \
195
261
.stream()
196
- #define LOG_VERBOSE_FL (L, FN, LN ) \
197
- if (LOG_VERBOSE_IS_ON(L)) \
198
- triton::common::LogMessage ( \
199
- (char *)(FN), LN, triton::common::LogMessage ::Level::kINFO) \
262
+ #define LOG_VERBOSE_FL (L, FN, LN ) \
263
+ if (LOG_VERBOSE_IS_ON(L)) \
264
+ triton::common::LogMessage ( \
265
+ (char *)(FN), LN, triton::common::Logger ::Level::kINFO) \
200
266
.stream()
201
267
202
268
// Macros that use current filename and line number.
@@ -205,7 +271,50 @@ extern Logger gLogger_;
205
271
#define LOG_ERROR LOG_ERROR_FL (__FILE__, __LINE__)
206
272
#define LOG_VERBOSE (L ) LOG_VERBOSE_FL(L, __FILE__, __LINE__)
207
273
274
+ // Macros for use with triton::common::table_printer objects
275
+ //
276
+ // Data is assumed to be server / backend generated
277
+ // and not for use with client input.
278
+ //
279
+ // Tables are printed without escaping
280
+ #define LOG_TABLE_VERBOSE (L, TABLE ) \
281
+ \
282
+ do { \
283
+ if (LOG_VERBOSE_IS_ON (L)) \
284
+ triton::common::LogMessage ( \
285
+ __FILE__, __LINE__, triton::common::Logger::Level::kINFO , nullptr , \
286
+ false ) \
287
+ .stream () \
288
+ << TABLE.PrintTable (); \
289
+ } while (false )
290
+
291
+ #define LOG_TABLE_INFO (TABLE ) \
292
+ do { \
293
+ if (LOG_INFO_IS_ON) \
294
+ triton::common::LogMessage ( \
295
+ __FILE__, __LINE__, triton::common::Logger::Level::kINFO , nullptr , \
296
+ false ) \
297
+ .stream () \
298
+ << TABLE.PrintTable (); \
299
+ } while (false )
300
+
301
+
302
+ // Macros for use with protobuf messages
303
+ //
304
+ // Data is serialized via DebugString()
305
+ //
306
+ // Data is printed without further escaping
307
+ #define LOG_PROTOBUF_VERBOSE (L, HEADING, PB_MESSAGE ) \
308
+ do { \
309
+ if (LOG_VERBOSE_IS_ON (L)) \
310
+ triton::common::LogMessage ( \
311
+ __FILE__, __LINE__, triton::common::Logger::Level::kINFO , HEADING, \
312
+ false ) \
313
+ .stream () \
314
+ << PB_MESSAGE.DebugString (); \
315
+ } while (false )
208
316
317
+ // Macros for logging errors
209
318
#define LOG_STATUS_ERROR (X, MSG ) \
210
319
do { \
211
320
const Status& status__ = (X); \
0 commit comments