File: spy_log.hpp

package info (click to toggle)
sight 25.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 42,184 kB
  • sloc: cpp: 289,476; xml: 17,257; ansic: 9,878; python: 1,379; sh: 144; makefile: 33
file content (351 lines) | stat: -rw-r--r-- 13,016 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/************************************************************************
 *
 * Copyright (C) 2009-2025 IRCAD France
 * Copyright (C) 2012-2020 IHU Strasbourg
 *
 * This file is part of Sight.
 *
 * Sight is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Sight is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Sight. If not, see <https://www.gnu.org/licenses/>.
 *
 ***********************************************************************/

/**
 * @file spy_log.hpp
 * @brief This file defines SpyLog macros.
 * These macros are used to log messages to a file or to the console during
 * application execution.
 *
 * Six log levels are defined :
 * -# Fatal
 * -# Error
 * -# Warning
 * -# Info
 * -# Debug
 * -# Trace
 *
 * Log level is set by defining SPYLOG_LEVEL to N where 0 < N <= 6. If log
 * level is set to N, every log level lesser than N will be enabled, the other
 * macro will be define but won't have any effect.
 *
 * Each log level macro can accept strings or stringstreams:
 *   - Example : SIGHT_INFO( "Count : " << i );
 *
 * FATAL macros have a particular behavior : the application is aborted after
 * the message was logged.
 *
 *
 */

#pragma once

#ifdef _DEBUG
    #ifdef WIN32
        #define DEBUG_BREAK() __debugbreak()
    #else
        #include <csignal>
        #define DEBUG_BREAK() do{std::ignore = std::raise(SIGTRAP); std::abort();}while(0)
    #endif

    #define SPYLOG_ABORT() DEBUG_BREAK()
#else
    #define SPYLOG_ABORT() std::abort()
#endif

#include <cassert>
#include <cstring>
#include <sstream>

# include <core/log/spy_logger.hpp>

// -----------------------------------------------------------------------------
constexpr static const char* strip_source_path(const char* const _path)
{
#ifndef SIGHT_SOURCE_DIR
    return path;
#else
    if(_path[0] == '.')
    {
        // If the path is relative, we return the path since it's a nightmare to deal with paths relative to the working
        // directory of the currently running compiler..
        // This is maybe doable by passing the working directory of the currently running compiler as a define and
        // resolve by hand the relative path ...in pure constexpr ! Good luck...
        return _path;
    }

    // Otherwise, we assume the path is absolute
    // We check if the path belongs to sight source
    constexpr std::size_t sight_source_length = sizeof(SIGHT_SOURCE_DIR) - 1;

    // If the path does not start with the sight source directory, we return the path
    for(std::size_t i = 0 ; i < sight_source_length ; ++i)
    {
        const auto path_c   = _path[i];
        const auto source_c = SIGHT_SOURCE_DIR[i];

        if(path_c == '\0')
        {
            // If the path is shorter than the sight source directory, we return the path
            return _path;
        }

        if((path_c == '/' || path_c == '\\') && source_c != '/' && source_c != '\\')
        {
            // If current path character is a path deliminator and the current source character is not, we return path
            return _path;
        }

        if(path_c != '/' && path_c != '\\' && (source_c == '/' || source_c == '\\'))
        {
            // If path character is not a path deliminator and the current source character is one, we return path
            return _path;
        }

        if(path_c != '/' && path_c != '\\' && source_c != '/' && source_c != '\\' && path_c != source_c)
        {
            // If path character is not a path deliminator and the current source character is also not, we return path
            // if they are different
            return _path;
        }
    }

    // Otherwise, we strip the sight source directory from the path
    // /home/user/sight/lib/core/log/spy_log.hpp => lib/core/log/spy_log.hpp
    return _path + sight_source_length + 1;
#endif
}

// This force to evaluate the constexpr at compile time, even on windows without optimization
#define SIGHT_SOURCE_FILE [] () constexpr {constexpr auto stripped = strip_source_path(__FILE__); return stripped;} ()

/**
 * @cond
 */

// -----------------------------------------------------------------------------

# ifndef FWCORE_EXPR_BLOCK
#  define FWCORE_EXPR_BLOCK(expr) do{expr}while(0)
# endif

# define FWCORE_IF(cond, code) if(cond){code}

# define SL_LOG(log, loglevel, message) FWCORE_EXPR_BLOCK( \
            std::stringstream osl_str; \
            osl_str << message; \
            log.loglevel(osl_str.str(), SIGHT_SOURCE_FILE, __LINE__); \
)

// -----------------------------------------------------------------------------

#define SL_TRACE(log, message) SL_LOG(log, trace, message);
#define SL_TRACE_IF(log, message, cond) FWCORE_IF(cond, SL_LOG(log, trace, message); )

#define SL_DEBUG(log, message) SL_LOG(log, debug, message);
#define SL_DEBUG_IF(log, message, cond) FWCORE_IF(cond, SL_LOG(log, debug, message); )

#define SL_INFO(log, message) SL_LOG(log, info, message);
#define SL_INFO_IF(log, message, cond) FWCORE_IF(cond, SL_LOG(log, info, message); )

#define SL_WARN(log, message) SL_LOG(log, warn, message);
#define SL_WARN_IF(log, message, cond) FWCORE_IF(cond, SL_LOG(log, warn, message); )

#define SL_ERROR(log, message) SL_LOG(log, error, message);
#define SL_ERROR_IF(log, message, cond) FWCORE_IF(cond, SL_LOG(log, error, message); )

#define SL_FATAL(log, message) SL_LOG(log, fatal, message); SPYLOG_ABORT();
#define SL_FATAL_IF(log, message, cond) FWCORE_IF(cond, SL_FATAL(log, message); )

// -----------------------------------------------------------------------------

# ifdef _DEBUG
#  ifdef WIN32
#  define SL_ASSERT_IMPL(log, message, cond) FWCORE_EXPR_BLOCK( \
            FWCORE_IF( \
                !(cond), \
                std::stringstream osl_str1; \
                osl_str1 << "Assertion '" \
                <<#cond << "' failed.\n" << message; \
                log.fatal(osl_str1.str(), SIGHT_SOURCE_FILE, __LINE__); \
                _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, NULL, "%s", osl_str1.str().c_str()); \
                __debugbreak(); \
            ) \
)
#  else
#  define SL_ASSERT_IMPL(log, message, cond) FWCORE_EXPR_BLOCK( \
            FWCORE_IF( \
                !(cond), \
                std::stringstream osl_str1; \
                osl_str1 << "Assertion '" \
                <<#cond << "' failed: " << message; \
                log.fatal(osl_str1.str(), SIGHT_SOURCE_FILE, __LINE__); \
                SPYLOG_ABORT(); \
            ) \
)
#  endif

#  define SL_ASSERT(log, message, cond) FWCORE_EXPR_BLOCK( \
            FWCORE_IF( \
                !(cond), \
                std::stringstream osl_str; \
                osl_str << message; \
                SL_ASSERT_IMPL(log, osl_str.str(), cond); \
            ) \
)
# else
#  define SL_ASSERT(log, message, cond) // empty
# endif

// -----------------------------------------------------------------------------

#  define SPYLOG_SPYLOGGER \
        sight::core::log::g_logger

// -----------------------------------------------------------------------------

/**
 * @endcond
 */

/** @{ */
/** Debug message macros.  */
# define SIGHT_DEBUG(message) SL_DEBUG(SPYLOG_SPYLOGGER, message)
/** @deprecated @sight22, use SIGHT_DEBUG instead. */
# define OSIGHT_DEBUG(message) SL_DEBUG(SPYLOG_SPYLOGGER, message); OSIGHT_DEPRECATED()
/** Conditional debug message macros.  */
# define SIGHT_DEBUG_IF(message, cond) SL_DEBUG_IF(SPYLOG_SPYLOGGER, message, cond)
/** @deprecated @sight22, use SIGHT_DEBUG_IF instead. */
# define OSIGHT_DEBUG_IF(message, cond) SL_DEBUG_IF(SPYLOG_SPYLOGGER, message, cond); OSIGHT_DEPRECATED()
/**  @} */

/** @{ */
/** Info message macros.  */
# define SIGHT_INFO(message) SL_INFO(SPYLOG_SPYLOGGER, message)
/** @deprecated @sight22, use SIGHT_INFO instead. */
# define OSIGHT_INFO(message) SL_INFO(SPYLOG_SPYLOGGER, message); OSIGHT_DEPRECATED()
/** Conditional info message macros.  */
# define SIGHT_INFO_IF(message, cond) SL_INFO_IF(SPYLOG_SPYLOGGER, message, cond)
/** @deprecated @sight22, use SIGHT_INFO_IF instead. */
# define OSIGHT_INFO_IF(message, cond) SL_INFO_IF(SPYLOG_SPYLOGGER, message, cond); OSIGHT_DEPRECATED()
/**  @} */

/** @{ */
/** Warning message macros.  */
# define SIGHT_WARN(message) SL_WARN(SPYLOG_SPYLOGGER, message)
/** @deprecated @sight22, use SIGHT_WARN instead.  */
# define OSIGHT_WARN(message) SL_WARN(SPYLOG_SPYLOGGER, message); OSIGHT_DEPRECATED()
/** Conditional warning message macros.  */
# define SIGHT_WARN_IF(message, cond) SL_WARN_IF(SPYLOG_SPYLOGGER, message, cond)
/** @deprecated @sight22, use SIGHT_WARN_IF instead. */
# define OSIGHT_WARN_IF(message, cond) SL_WARN_IF(SPYLOG_SPYLOGGER, message, cond); OSIGHT_DEPRECATED()
/**  @} */

/** @{ */
/** Error message macros.  */
# define SIGHT_ERROR(message) SL_ERROR(SPYLOG_SPYLOGGER, message)
/** @deprecated @sight22, use SIGHT_ERROR instead.  */
# define OSIGHT_ERROR(message) SL_ERROR(SPYLOG_SPYLOGGER, message); OSIGHT_DEPRECATED()
/** Conditional error message macros.  */
# define SIGHT_ERROR_IF(message, cond) SL_ERROR_IF(SPYLOG_SPYLOGGER, message, cond)
/** @deprecated @sight22, use SIGHT_ERROR_IF instead.  */
# define OSIGHT_ERROR_IF(message, cond) SL_ERROR_IF(SPYLOG_SPYLOGGER, message, cond); OSIGHT_DEPRECATED()
/**  @} */

/** @{ */
/** Fatal message macros.  */
# define SIGHT_FATAL(message) SL_FATAL(SPYLOG_SPYLOGGER, message)
/** @deprecated @sight22, use SIGHT_FATAL instead.  */
# define OSIGHT_FATAL(message) SL_FATAL(SPYLOG_SPYLOGGER, message); OSIGHT_DEPRECATED()
/** Conditional fatal message macros.  */
# define SIGHT_FATAL_IF(message, cond) SL_FATAL_IF(SPYLOG_SPYLOGGER, message, cond)
/** @deprecated @sight22, use SIGHT_FATAL_IF instead.  */
# define OSIGHT_FATAL_IF(message, cond) SL_FATAL_IF(SPYLOG_SPYLOGGER, message, cond); OSIGHT_DEPRECATED()
/**  @} */

/**
 * @name Special macros
 * @{ */

/** @brief work like 'assert' from 'cassert', with in addition a message logged by
 * spylog (with FATAL loglevel)  */
# define SIGHT_ASSERT(message, cond) \
        SL_ASSERT(SPYLOG_SPYLOGGER, message, cond)
# define OSIGHT_ASSERT(message, cond) \
        SL_ASSERT(SPYLOG_SPYLOGGER, message, cond)

// -----------------------------------------------------------------------------

# ifdef __GNUC__ // with GCC
#  define SIGHT_PRETTY_FUNC() __PRETTY_FUNCTION__
# elif defined(_MSC_VER) // with MSC
#  define SIGHT_PRETTY_FUNC() __FUNCSIG__
# else
#  define SIGHT_PRETTY_FUNC() __func__
# endif
/**  @} */

/**
 * @brief Use this macro when deprecating a function to warn the developer.
 */
#define FW_DEPRECATED(old_fn_name, new_fn_name, version) \
        SIGHT_ERROR( \
            "[DEPRECATED] '" << old_fn_name << "' is deprecated and will be removed in '" << version << "', use '" \
            << new_fn_name << "' instead. It is still used by '" + this->get_classname() + "'." \
        );

/**
 * @brief Use this macro when deprecating a function to warn the developer.
 */
#define FW_DEPRECATED_IF(old_fn_name, new_fn_name, version, condition) \
        SIGHT_ERROR_IF( \
            "[DEPRECATED] '" << old_fn_name << "' is deprecated and will be removed in '" << version << "', use '" \
            << new_fn_name << "' instead. It is still used by '" + this->get_classname() + "'.", \
            condition \
        );

/**
 * @brief Use this macro when deprecating something to warn the developer.
 */
#define FW_DEPRECATED_MSG(message, version) \
        SIGHT_ERROR("[DEPRECATED] " << message << " It will be removed in '" << version << "'");

/**
 * @brief Use this macro when deprecating something to warn the developer.
 */
#define FW_DEPRECATED_MSG_IF(message, version, condition) \
        SIGHT_ERROR_IF("[DEPRECATED] " << message << " It will be removed in '" << version << "'", condition);

/**
 * @brief Use this macro when deprecating a service key to warn the developer.
 */
#define FW_DEPRECATED_KEY(new_key, access, version) \
        SIGHT_ERROR( \
            "[DEPRECATED] The key '" \
            << new_key << "' is not correctly set. Please correct the configuration to set an '" \
            << access << "' key named '" << new_key << "'. The support of the old key will be removed in '" \
            << version << "'." \
        );

//------------------------------------------------------------------------------

inline void osight_deprecated()
{
    // Empty function to trigger deprecation warnings
}

//------------------------------------------------------------------------------

inline void sight_trace_deprecated()
{
    // Empty function to trigger deprecation warnings
}