Viskores  1.0
Logging.h
Go to the documentation of this file.
1 //============================================================================
2 // The contents of this file are covered by the Viskores license. See
3 // LICENSE.txt for details.
4 //
5 // By contributing to this file, all contributors agree to the Developer
6 // Certificate of Origin Version 1.1 (DCO 1.1) as stated in DCO.txt.
7 //============================================================================
8 
9 //============================================================================
10 // Copyright (c) Kitware, Inc.
11 // All rights reserved.
12 // See LICENSE.txt for details.
13 //
14 // This software is distributed WITHOUT ANY WARRANTY; without even
15 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 // PURPOSE. See the above copyright notice for more information.
17 //============================================================================
18 #ifndef viskores_cont_Logging_h
19 #define viskores_cont_Logging_h
20 
23 
24 #include <viskores/Types.h>
25 
27 
28 #include <iostream>
29 #include <memory>
30 #include <sstream>
31 #include <string>
32 #include <typeindex>
33 #include <typeinfo>
34 
109 
121 
134 
137 
140 
153 
156 
160 
165 
170 
178 
186 
198 
199 #define VISKORES_CONCAT_IMPL(s1, s2) s1##s2
200 #define VISKORES_CONCAT(s1, s2) VISKORES_CONCAT_IMPL(s1, s2)
201 
202 #ifdef __COUNTER__
203 #define VISKORES_ANONYMOUS_VARIABLE VISKORES_CONCAT(viskores_anonymous_, __COUNTER__)
204 #else
205 #define VISKORES_ANONYMOUS_VARIABLE VISKORES_CONCAT(viskores_anonymous_, __LINE__)
206 #endif
207 
208 #if defined(VISKORES_ENABLE_LOGGING)
209 
210 #define VISKORES_LOG_IF_S(level, cond, ...) \
211  viskores::cont::LogCondStream(level, cond, __FILE__, __LINE__) << __VA_ARGS__
212 
213 #define VISKORES_LOG_IF_F(level, cond, ...) \
214  viskores::cont::LogCond(level, cond, __FILE__, __LINE__, __VA_ARGS__)
215 
216 #define VISKORES_LOG_S(level, ...) VISKORES_LOG_IF_S(level, true, __VA_ARGS__)
217 #define VISKORES_LOG_F(level, ...) VISKORES_LOG_IF_F(level, true, __VA_ARGS__)
218 
219 #define VISKORES_LOG_SCOPE(level, ...) \
220  viskores::cont::detail::LogScope VISKORES_ANONYMOUS_VARIABLE \
221  { \
222  level, __FILE__, __LINE__, __VA_ARGS__ \
223  }
224 
225 #define VISKORES_LOG_SCOPE_FUNCTION(level) VISKORES_LOG_SCOPE(level, __func__)
226 #define VISKORES_LOG_ALWAYS_S(level, ...) VISKORES_LOG_S(level, __VA_ARGS__)
227 
228 
229 // Convenience macros:
230 
231 // Cast success:
232 #define VISKORES_LOG_CAST_SUCC(inObj, outObj) \
233  VISKORES_LOG_F(viskores::cont::LogLevel::Cast, \
234  "Cast succeeded: %s (%p) --> %s (%p)", \
235  viskores::cont::TypeToString(inObj).c_str(), \
236  &inObj, \
237  viskores::cont::TypeToString(outObj).c_str(), \
238  &outObj)
239 
240 // Cast failure:
241 #define VISKORES_LOG_CAST_FAIL(inObj, outType) \
242  VISKORES_LOG_F(viskores::cont::LogLevel::Cast, \
243  "Cast failed: %s (%p) --> %s", \
244  viskores::cont::TypeToString(inObj).c_str(), \
245  &inObj, \
246  viskores::cont::TypeToString<outType>().c_str())
247 
248 // TryExecute failure
249 #define VISKORES_LOG_TRYEXECUTE_FAIL(errorMessage, functorName, deviceId) \
250  VISKORES_LOG_S(viskores::cont::LogLevel::Error, \
251  "TryExecute encountered an error: " << errorMessage); \
252  VISKORES_LOG_S(viskores::cont::LogLevel::Error, "Failing functor: " << functorName); \
253  VISKORES_LOG_S(viskores::cont::LogLevel::Error, "Failing device: " << deviceId.GetName())
254 
255 // Same, but disabling device:
256 #define VISKORES_LOG_TRYEXECUTE_DISABLE(errorMessage, functorName, deviceId) \
257  VISKORES_LOG_S(viskores::cont::LogLevel::Error, \
258  "TryExecute encountered an error: " << errorMessage); \
259  VISKORES_LOG_S(viskores::cont::LogLevel::Error, "Failing functor: " << functorName); \
260  VISKORES_LOG_S(viskores::cont::LogLevel::Error, "Failing device: " << deviceId.GetName()); \
261  VISKORES_LOG_S(viskores::cont::LogLevel::Error, "The failing device has been disabled.")
262 
263 // Custom log level
264 #define VISKORES_DEFINE_USER_LOG_LEVEL(name, offset) \
265  static constexpr viskores::cont::LogLevel name = static_cast<viskores::cont::LogLevel>( \
266  static_cast<typename std::underlying_type<viskores::cont::LogLevel>::type>( \
267  viskores::cont::LogLevel::UserFirst) + \
268  offset % \
269  static_cast<typename std::underlying_type<viskores::cont::LogLevel>::type>( \
270  viskores::cont::LogLevel::UserLast))
271 
272 #else // VISKORES_ENABLE_LOGGING
273 
274 #define VISKORES_LOG_S(level, ...)
275 #define VISKORES_LOG_F(level, ...)
276 #define VISKORES_LOG_IF_S(level, cond, ...)
277 #define VISKORES_LOG_IF_F(level, cond, ...)
278 #define VISKORES_LOG_SCOPE(level, ...)
279 #define VISKORES_LOG_SCOPE_FUNCTION(level)
280 #define VISKORES_LOG_ERROR_CONTEXT(desc, data)
281 #define VISKORES_LOG_CAST_SUCC(inObj, outObj)
282 #define VISKORES_LOG_CAST_FAIL(inObj, outType)
283 #define VISKORES_DEFINE_USER_LOG_LEVEL(name, offset)
284 
285 // Always emitted. When logging is disabled, std::cerr is used.
286 
287 #define VISKORES_LOG_ALWAYS_S(level, ...) \
288  (static_cast<int>(level) < 0 ? std::cerr : std::cout) \
289  << viskores::cont::GetLogLevelName(level) << ": " << __VA_ARGS__ << "\n"
290 
291 // TryExecute failures are still important enough to log, but we just write to
292 // std::cerr when logging is disabled.
293 #define VISKORES_LOG_TRYEXECUTE_FAIL(errorMessage, functorName, deviceId) \
294  std::cerr << "Error: TryExecute encountered an error: " << errorMessage << "\n" \
295  << "\t- Failing functor: " << functorName << "\n" \
296  << "\t- Failing device: " << deviceId.GetName() << "\n\n"
297 #define VISKORES_LOG_TRYEXECUTE_DISABLE(errorMessage, functorName, deviceId) \
298  std::cerr << "Error: TryExecute encountered an error: " << errorMessage << "\n" \
299  << "\t- Failing functor: " << functorName << "\n" \
300  << "\t- Failing device: " << deviceId.GetName() << "\n" \
301  << "The failing device has been disabled.\n\n"
302 
303 #endif // VISKORES_ENABLE_LOGGING
304 
305 namespace viskores
306 {
307 namespace cont
308 {
309 
311 enum class LogLevel
312 {
315  Off = -9, //loguru::Verbosity_OFF,
316 
318  Fatal = -3, // loguru::Verbosity_FATAL,
319 
321  Error = -2, // loguru::Verbosity_ERROR,
322 
324  Warn = -1, // loguru::Verbosity_WARNING,
325 
328  Info = 0, //loguru::Verbosity_INFO,
329 
332  UserFirst = 1,
334  UserLast = 255,
335 
338 
341  Perf,
342 
344  MemCont,
345 
347  MemExec,
348 
350  MemTransfer,
351 
354 
357  Cast,
358 
363  UserVerboseFirst = 1024,
365  UserVerboseLast = 2047
366 };
367 
368 
385 VISKORES_CONT_EXPORT
387 void InitLogging(int& argc,
388  char* argv[],
389  const std::string& loggingFlag = "--viskores-log-level",
390  const std::string& loggingEnv = "VISKORES_LOG_LEVEL");
391 VISKORES_CONT_EXPORT
393 void InitLogging();
401 VISKORES_CONT_EXPORT
403 void SetStderrLogLevel(const char* verbosity);
404 
405 VISKORES_CONT_EXPORT
413 VISKORES_CONT_EXPORT
416 
426 VISKORES_CONT_EXPORT
428 void SetLogLevelName(viskores::cont::LogLevel level, const std::string& name);
429 
435 VISKORES_CONT_EXPORT
437 std::string GetLogLevelName(viskores::cont::LogLevel level);
438 
443 VISKORES_CONT_EXPORT
445 void SetLogThreadName(const std::string& name);
446 VISKORES_CONT_EXPORT
448 std::string GetLogThreadName();
451 // Per-thread error context, not currently used, undocumented....
452 VISKORES_CONT_EXPORT
454 std::string GetLogErrorContext();
455 
461 VISKORES_CONT_EXPORT
463 std::string GetStackTrace(viskores::Int32 skip = 0);
464 
466 VISKORES_CONT_EXPORT
471 std::string GetHumanReadableSize(viskores::UInt64 bytes, int prec = 2);
472 
473 template <typename T>
474 VISKORES_CONT inline std::string GetHumanReadableSize(T&& bytes, int prec = 2)
475 {
476  return GetHumanReadableSize(static_cast<viskores::UInt64>(std::forward<T>(bytes)), prec);
477 }
479 
481 VISKORES_CONT_EXPORT
485 std::string GetSizeString(viskores::UInt64 bytes, int prec = 2);
486 
487 template <typename T>
488 VISKORES_CONT inline std::string GetSizeString(T&& bytes, int prec = 2)
489 {
490  return GetSizeString(static_cast<viskores::UInt64>(std::forward<T>(bytes)), prec);
491 }
493 
499 VISKORES_CONT_EXPORT VISKORES_CONT std::string TypeToString(const std::type_info& t);
500 VISKORES_CONT_EXPORT VISKORES_CONT std::string TypeToString(const std::type_index& t);
501 template <typename T>
502 inline VISKORES_CONT std::string TypeToString()
503 {
504  return TypeToString(typeid(T));
505 }
506 template <typename T>
507 inline VISKORES_CONT std::string TypeToString(const T&)
508 {
509  return TypeToString(typeid(T));
510 }
513 #ifdef VISKORES_ENABLE_LOGGING
514 
524 VISKORES_CONT_EXPORT
526 void LogCond(LogLevel level, bool cond, const char* file, unsigned line, const char* format...);
527 
528 namespace detail
529 {
530 
538 class VISKORES_CONT_EXPORT LogScope
539 {
540  struct InternalStruct;
541  std::unique_ptr<InternalStruct> Internals;
542 
543 public:
544  /*
545  * \param level Desired LogLevel value for the log message.
546  * \param cond When false this function is no-op.
547  * \param format Printf like format string.
548  */
550  LogScope(LogLevel level, const char* file, unsigned line, const char* format...);
551 
552  VISKORES_CONT ~LogScope();
553 };
554 
555 
556 } // namespace detail
557 
563 struct VISKORES_CONT_EXPORT LogCondStream
564 {
566  LogCondStream(LogLevel level, bool cond, const char* file, int line)
567  : Level(level)
568  , Condition(cond)
569  , File(file)
570  , Line(line)
571  {
572  }
573 
575  ~LogCondStream() noexcept(false);
576 
577  template <typename T>
578  VISKORES_CONT LogCondStream& operator<<(const T& in)
579  {
580  SStream << in;
581  return *this;
582  }
583 
585  LogCondStream& operator<<(std::ostream& (*f)(std::ostream&))
586  {
587  f(SStream);
588  return *this;
589  }
590 
591 private:
593  bool Condition;
594  const char* File;
595  int Line;
596  std::ostringstream SStream;
597 };
598 #endif // VISKORES_ENABLE_LOGGING
599 
600 }
601 } // end namespace viskores::cont
602 
603 #endif // viskores_cont_Logging_h
viskores::cont::LogLevel::UserVerboseFirst
@ UserVerboseFirst
The first in a range of logging levels reserved for code that uses Viskores.
viskores::cont::LogCondStream::SStream
std::ostringstream SStream
Definition: Logging.h:596
viskores::cont::LogCond
void LogCond(LogLevel level, bool cond, const char *file, unsigned line, const char *format...)
Conditionally logs a message with a printf-like format.
Types.h
viskores::cont::LogLevel::Warn
@ Warn
Less important user errors, such as out-of-bounds parameters.
viskores::cont::GetHumanReadableSize
std::string GetHumanReadableSize(viskores::UInt64 bytes, int prec=2)
Convert a size in bytes to a human readable string (such as "64 bytes", "1.44 MiB",...
viskores::cont::GetStderrLogLevel
viskores::cont::LogLevel GetStderrLogLevel()
Get the active highest log level that will be printed to stderr.
viskores::cont::SetStderrLogLevel
void SetStderrLogLevel(const char *verbosity)
Set the range of log levels that will be printed to stderr.
viskores::cont::LogLevel::Info
@ Info
Information messages (detected hardware, etc) and temporary debugging output.
viskores::cont::LogCondStream::operator<<
LogCondStream & operator<<(std::ostream &(*f)(std::ostream &))
Definition: Logging.h:585
viskores::cont::LogLevel::UserLast
@ UserLast
The last in a range of logging levels reserved for code that uses Viskores.
viskores::cont::LogLevel::Fatal
@ Fatal
Fatal errors that should abort execution.
viskores::cont::LogLevel::Cast
@ Cast
Reports when a dynamic object is (or is not) resolved via a CastAndCall or other casting method.
ExportMacros.h
viskores::cont::GetLogErrorContext
std::string GetLogErrorContext()
viskores::cont::GetLogThreadName
std::string GetLogThreadName()
Specifies a humman-readable name to identify the current thread in the log output.
viskores::cont::LogCondStream::Level
LogLevel Level
Definition: Logging.h:592
VISKORES_CONT
#define VISKORES_CONT
Definition: ExportMacros.h:65
viskores
Groups connected points that have the same field value.
Definition: Atomic.h:27
viskores::cont::LogLevel
LogLevel
Log levels for use with the logging macros.
Definition: Logging.h:311
viskores::cont::LogLevel::UserFirst
@ UserFirst
The first in a range of logging levels reserved for code that uses Viskores.
viskores::cont::LogCondStream
Conditionally logs a message with a stream-like interface.
Definition: Logging.h:563
Configure.h
viskores::cont::LogCondStream::LogCondStream
LogCondStream(LogLevel level, bool cond, const char *file, int line)
Definition: Logging.h:566
viskores::cont::LogLevel::KernelLaunches
@ KernelLaunches
Details on device-side kernel launches.
viskores::cont::LogLevel::MemExec
@ MemExec
Device-side resource allocations/frees (e.g ArrayHandle device buffers).
viskores::cont::GetStackTrace
std::string GetStackTrace(viskores::Int32 skip=0)
Returns a stacktrace on supported platforms.
viskores::cont::LogCondStream::Condition
bool Condition
Definition: Logging.h:593
viskores::Ray
Represent an infinite or semi-infinite line segment with a point and a direction.
Definition: Geometry.h:29
viskores::cont::LogLevel::Off
@ Off
A placeholder used to silence all logging.
viskores::cont::LogLevel::DevicesEnabled
@ DevicesEnabled
Information about which devices are enabled/disabled.
viskores::cont::LogLevel::MemCont
@ MemCont
Host-side resource allocations/frees (e.g. ArrayHandle control buffers).
viskores::UInt64
unsigned long long UInt64
Base type to use for 64-bit signed integer numbers.
Definition: Types.h:215
viskores::Int32
int32_t Int32
Base type to use for 32-bit signed integer numbers.
Definition: Types.h:189
viskores::cont::LogCondStream::File
const char * File
Definition: Logging.h:594
viskores::cont::InitLogging
void InitLogging(int &argc, char *argv[], const std::string &loggingFlag="--viskores-log-level", const std::string &loggingEnv="VISKORES_LOG_LEVEL")
This shouldn't be called directly – prefer calling viskores::cont::Initialize, which takes care of lo...
viskores::cont::LogLevel::MemTransfer
@ MemTransfer
Transferring of data between a host and device.
viskores::cont::LogLevel::Perf
@ Perf
General timing data and algorithm flow information, such as filter execution, worklet dispatches,...
viskores::cont::LogLevel::UserVerboseLast
@ UserVerboseLast
The last in a range of logging levels reserved for code that uses Viskores.
viskores::cont::Error
The superclass of all exceptions thrown by any Viskores function or method.
Definition: Error.h:41
viskores::cont::SetLogLevelName
void SetLogLevelName(viskores::cont::LogLevel level, const std::string &name)
Register a custom name to identify a log level.
viskores::cont::GetSizeString
std::string GetSizeString(viskores::UInt64 bytes, int prec=2)
Returns "%1 (%2 bytes)" where %1 is the result from GetHumanReadableSize and %2 is the exact number o...
viskores::cont::TypeToString
std::string TypeToString(const std::type_info &t)
Use RTTI information to retrieve the name of the type T.
viskores::cont::SetLogThreadName
void SetLogThreadName(const std::string &name)
Specifies a humman-readable name to identify the current thread in the log output.
viskores_cont_export.h
viskores::cont::GetLogLevelName
std::string GetLogLevelName(viskores::cont::LogLevel level)
Get a human readable name for the log level.
viskores::cont::LogCondStream::Line
int Line
Definition: Logging.h:595