libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_logger.h
Go to the documentation of this file.
1/*! \file
2 * \brief GblLogger filterable log and logging macros
3 * \ingroup core
4 *
5 * This file provides the public API for creating and
6 * managing custom logger types as well as the utility
7 * macros for actually using the log system.
8 *
9 * \todo
10 * - migrate away from GblThd and towards GblThread
11 * - Spam filter: deduplicate messages within a certain interval
12 * - Default constructor values
13 *
14 * \author 2023 Falco Girgis
15 * \copyright MIT License
16 */
17
18#ifndef GIMBAL_LOGGER_H
19#define GIMBAL_LOGGER_H
20
21#include <time.h>
22#include "../meta/instances/gimbal_object.h"
23#include "../containers/gimbal_linked_list.h"
24
25/*! \name Type System
26 * \brief Type UUID and cast operators
27 * @{
28 */
29#define GBL_LOGGER_TYPE (GBL_TYPEID(GblLogger)) //!< Type UUID for GblLogger
30#define GBL_LOGGER(self) (GBL_CAST(GblLogger, self)) //!< Function-style cast to GblLogger
31#define GBL_LOGGER_CLASS(klass) (GBL_CLASS_CAST(GblLogger, klass)) //!< Function-style cast to GblLoggerClass
32#define GBL_LOGGER_GET_CLASS(self) (GBL_CLASSOF(GblLogger, self)) //!< Get GblLoggerClass from GblLogger
33//! @}
34
35/*! \name Logging Macros
36 * \brief Top-level macros used with logging system
37 * @{
38 */
39#define GBL_LOG_WRITE(flags, domain, ...) GblLogger_write(__FILE__, __func__, __LINE__,
40 domain, flags, __VA_ARGS__) //!< Generalized log write operation
41#define GBL_LOG_DEBUG(domain, ...) GBL_LOG_WRITE(GBL_LOG_DEBUG, domain, __VA_ARGS__) //!< Writes to log with GBL_LOG_DEBUG
42#define GBL_LOG_VERBOSE(domain, ...) GBL_LOG_WRITE(GBL_LOG_VERBOSE, domain, __VA_ARGS__) //!< Writes to log with GBL_LOG_VERBOSE
43#define GBL_LOG_INFO(domain, ...) GBL_LOG_WRITE(GBL_LOG_INFO, domain, __VA_ARGS__) //!< Writes to log with GBL_LOG_INFO
44#define GBL_LOG_WARN(domain, ...) GBL_LOG_WRITE(GBL_LOG_WARN, domain, __VA_ARGS__) //!< Writes to log with GBL_LOG_WARN
45#define GBL_LOG_ERROR(domain, ...) GBL_LOG_WRITE(GBL_LOG_ERROR, domain, __VA_ARGS__) //!< Writes to log with GBL_LOG_ERROR
46#define GBL_LOG_PUSH() GblLogger_push() //!< Pushes level to log stack
47#define GBL_LOG_POP(n) GblLogger_pop(n) //!< Pops N levels from log stack
48
49#define GBL_LOG_DEBUG_PUSH(domain, ...) GBL_LOG_MAKE_PUSH_(domain, GBL_LOG_DEBUG, __VA_ARGS__) //!< Writes to log with GBL_LOG_DEBUG, then pushes level to log stack
50#define GBL_LOG_VERBOSE_PUSH(domain, ...) GBL_LOG_MAKE_PUSH_(domain, GBL_LOG_VERBOSE, __VA_ARGS__) //!< Writes to log with GBL_LOG_VERBOSE, then pushes level to log stack
51#define GBL_LOG_INFO_PUSH(domain, ...) GBL_LOG_MAKE_PUSH_(domain, GBL_LOG_INFO, __VA_ARGS__) //!< Writes to log with GBL_LOG_INFO, then pushes level to log stack
52#define GBL_LOG_WARN_PUSH(domain, ...) GBL_LOG_MAKE_PUSH_(domain, GBL_LOG_WARN, __VA_ARGS__) //!< Writes to log with GBL_LOG_WARN, then pushes level to log stack
53#define GBL_LOG_ERROR_PUSH(domain, ...) GBL_LOG_MAKE_PUSH_(domain, GBL_LOG_ERROR, __VA_ARGS__) //!< Writes to log with GBL_LOG_ERROR, then pushes level to log stack
54
55#define GBL_LOG_DEBUG_SCOPE(domain, ...) GBL_LOG_MAKE_SCOPE_(domain, GBL_LOG_DEBUG, __VA_ARGS__) //!< Writes to log with GBL_LOG_DEBUG, then pushes level to log stack. Pops level when scope ends
56#define GBL_LOG_VERBOSE_SCOPE(domain, ...) GBL_LOG_MAKE_SCOPE_(domain, GBL_LOG_VERBOSE, __VA_ARGS__) //!< Writes to log with GBL_LOG_VERBOSE, then pushes level to log stack. Pops level when scope ends
57#define GBL_LOG_INFO_SCOPE(domain, ...) GBL_LOG_MAKE_SCOPE_(domain, GBL_LOG_INFO, __VA_ARGS__) //!< Writes to log with GBL_LOG_INFO, then pushes level to log stack. Pops level when scope ends
58#define GBL_LOG_WARN_SCOPE(domain, ...) GBL_LOG_MAKE_SCOPE_(domain, GBL_LOG_WARN, __VA_ARGS__) //!< Writes to log with GBL_LOG_WARN, then pushes level to log stack. Pops level when scope ends
59#define GBL_LOG_ERROR_SCOPE(domain, ...) GBL_LOG_MAKE_SCOPE_(domain, GBL_LOG_ERROR, __VA_ARGS__) //!< Writes to log with GBL_LOG_ERROR, then pushes level to log stack. Pops level when scope ends
60//! @}
61
62#define GBL_SELF_TYPE GblLogger
63
65
67
68//! Function signature for iterating over all loggers (see \ref GblLogger_foreach())
69typedef GblBool (*GblLoggerIterFn)(GblLogger* pLogger, void* pClosure);
70
71//! Flags used to tag a message or message filter
73 GBL_LOG_REENTRANT = 0x1, //!< Denotes a GblLogger's virtual methods are reentrant
74 GBL_LOG_DEBUG = 0x2, //!< Denotes a "debug" level message, which is typically disabled
75 GBL_LOG_VERBOSE = 0x4, //!< Denotes a "verbose" level message, which is regular-level
76 GBL_LOG_INFO = 0x8, //!< Denotes an "info" message, which is typically used for noteworthy events
77 GBL_LOG_WARN = 0x10, //!< Denotes a "warning" message, which means a potential issue has arisen
78 GBL_LOG_ERROR = 0x20, //!< Denotes an "error" message, which means something has failed
79 GBL_LOG_USER = 0x40 //!< Denotess the first flag which can be used for arbitrary userdata
80};
81
82/*! \struct GblLoggerClass
83 * \extends GblObjectClass
84 * \brief GblClass vtable for GblLogger
85 *
86 * GblLoggerClass provides virtual methods for implementing
87 * a logger back-end. These include push/pop operations for
88 * the stack-based structured logging as well as a generic
89 * write method for doing the actual message logging.
90 *
91 * \sa GblLogger
92 */
93GBL_CLASS_DERIVE(GblLogger, GblObject)
94 //! Virtual method used to do the actual log writing for a message
95 GBL_RESULT (*pFnWrite)(GBL_SELF,
96 const char* pFile,
97 const char* pFunction,
98 size_t line,
99 GblThd* pThread,
100 time_t timeStamp,
101 const char* pDomain,
102 GBL_LOG_FLAGS flags,
103 const char* pFmt,
104 va_list varArgs);
105 //! Virtual method used to signify that another level has been pushed onto the log stack
106 GBL_RESULT (*pFnPush) (GBL_SELF,
107 GblThd* pThread);
108 //! Virtual method to denote that that \param{count} levels have been popped from the log stack
109 GBL_RESULT (*pFnPop) (GBL_SELF,
110 GblThd* pThread,
111 size_t count);
113
114/*! \struct GblLogger
115 * \extends GblObject
116 * \ingroup core
117 * \brief Object used for implementing a custom logger
118 *
119 * GblLogger is used to create a new instance of a custom logger.
120 * You can either subclass it and reimplement its virtual methods or
121 * do so by giving it a floating class (see \ref {Classes::Floating Classes}).
122 *
123 * \sa GblLoggerClass
124 */
127 union {
128 GblLinkedListNode listNode; //!< Internal generic list node
129 GblLogger* pNext; //!< Internal pointer to next logger in list
130 };
131 GblBool reentrant; //!< Whether the logger is already handling a messaage
133 GblFlags flagsFilter; //!< Combination of GBL_LOG_FLAGS to filter messages for
135
136//! \cond
137GBL_PROPERTIES(GblLogger,
138 (flagsFilter, GBL_GENERIC, (READ, WRITE), GBL_FLAGS_TYPE),
139 (threadFilters, GBL_GENERIC, (READ, WRITE), GBL_POINTER_TYPE),
140 (domainFilters, GBL_GENERIC, (READ, WRITE), GBL_POINTER_TYPE)
141)
142//! \endcond
143
144// ===== Static Methods =====
145GBL_EXPORT GblType GblLogger_type (void) GBL_NOEXCEPT;
146GBL_EXPORT GBL_RESULT GblLogger_register (GblLogger* pLogger) GBL_NOEXCEPT;
147GBL_EXPORT GBL_RESULT GblLogger_unregister (GblLogger* pLogger) GBL_NOEXCEPT;
148
149GBL_EXPORT GblBool GblLogger_foreach (GblLoggerIterFn pIt,
150 void* pClosure) GBL_NOEXCEPT;
151
152GBL_EXPORT GBL_RESULT GblLogger_push (void) GBL_NOEXCEPT;
153GBL_EXPORT GBL_RESULT GblLogger_pop (size_t count) GBL_NOEXCEPT;
154GBL_EXPORT size_t GblLogger_depth (void) GBL_NOEXCEPT;
155
156GBL_EXPORT GBL_RESULT GblLogger_write (const char* pFile,
157 const char* pFunction,
158 size_t line,
159 const char* pDomain,
160 GBL_LOG_FLAGS flags,
161 const char* pFmt,
162 ...) GBL_NOEXCEPT;
163
164GBL_EXPORT GBL_RESULT GblLogger_writeVa (const char* pFile,
165 const char* pFunction,
166 size_t line,
167 const char* pDomain,
168 GBL_LOG_FLAGS flags,
169 const char* pFmt,
170 va_list varArgs) GBL_NOEXCEPT;
171// ===== Instance Methods =====
172GBL_EXPORT GblLogger* GblLogger_create (GblType derived,
173 size_t allocSize,
174 GblLoggerClass* pClass) GBL_NOEXCEPT;
175
176GBL_EXPORT GBL_RESULT GblLogger_construct (GBL_SELF,
177 GblType derived,
178 GblLoggerClass* pClass) GBL_NOEXCEPT;
179
181
182GBL_EXPORT GblBool GblLogger_hasFilter (GBL_CSELF,
183 const GblThd* pThread,
184 const char* pDomain,
186
187GBL_EXPORT GBL_RESULT GblLogger_setDomainFilters (GBL_SELF,
188 const char* domains[]) GBL_NOEXCEPT;
189
190GBL_EXPORT const char** GblLogger_domainFilters (GBL_CSELF) GBL_NOEXCEPT;
191
192GBL_EXPORT GblBool GblLogger_hasDomainFilter (GBL_CSELF,
193 const char* pDomain) GBL_NOEXCEPT;
194
195GBL_EXPORT GBL_RESULT GblLogger_setThreadFilters (GBL_SELF,
196 const GblThd* pThrs[]) GBL_NOEXCEPT;
197
198GBL_EXPORT const GblThd**
199 GblLogger_threadFilters (GBL_CSELF) GBL_NOEXCEPT;
200
201GBL_EXPORT GblBool GblLogger_hasThreadFilter (GBL_CSELF,
202 const GblThd* pThr) GBL_NOEXCEPT;
203
205
206#undef GBL_SELF_TYPE
207
208// Helper macro for GBL_LOG_XXX_PUSH
209#define GBL_LOG_MAKE_PUSH_(domain, level_macro, ...)
211 level_macro(domain, __VA_ARGS__);
212 GBL_LOG_PUSH();
214
215// Helper macro for GBL_LOG_XXX_SCOPE
216#define GBL_LOG_MAKE_SCOPE_(domain, level_macro, ...)
218 level_macro(domain, __VA_ARGS__);
219 } GBL_STMT_END;
221
222#endif // GIMBAL_LOGGER_H
#define GBL_STMT_START
#define GBL_NOEXCEPT
#define GBL_STMT_END
#define GBL_DECLS_BEGIN
#define GBL_FORWARD_DECLARE_STRUCT(S)
#define GBL_TYPEID(instanceStruct)
#define GBL_INSTANCE_DERIVE(derivedInstance, baseInstance)
#define GBL_PRIVATE_BEGIN
#define GBL_CLASS_DERIVE(...)
#define GBL_DECLARE_FLAGS(F)
#define GBL_INSTANCE_END
#define GBL_EXPORT
#define GBL_CLASS_END
#define GBL_PRIVATE_END
Private data structure.
#define GBL_FLAGS_TYPE
GblType UUID for flags.
#define GBL_LOG_ERROR(domain,...)
Writes to log with GBL_LOG_ERROR.
#define GBL_LOG_WRITE(flags, domain,...)
Generalized log write operation.
#define GBL_LOG_INFO(domain,...)
Writes to log with GBL_LOG_INFO.
#define GBL_LOG_PUSH()
Pushes level to log stack.
#define GBL_LOG_DEBUG(domain,...)
Writes to log with GBL_LOG_DEBUG.
#define GBL_LOG_MAKE_SCOPE_(domain, level_macro,...)
#define GBL_LOG_VERBOSE(domain,...)
Writes to log with GBL_LOG_VERBOSE.
#define GBL_LOG_WARN(domain,...)
Writes to log with GBL_LOG_WARN.
#define GBL_LOG_POP(n)
Pops N levels from log stack.
GBL_LOG_FLAGS
@ GBL_LOG_INFO
Denotes an "info" message, which is typically used for noteworthy events.
@ GBL_LOG_VERBOSE
Denotes a "verbose" level message, which is regular-level.
@ GBL_LOG_REENTRANT
Denotes a GblLogger's virtual methods are reentrant.
@ GBL_LOG_WARN
Denotes a "warning" message, which means a potential issue has arisen.
@ GBL_LOG_ERROR
Denotes an "error" message, which means something has failed.
@ GBL_LOG_DEBUG
Denotes a "debug" level message, which is typically disabled.
@ GBL_LOG_USER
Denotess the first flag which can be used for arbitrary userdata.
#define GBL_LOG_MAKE_PUSH_(domain, level_macro,...)
#define GBL_SCOPE(begin, end)
#define GBL_PROPERTIES(object,...)
Declares a list of properties for the given object/instance structure.
uint32_t GblFlags
Standard-sized flags type, 32-bits across platforms.
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)
uint16_t GblRefCount
Type able to hold a reference counter across the codebase.
#define GBL_POINTER_TYPE
uintptr_t GblType
Meta Type UUID.
Definition gimbal_type.h:52
Object used for implementing a custom logger.
GblLinkedListNode listNode
Internal generic list node.
GblLogger * pNext
Internal pointer to next logger in list.
GblFlags flagsFilter
Combination of GBL_LOG_FLAGS to filter messages for.
GblBool reentrant
Whether the logger is already handling a messaage.