Logger.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * Copyright 2017-2020 NVIDIA Corporation. All rights reserved.
  3. *
  4. * Please refer to the NVIDIA end user license agreement (EULA) associated
  5. * with this source code for terms and conditions that govern your use of
  6. * this software. Any use, reproduction, disclosure, or distribution of
  7. * this software and related documentation outside the terms of the EULA
  8. * is strictly prohibited.
  9. *
  10. */
  11. #pragma once
  12. #include <iostream>
  13. #include <fstream>
  14. #include <string>
  15. #include <sstream>
  16. #include <mutex>
  17. #include <time.h>
  18. #ifdef _WIN32
  19. #include <winsock.h>
  20. #include <windows.h>
  21. #pragma comment(lib, "ws2_32.lib")
  22. #undef ERROR
  23. #else
  24. #include <unistd.h>
  25. #include <sys/socket.h>
  26. #include <netinet/in.h>
  27. #include <arpa/inet.h>
  28. #define SOCKET int
  29. #define INVALID_SOCKET -1
  30. #endif
  31. enum LogLevel {
  32. TRACE,
  33. INFO,
  34. WARNING,
  35. ERROR,
  36. FATAL
  37. };
  38. namespace simplelogger{
  39. class Logger {
  40. public:
  41. Logger(LogLevel level, bool bPrintTimeStamp) : level(level), bPrintTimeStamp(bPrintTimeStamp) {}
  42. virtual ~Logger() {}
  43. virtual std::ostream& GetStream() = 0;
  44. virtual void FlushStream() {}
  45. bool ShouldLogFor(LogLevel l) {
  46. return l >= level;
  47. }
  48. char* GetLead(LogLevel l, const char *szFile, int nLine, const char *szFunc) {
  49. if (l < TRACE || l > FATAL) {
  50. sprintf(szLead, "[?????] ");
  51. return szLead;
  52. }
  53. const char *szLevels[] = {"TRACE", "INFO", "WARN", "ERROR", "FATAL"};
  54. if (bPrintTimeStamp) {
  55. time_t t = time(NULL);
  56. struct tm *ptm = localtime(&t);
  57. sprintf(szLead, "[%-5s][%02d:%02d:%02d] ",
  58. szLevels[l], ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
  59. } else {
  60. sprintf(szLead, "[%-5s] ", szLevels[l]);
  61. }
  62. return szLead;
  63. }
  64. void EnterCriticalSection() {
  65. mtx.lock();
  66. }
  67. void LeaveCriticalSection() {
  68. mtx.unlock();
  69. }
  70. private:
  71. LogLevel level;
  72. char szLead[80];
  73. bool bPrintTimeStamp;
  74. std::mutex mtx;
  75. };
  76. class LoggerFactory {
  77. public:
  78. static Logger* CreateFileLogger(std::string strFilePath,
  79. LogLevel level = INFO, bool bPrintTimeStamp = true) {
  80. return new FileLogger(strFilePath, level, bPrintTimeStamp);
  81. }
  82. static Logger* CreateConsoleLogger(LogLevel level = INFO,
  83. bool bPrintTimeStamp = true) {
  84. return new ConsoleLogger(level, bPrintTimeStamp);
  85. }
  86. static Logger* CreateUdpLogger(char *szHost, unsigned uPort, LogLevel level = INFO,
  87. bool bPrintTimeStamp = true) {
  88. return new UdpLogger(szHost, uPort, level, bPrintTimeStamp);
  89. }
  90. private:
  91. LoggerFactory() {}
  92. class FileLogger : public Logger {
  93. public:
  94. FileLogger(std::string strFilePath, LogLevel level, bool bPrintTimeStamp)
  95. : Logger(level, bPrintTimeStamp) {
  96. pFileOut = new std::ofstream();
  97. pFileOut->open(strFilePath.c_str());
  98. }
  99. ~FileLogger() {
  100. pFileOut->close();
  101. }
  102. std::ostream& GetStream() {
  103. return *pFileOut;
  104. }
  105. private:
  106. std::ofstream *pFileOut;
  107. };
  108. class ConsoleLogger : public Logger {
  109. public:
  110. ConsoleLogger(LogLevel level, bool bPrintTimeStamp)
  111. : Logger(level, bPrintTimeStamp) {}
  112. std::ostream& GetStream() {
  113. return std::cout;
  114. }
  115. };
  116. class UdpLogger : public Logger {
  117. private:
  118. class UdpOstream : public std::ostream {
  119. public:
  120. UdpOstream(char *szHost, unsigned short uPort) : std::ostream(&sb), socket(INVALID_SOCKET){
  121. #ifdef _WIN32
  122. WSADATA w;
  123. if (WSAStartup(0x0101, &w) != 0) {
  124. fprintf(stderr, "WSAStartup() failed.\n");
  125. return;
  126. }
  127. #endif
  128. socket = ::socket(AF_INET, SOCK_DGRAM, 0);
  129. if (socket == INVALID_SOCKET) {
  130. #ifdef _WIN32
  131. WSACleanup();
  132. #endif
  133. fprintf(stderr, "socket() failed.\n");
  134. return;
  135. }
  136. #ifdef _WIN32
  137. unsigned int b1, b2, b3, b4;
  138. sscanf(szHost, "%u.%u.%u.%u", &b1, &b2, &b3, &b4);
  139. struct in_addr addr = {(unsigned char)b1, (unsigned char)b2, (unsigned char)b3, (unsigned char)b4};
  140. #else
  141. struct in_addr addr = {inet_addr(szHost)};
  142. #endif
  143. struct sockaddr_in s = {AF_INET, htons(uPort), addr};
  144. server = s;
  145. }
  146. ~UdpOstream() throw() {
  147. if (socket == INVALID_SOCKET) {
  148. return;
  149. }
  150. #ifdef _WIN32
  151. closesocket(socket);
  152. WSACleanup();
  153. #else
  154. close(socket);
  155. #endif
  156. }
  157. void Flush() {
  158. if (sendto(socket, sb.str().c_str(), (int)sb.str().length() + 1,
  159. 0, (struct sockaddr *)&server, (int)sizeof(sockaddr_in)) == -1) {
  160. fprintf(stderr, "sendto() failed.\n");
  161. }
  162. sb.str("");
  163. }
  164. private:
  165. std::stringbuf sb;
  166. SOCKET socket;
  167. struct sockaddr_in server;
  168. };
  169. public:
  170. UdpLogger(char *szHost, unsigned uPort, LogLevel level, bool bPrintTimeStamp)
  171. : Logger(level, bPrintTimeStamp), udpOut(szHost, (unsigned short)uPort) {}
  172. UdpOstream& GetStream() {
  173. return udpOut;
  174. }
  175. virtual void FlushStream() {
  176. udpOut.Flush();
  177. }
  178. private:
  179. UdpOstream udpOut;
  180. };
  181. };
  182. class LogTransaction {
  183. public:
  184. LogTransaction(Logger *pLogger, LogLevel level, const char *szFile, const int nLine, const char *szFunc) : pLogger(pLogger), level(level) {
  185. if (!pLogger) {
  186. std::cout << "[-----] ";
  187. return;
  188. }
  189. if (!pLogger->ShouldLogFor(level)) {
  190. return;
  191. }
  192. pLogger->EnterCriticalSection();
  193. pLogger->GetStream() << pLogger->GetLead(level, szFile, nLine, szFunc);
  194. }
  195. ~LogTransaction() {
  196. if (!pLogger) {
  197. std::cout << std::endl;
  198. return;
  199. }
  200. if (!pLogger->ShouldLogFor(level)) {
  201. return;
  202. }
  203. pLogger->GetStream() << std::endl;
  204. pLogger->FlushStream();
  205. pLogger->LeaveCriticalSection();
  206. if (level == FATAL) {
  207. exit(1);
  208. }
  209. }
  210. std::ostream& GetStream() {
  211. if (!pLogger) {
  212. return std::cout;
  213. }
  214. if (!pLogger->ShouldLogFor(level)) {
  215. return ossNull;
  216. }
  217. return pLogger->GetStream();
  218. }
  219. private:
  220. Logger *pLogger;
  221. LogLevel level;
  222. std::ostringstream ossNull;
  223. };
  224. }
  225. extern simplelogger::Logger *logger;
  226. #define LOG(level) simplelogger::LogTransaction(logger, level, __FILE__, __LINE__, __FUNCTION__).GetStream()