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