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
}
|