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