KSLogger.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. //
  2. // KSLogger.h
  3. //
  4. // Created by Karl Stenerud on 11-06-25.
  5. //
  6. // Copyright (c) 2011 Karl Stenerud. All rights reserved.
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining a copy
  9. // of this software and associated documentation files (the "Software"), to deal
  10. // in the Software without restriction, including without limitation the rights
  11. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. // copies of the Software, and to permit persons to whom the Software is
  13. // furnished to do so, subject to the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall remain in place
  16. // in this source code.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. // THE SOFTWARE.
  25. //
  26. /**
  27. * KSLogger
  28. * ========
  29. *
  30. * Prints log entries to the console consisting of:
  31. * - Level (Error, Warn, Info, Debug, Trace)
  32. * - File
  33. * - Line
  34. * - Function
  35. * - Message
  36. *
  37. * Allows setting the minimum logging level in the preprocessor.
  38. *
  39. * Works in C or Objective-C contexts, with or without ARC, using CLANG or GCC.
  40. *
  41. *
  42. * =====
  43. * USAGE
  44. * =====
  45. *
  46. * Set the log level in your "Preprocessor Macros" build setting. You may choose
  47. * TRACE, DEBUG, INFO, WARN, ERROR. If nothing is set, it defaults to ERROR.
  48. *
  49. * Example: KSLogger_Level=WARN
  50. *
  51. * Anything below the level specified for KSLogger_Level will not be compiled
  52. * or printed.
  53. *
  54. *
  55. * Next, include the header file:
  56. *
  57. * #include "KSLogger.h"
  58. *
  59. *
  60. * Next, call the logger functions from your code (using objective-c strings
  61. * in objective-C files and regular strings in regular C files):
  62. *
  63. * Code:
  64. * KSLOG_ERROR(@"Some error message");
  65. *
  66. * Prints:
  67. * 2011-07-16 05:41:01.379 TestApp[4439:f803] ERROR: SomeClass.m (21): -[SomeFunction]: Some error message
  68. *
  69. * Code:
  70. * KSLOG_INFO(@"Info about %@", someObject);
  71. *
  72. * Prints:
  73. * 2011-07-16 05:44:05.239 TestApp[4473:f803] INFO : SomeClass.m (20): -[SomeFunction]: Info about <NSObject: 0xb622840>
  74. *
  75. *
  76. * The "BASIC" versions of the macros behave exactly like NSLog() or printf(),
  77. * except they respect the KSLogger_Level setting:
  78. *
  79. * Code:
  80. * KSLOGBASIC_ERROR(@"A basic log entry");
  81. *
  82. * Prints:
  83. * 2011-07-16 05:44:05.916 TestApp[4473:f803] A basic log entry
  84. *
  85. *
  86. * NOTE: In C files, use "" instead of @"" in the format field. Logging calls
  87. * in C files do not print the NSLog preamble:
  88. *
  89. * Objective-C version:
  90. * KSLOG_ERROR(@"Some error message");
  91. *
  92. * 2011-07-16 05:41:01.379 TestApp[4439:f803] ERROR: SomeClass.m (21): -[SomeFunction]: Some error message
  93. *
  94. * C version:
  95. * KSLOG_ERROR("Some error message");
  96. *
  97. * ERROR: SomeClass.c (21): SomeFunction(): Some error message
  98. *
  99. *
  100. * =============
  101. * LOCAL LOGGING
  102. * =============
  103. *
  104. * You can control logging messages at the local file level using the
  105. * "KSLogger_LocalLevel" define. Note that it must be defined BEFORE
  106. * including KSLogger.h
  107. *
  108. * The KSLOG_XX() and KSLOGBASIC_XX() macros will print out based on the LOWER
  109. * of KSLogger_Level and KSLogger_LocalLevel, so if KSLogger_Level is DEBUG
  110. * and KSLogger_LocalLevel is TRACE, it will print all the way down to the trace
  111. * level for the local file where KSLogger_LocalLevel was defined, and to the
  112. * debug level everywhere else.
  113. *
  114. * Example:
  115. *
  116. * // KSLogger_LocalLevel, if defined, MUST come BEFORE including KSLogger.h
  117. * #define KSLogger_LocalLevel TRACE
  118. * #import "KSLogger.h"
  119. *
  120. *
  121. * ===============
  122. * IMPORTANT NOTES
  123. * ===============
  124. *
  125. * The C logger changes its behavior depending on the value of the preprocessor
  126. * define KSLogger_CBufferSize.
  127. *
  128. * If KSLogger_CBufferSize is > 0, the C logger will behave in an async-safe
  129. * manner, calling write() instead of printf(). Any log messages that exceed the
  130. * length specified by KSLogger_CBufferSize will be truncated.
  131. *
  132. * If KSLogger_CBufferSize == 0, the C logger will use printf(), and there will
  133. * be no limit on the log message length.
  134. *
  135. * KSLogger_CBufferSize can only be set as a preprocessor define, and will
  136. * default to 1024 if not specified during compilation.
  137. */
  138. // ============================================================================
  139. #pragma mark - (internal) -
  140. // ============================================================================
  141. #ifndef HDR_KSLogger_h
  142. #define HDR_KSLogger_h
  143. #ifdef __cplusplus
  144. extern "C" {
  145. #endif
  146. #include <stdbool.h>
  147. #ifdef __OBJC__
  148. #import <CoreFoundation/CoreFoundation.h>
  149. void i_kslog_logObjC(const char* level,
  150. const char* file,
  151. int line,
  152. const char* function,
  153. CFStringRef fmt, ...);
  154. void i_kslog_logObjCBasic(CFStringRef fmt, ...);
  155. #define i_KSLOG_FULL(LEVEL,FILE,LINE,FUNCTION,FMT,...) i_kslog_logObjC(LEVEL,FILE,LINE,FUNCTION,(__bridge CFStringRef)FMT,##__VA_ARGS__)
  156. #define i_KSLOG_BASIC(FMT, ...) i_kslog_logObjCBasic((__bridge CFStringRef)FMT,##__VA_ARGS__)
  157. #else // __OBJC__
  158. void i_kslog_logC(const char* level,
  159. const char* file,
  160. int line,
  161. const char* function,
  162. const char* fmt, ...);
  163. void i_kslog_logCBasic(const char* fmt, ...);
  164. #define i_KSLOG_FULL i_kslog_logC
  165. #define i_KSLOG_BASIC i_kslog_logCBasic
  166. #endif // __OBJC__
  167. /* Back up any existing defines by the same name */
  168. #ifdef KS_NONE
  169. #define KSLOG_BAK_NONE KS_NONE
  170. #undef KS_NONE
  171. #endif
  172. #ifdef ERROR
  173. #define KSLOG_BAK_ERROR ERROR
  174. #undef ERROR
  175. #endif
  176. #ifdef WARN
  177. #define KSLOG_BAK_WARN WARN
  178. #undef WARN
  179. #endif
  180. #ifdef INFO
  181. #define KSLOG_BAK_INFO INFO
  182. #undef INFO
  183. #endif
  184. #ifdef DEBUG
  185. #define KSLOG_BAK_DEBUG DEBUG
  186. #undef DEBUG
  187. #endif
  188. #ifdef TRACE
  189. #define KSLOG_BAK_TRACE TRACE
  190. #undef TRACE
  191. #endif
  192. #define KSLogger_Level_None 0
  193. #define KSLogger_Level_Error 10
  194. #define KSLogger_Level_Warn 20
  195. #define KSLogger_Level_Info 30
  196. #define KSLogger_Level_Debug 40
  197. #define KSLogger_Level_Trace 50
  198. #define KS_NONE KSLogger_Level_None
  199. #define ERROR KSLogger_Level_Error
  200. #define WARN KSLogger_Level_Warn
  201. #define INFO KSLogger_Level_Info
  202. #define DEBUG KSLogger_Level_Debug
  203. #define TRACE KSLogger_Level_Trace
  204. #ifndef KSLogger_Level
  205. #define KSLogger_Level KSLogger_Level_Error
  206. #endif
  207. #ifndef KSLogger_LocalLevel
  208. #define KSLogger_LocalLevel KSLogger_Level_None
  209. #endif
  210. #define a_KSLOG_FULL(LEVEL, FMT, ...) \
  211. i_KSLOG_FULL(LEVEL, \
  212. __FILE__, \
  213. __LINE__, \
  214. __PRETTY_FUNCTION__, \
  215. FMT, \
  216. ##__VA_ARGS__)
  217. // ============================================================================
  218. #pragma mark - API -
  219. // ============================================================================
  220. /** Set the filename to log to.
  221. *
  222. * @param filename The file to write to (NULL = write to stdout).
  223. *
  224. * @param overwrite If true, overwrite the log file.
  225. */
  226. bool kslog_setLogFilename(const char* filename, bool overwrite);
  227. /** Clear the log file. */
  228. bool kslog_clearLogFile(void);
  229. /** Tests if the logger would print at the specified level.
  230. *
  231. * @param LEVEL The level to test for. One of:
  232. * KSLogger_Level_Error,
  233. * KSLogger_Level_Warn,
  234. * KSLogger_Level_Info,
  235. * KSLogger_Level_Debug,
  236. * KSLogger_Level_Trace,
  237. *
  238. * @return TRUE if the logger would print at the specified level.
  239. */
  240. #define KSLOG_PRINTS_AT_LEVEL(LEVEL) \
  241. (KSLogger_Level >= LEVEL || KSLogger_LocalLevel >= LEVEL)
  242. /** Log a message regardless of the log settings.
  243. * Normal version prints out full context. Basic version prints directly.
  244. *
  245. * @param FMT The format specifier, followed by its arguments.
  246. */
  247. #define KSLOG_ALWAYS(FMT, ...) a_KSLOG_FULL("FORCE", FMT, ##__VA_ARGS__)
  248. #define KSLOGBASIC_ALWAYS(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
  249. /** Log an error.
  250. * Normal version prints out full context. Basic version prints directly.
  251. *
  252. * @param FMT The format specifier, followed by its arguments.
  253. */
  254. #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Error)
  255. #define KSLOG_ERROR(FMT, ...) a_KSLOG_FULL("ERROR", FMT, ##__VA_ARGS__)
  256. #define KSLOGBASIC_ERROR(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
  257. #else
  258. #define KSLOG_ERROR(FMT, ...)
  259. #define KSLOGBASIC_ERROR(FMT, ...)
  260. #endif
  261. /** Log a warning.
  262. * Normal version prints out full context. Basic version prints directly.
  263. *
  264. * @param FMT The format specifier, followed by its arguments.
  265. */
  266. #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Warn)
  267. #define KSLOG_WARN(FMT, ...) a_KSLOG_FULL("WARN ", FMT, ##__VA_ARGS__)
  268. #define KSLOGBASIC_WARN(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
  269. #else
  270. #define KSLOG_WARN(FMT, ...)
  271. #define KSLOGBASIC_WARN(FMT, ...)
  272. #endif
  273. /** Log an info message.
  274. * Normal version prints out full context. Basic version prints directly.
  275. *
  276. * @param FMT The format specifier, followed by its arguments.
  277. */
  278. #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Info)
  279. #define KSLOG_INFO(FMT, ...) a_KSLOG_FULL("INFO ", FMT, ##__VA_ARGS__)
  280. #define KSLOGBASIC_INFO(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
  281. #else
  282. #define KSLOG_INFO(FMT, ...)
  283. #define KSLOGBASIC_INFO(FMT, ...)
  284. #endif
  285. /** Log a debug message.
  286. * Normal version prints out full context. Basic version prints directly.
  287. *
  288. * @param FMT The format specifier, followed by its arguments.
  289. */
  290. #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Debug)
  291. #define KSLOG_DEBUG(FMT, ...) a_KSLOG_FULL("DEBUG", FMT, ##__VA_ARGS__)
  292. #define KSLOGBASIC_DEBUG(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
  293. #else
  294. #define KSLOG_DEBUG(FMT, ...)
  295. #define KSLOGBASIC_DEBUG(FMT, ...)
  296. #endif
  297. /** Log a trace message.
  298. * Normal version prints out full context. Basic version prints directly.
  299. *
  300. * @param FMT The format specifier, followed by its arguments.
  301. */
  302. #if KSLOG_PRINTS_AT_LEVEL(KSLogger_Level_Trace)
  303. #define KSLOG_TRACE(FMT, ...) a_KSLOG_FULL("TRACE", FMT, ##__VA_ARGS__)
  304. #define KSLOGBASIC_TRACE(FMT, ...) i_KSLOG_BASIC(FMT, ##__VA_ARGS__)
  305. #else
  306. #define KSLOG_TRACE(FMT, ...)
  307. #define KSLOGBASIC_TRACE(FMT, ...)
  308. #endif
  309. // ============================================================================
  310. #pragma mark - (internal) -
  311. // ============================================================================
  312. /* Put everything back to the way we found it. */
  313. #undef ERROR
  314. #ifdef KSLOG_BAK_ERROR
  315. #define ERROR KSLOG_BAK_ERROR
  316. #undef KSLOG_BAK_ERROR
  317. #endif
  318. #undef WARNING
  319. #ifdef KSLOG_BAK_WARN
  320. #define WARNING KSLOG_BAK_WARN
  321. #undef KSLOG_BAK_WARN
  322. #endif
  323. #undef INFO
  324. #ifdef KSLOG_BAK_INFO
  325. #define INFO KSLOG_BAK_INFO
  326. #undef KSLOG_BAK_INFO
  327. #endif
  328. #undef DEBUG
  329. #ifdef KSLOG_BAK_DEBUG
  330. #define DEBUG KSLOG_BAK_DEBUG
  331. #undef KSLOG_BAK_DEBUG
  332. #endif
  333. #undef TRACE
  334. #ifdef KSLOG_BAK_TRACE
  335. #define TRACE KSLOG_BAK_TRACE
  336. #undef KSLOG_BAK_TRACE
  337. #endif
  338. #ifdef __cplusplus
  339. }
  340. #endif
  341. #endif // HDR_KSLogger_h