1 /* 2 * Copyright 2017-2022, Andrew Lindesay <apl@lindesay.co.nz>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 #ifndef LOGGER_H 6 #define LOGGER_H 7 8 #include <String.h> 9 #include <File.h> 10 #include <Path.h> 11 12 #include <ctype.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 16 17 #define MILLIS_IN_DAY 86400000L 18 19 #define HDLOGLEVELCHAR(L) ( \ 20 L == LOG_LEVEL_INFO ? 'I' \ 21 : L == LOG_LEVEL_DEBUG ? 'D' \ 22 : L == LOG_LEVEL_TRACE ? 'T' \ 23 : L == LOG_LEVEL_ERROR ? 'E' \ 24 : '?') 25 26 // These macros allow for standardized logging to be output. 27 // The use of macros in this way means that the use of the log is concise where 28 // it is used and also because the macro unwraps to a block contained with a 29 // condition statement, if the log level is not sufficient to trigger the log 30 // line then there is no computational cost to running over the log space. This 31 // is because the arguments will not be evaluated. Avoiding all of the 32 // conditional clauses in the code to prevent this otherwise would be 33 // cumbersome. 34 35 // The time element @<time> is presented in milliseconds on the current day. 36 37 #define HDLOGPREFIX(L) printf("@%08" B_PRId64 " {%c} <t:%" B_PRIu32 "> ", \ 38 ((system_time() / 1000L) % MILLIS_IN_DAY), \ 39 HDLOGLEVELCHAR(L), \ 40 Logger::CurrentThreadIndicator() \ 41 ); 42 43 #define HDLOG(L, M...) do { if (Logger::IsLevelEnabled(L)) { \ 44 HDLOGPREFIX(L) \ 45 printf(M); \ 46 putchar('\n'); \ 47 } } while (0) 48 49 #define HDINFO(M...) HDLOG(LOG_LEVEL_INFO, M) 50 #define HDDEBUG(M...) HDLOG(LOG_LEVEL_DEBUG, M) 51 #define HDTRACE(M...) HDLOG(LOG_LEVEL_TRACE, M) 52 #define HDERROR(M...) HDLOG(LOG_LEVEL_ERROR, M) 53 54 #define HDFATAL(M...) do { \ 55 printf("{!} (failed @ %s:%d) ", __FILE__, __LINE__); \ 56 printf(M); \ 57 putchar('\n'); \ 58 exit(EXIT_FAILURE); \ 59 } while (0) 60 61 typedef enum log_level { 62 LOG_LEVEL_OFF = 1, 63 LOG_LEVEL_ERROR = 2, 64 LOG_LEVEL_INFO = 3, 65 LOG_LEVEL_DEBUG = 4, 66 LOG_LEVEL_TRACE = 5 67 } log_level; 68 69 70 class Logger { 71 public: 72 static log_level Level(); 73 static void SetLevel(log_level value); 74 static bool SetLevelByName(const char *name); 75 76 static const char* NameForLevel(log_level value); 77 78 static bool IsLevelEnabled(log_level value); 79 static bool IsInfoEnabled(); 80 static bool IsDebugEnabled(); 81 static bool IsTraceEnabled(); 82 83 static uint32 CurrentThreadIndicator(); 84 85 private: 86 static log_level fLevel; 87 }; 88 89 90 #endif // LOGGER_H 91