3333#include < string>
3434#include < vector>
3535
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 };
36+ #include " table_printer.h"
37+ #ifdef _WIN32
38+ // suppress the min and max definitions in Windef.h.
39+ #define NOMINMAX
40+ #include < Windows.h>
41+ #else
42+ #include < sys/time.h>
43+ #include < sys/types.h>
44+ #include < time.h>
45+ #include < unistd.h>
46+ #endif
4347
44- LogMessage (const char * file, int line, uint32_t level);
45- ~LogMessage ();
4648
47- std::stringstream& stream () { return stream_; }
49+ namespace triton { namespace common {
4850
49- private:
50- static const std::vector<char > level_name_;
51- std::stringstream stream_;
52- };
5351
5452// Global logger for messages. Controls how log messages are reported.
5553class Logger {
5654 public:
55+ // Log Formats.
5756 enum class Format { kDEFAULT , kISO8601 };
5857
58+ // Log levels.
59+ enum class Level : uint8_t { kERROR = 0 , kWARNING = 1 , kINFO = 2 , kEND };
60+
61+ inline static const std::array<const char *, static_cast <uint8_t >(Level::kEND )>
62+ LEVEL_NAMES{" E" , " W" , " I" };
63+
5964 Logger ();
6065
6166 // Is a log level enabled.
62- bool IsEnabled (LogMessage::Level level) const { return enables_[level]; }
67+ bool IsEnabled (Level level) const
68+ {
69+ return enables_[static_cast <uint8_t >(level)];
70+ }
6371
6472 // Set enable for a log Level.
65- void SetEnabled (LogMessage:: Level level, bool enable)
73+ void SetEnabled (Level level, bool enable)
6674 {
67- enables_[level] = enable;
75+ enables_[static_cast < uint8_t >( level) ] = enable;
6876 }
6977
7078 // Get the current verbose logging level.
@@ -73,6 +81,16 @@ class Logger {
7381 // Set the current verbose logging level.
7482 void SetVerboseLevel (uint32_t vlevel) { vlevel_ = vlevel; }
7583
84+ // Whether to escape log messages
85+ // using JSON string escaping rules.
86+ // Default is true but can be disabled by setting
87+ // the following environment variable to '0'.
88+ // If the variable is unset or set to any value !='0'
89+ // log messages will be escaped
90+ //
91+ // TRITON_SERVER_ESCAPE_LOG_MESSAGES=0
92+ bool EscapeLogMessages () const { return escape_log_messages_; };
93+
7694 // Get the logging format.
7795 Format LogFormat () { return format_; }
7896
@@ -126,7 +144,10 @@ class Logger {
126144 void Flush ();
127145
128146 private:
129- std::vector<bool > enables_;
147+ inline static const char * ESCAPE_ENVIRONMENT_VARIABLE =
148+ " TRITON_SERVER_ESCAPE_LOG_MESSAGES" ;
149+ bool escape_log_messages_;
150+ std::array<bool , static_cast <uint8_t >(Level::kEND )> enables_;
130151 uint32_t vlevel_;
131152 Format format_;
132153 std::mutex mutex_;
@@ -136,15 +157,60 @@ class Logger {
136157
137158extern Logger gLogger_ ;
138159
139- #define LOG_ENABLE_INFO (E ) \
140- triton::common::gLogger_ .SetEnabled( \
141- triton::common::LogMessage::Level::kINFO , (E))
160+ // A log message.
161+ class LogMessage {
162+ public:
163+ LogMessage (
164+ const char * file, int line, Logger::Level level,
165+ const char * heading = nullptr ,
166+ bool escape_log_messages = gLogger_ .EscapeLogMessages())
167+ : path_(file), line_(line), level_(level), pid_(GetProcessId()),
168+ heading_ (heading), escape_log_messages_(escape_log_messages)
169+ {
170+ SetTimestamp ();
171+ size_t path_start = path_.rfind (' /' );
172+ if (path_start != std::string::npos) {
173+ path_ = path_.substr (path_start + 1 , std::string::npos);
174+ }
175+ }
176+
177+ ~LogMessage ();
178+
179+ std::stringstream& stream () { return message_; }
180+
181+ private:
182+ std::string path_;
183+ const int line_;
184+ const Logger::Level level_;
185+ const uint32_t pid_;
186+ void LogPreamble (std::stringstream& stream);
187+ void LogTimestamp (std::stringstream& stream);
188+
189+ #ifdef _WIN32
190+ SYSTEMTIME timestamp_;
191+ void SetTimestamp () { GetSystemTime (×tamp_); }
192+ static uint32_t GetProcessId ()
193+ {
194+ return static_cast <uint32_t >(GetCurrentProcessId ());
195+ };
196+ #else
197+ struct timeval timestamp_;
198+ void SetTimestamp () { gettimeofday (×tamp_, NULL ); }
199+ static uint32_t GetProcessId () { return static_cast <uint32_t >(getpid ()); };
200+ #endif
201+ std::stringstream message_;
202+ const char * heading_;
203+ bool escape_log_messages_;
204+ };
205+
206+ #define LOG_ENABLE_INFO (E ) \
207+ triton::common::gLogger_ .SetEnabled(triton::common::Logger::Level::kINFO , (E))
142208#define LOG_ENABLE_WARNING (E ) \
143209 triton::common::gLogger_ .SetEnabled( \
144- triton::common::LogMessage ::Level::kWARNING , (E))
210+ triton::common::Logger ::Level::kWARNING , (E))
145211#define LOG_ENABLE_ERROR (E ) \
146212 triton::common::gLogger_ .SetEnabled( \
147- triton::common::LogMessage ::Level::kERROR , (E))
213+ triton::common::Logger ::Level::kERROR , (E))
148214#define LOG_SET_VERBOSE (L ) \
149215 triton::common::gLogger_ .SetVerboseLevel( \
150216 static_cast <uint32_t >(std::max(0 , (L))))
@@ -159,12 +225,11 @@ extern Logger gLogger_;
159225#ifdef TRITON_ENABLE_LOGGING
160226
161227#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 )
228+ triton::common::gLogger_ .IsEnabled(triton::common::Logger::Level::kINFO )
229+ #define LOG_WARNING_IS_ON \
230+ triton::common::gLogger_ .IsEnabled(triton::common::Logger::Level::kWARNING )
166231#define LOG_ERROR_IS_ON \
167- triton::common::gLogger_ .IsEnabled(triton::common::LogMessage ::Level::kERROR )
232+ triton::common::gLogger_ .IsEnabled(triton::common::Logger ::Level::kERROR )
168233#define LOG_VERBOSE_IS_ON (L ) (triton::common::gLogger_ .VerboseLevel() >= (L))
169234
170235#else
@@ -178,25 +243,25 @@ extern Logger gLogger_;
178243#endif // TRITON_ENABLE_LOGGING
179244
180245// 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) \
246+ #define LOG_INFO_FL (FN, LN ) \
247+ if (LOG_INFO_IS_ON) \
248+ triton::common::LogMessage ( \
249+ (char *)(FN), LN, triton::common::Logger ::Level::kINFO) \
185250 .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) \
251+ #define LOG_WARNING_FL (FN, LN ) \
252+ if (LOG_WARNING_IS_ON) \
253+ triton::common::LogMessage ( \
254+ (char *)(FN), LN, triton::common::Logger ::Level::kWARNING) \
190255 .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) \
256+ #define LOG_ERROR_FL (FN, LN ) \
257+ if (LOG_ERROR_IS_ON) \
258+ triton::common::LogMessage ( \
259+ (char *)(FN), LN, triton::common::Logger ::Level::kERROR) \
195260 .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) \
261+ #define LOG_VERBOSE_FL (L, FN, LN ) \
262+ if (LOG_VERBOSE_IS_ON(L)) \
263+ triton::common::LogMessage ( \
264+ (char *)(FN), LN, triton::common::Logger ::Level::kINFO) \
200265 .stream()
201266
202267// Macros that use current filename and line number.
@@ -205,7 +270,50 @@ extern Logger gLogger_;
205270#define LOG_ERROR LOG_ERROR_FL (__FILE__, __LINE__)
206271#define LOG_VERBOSE (L ) LOG_VERBOSE_FL(L, __FILE__, __LINE__)
207272
273+ // Macros for use with triton::common::table_printer objects
274+ //
275+ // Data is assumed to be server / backend generated
276+ // and not for use with client input.
277+ //
278+ // Tables are printed without escaping
279+ #define LOG_TABLE_VERBOSE (L, TABLE ) \
280+ \
281+ do { \
282+ if (LOG_VERBOSE_IS_ON (L)) \
283+ triton::common::LogMessage ( \
284+ __FILE__, __LINE__, triton::common::Logger::Level::kINFO , nullptr , \
285+ false ) \
286+ .stream () \
287+ << TABLE.PrintTable (); \
288+ } while (false )
289+
290+ #define LOG_TABLE_INFO (TABLE ) \
291+ do { \
292+ if (LOG_INFO_IS_ON) \
293+ triton::common::LogMessage ( \
294+ __FILE__, __LINE__, triton::common::Logger::Level::kINFO , nullptr , \
295+ false ) \
296+ .stream () \
297+ << TABLE.PrintTable (); \
298+ } while (false )
299+
300+
301+ // Macros for use with protobuf messages
302+ //
303+ // Data is serialized via DebugString()
304+ //
305+ // Data is printed without further escaping
306+ #define LOG_PROTOBUF_VERBOSE (L, HEADING, PB_MESSAGE ) \
307+ do { \
308+ if (LOG_VERBOSE_IS_ON (L)) \
309+ triton::common::LogMessage ( \
310+ __FILE__, __LINE__, triton::common::Logger::Level::kINFO , HEADING, \
311+ false ) \
312+ .stream () \
313+ << PB_MESSAGE.DebugString (); \
314+ } while (false )
208315
316+ // Macros for logging errors
209317#define LOG_STATUS_ERROR (X, MSG ) \
210318 do { \
211319 const Status& status__ = (X); \
0 commit comments