xref: /haiku/src/apps/haikudepot/model/Logger.h (revision 1978089f7cec856677e46204e992c7273d70b9af)
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