2525//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2626#pragma  once
2727
28+ #include  < array> 
2829#include  < cerrno> 
2930#include  < cstring> 
3031#include  < fstream> 
3334#include  < string> 
3435#include  < vector> 
3536
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 
4348
44-   LogMessage (const  char * file, int  line, uint32_t  level);
45-   ~LogMessage ();
4649
47-   std::stringstream&  stream () {  return  stream_; } 
50+ namespace   triton  {  namespace   common  { 
4851
49-  private: 
50-   static  const  std::vector<char > level_name_;
51-   std::stringstream stream_;
52- };
5352
5453//  Global logger for messages. Controls how log messages are reported.
5554class  Logger  {
5655 public: 
56+   //  Log Formats.
5757  enum  class  Format  { kDEFAULT , kISO8601  };
5858
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+ 
5965  Logger ();
6066
6167  //  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+   }
6372
6473  //  Set enable for a log Level.
65-   void  SetEnabled (LogMessage:: Level level, bool  enable)
74+   void  SetEnabled (Level level, bool  enable)
6675  {
67-     enables_[level] = enable;
76+     enables_[static_cast < uint8_t >( level) ] = enable;
6877  }
6978
7079  //  Get the current verbose logging level.
@@ -73,6 +82,16 @@ class Logger {
7382  //  Set the current verbose logging level.
7483  void  SetVerboseLevel (uint32_t  vlevel) { vlevel_ = vlevel; }
7584
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+ 
7695  //  Get the logging format.
7796  Format LogFormat () { return  format_; }
7897
@@ -126,7 +145,10 @@ class Logger {
126145  void  Flush ();
127146
128147 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_;
130152  uint32_t  vlevel_;
131153  Format format_;
132154  std::mutex mutex_;
@@ -136,15 +158,60 @@ class Logger {
136158
137159extern  Logger gLogger_ ;
138160
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))
142209#define  LOG_ENABLE_WARNING (E )          \
143210  triton::common::gLogger_ .SetEnabled( \
144-       triton::common::LogMessage ::Level::kWARNING , (E))
211+       triton::common::Logger ::Level::kWARNING , (E))
145212#define  LOG_ENABLE_ERROR (E )            \
146213  triton::common::gLogger_ .SetEnabled( \
147-       triton::common::LogMessage ::Level::kERROR , (E))
214+       triton::common::Logger ::Level::kERROR , (E))
148215#define  LOG_SET_VERBOSE (L )                  \
149216  triton::common::gLogger_ .SetVerboseLevel( \
150217      static_cast <uint32_t >(std::max(0 , (L))))
@@ -159,12 +226,11 @@ extern Logger gLogger_;
159226#ifdef  TRITON_ENABLE_LOGGING
160227
161228#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 )
166232#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 )
168234#define  LOG_VERBOSE_IS_ON (L ) (triton::common::gLogger_ .VerboseLevel() >= (L))
169235
170236#else 
@@ -178,25 +244,25 @@ extern Logger gLogger_;
178244#endif   //  TRITON_ENABLE_LOGGING
179245
180246//  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) \
185251      .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) \
190256      .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) \
195261      .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) \
200266      .stream()
201267
202268//  Macros that use current filename and line number.
@@ -205,7 +271,50 @@ extern Logger gLogger_;
205271#define  LOG_ERROR  LOG_ERROR_FL (__FILE__, __LINE__)
206272#define  LOG_VERBOSE (L ) LOG_VERBOSE_FL(L, __FILE__, __LINE__)
207273
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 )
208316
317+ //  Macros for logging errors
209318#define  LOG_STATUS_ERROR (X, MSG )                         \
210319  do  {                                                   \
211320    const  Status& status__ = (X);                        \
0 commit comments