262 lines
10 KiB
C
262 lines
10 KiB
C
![]() |
// ----------------------------------------------------------------------------
|
||
|
// - Open3D: www.open3d.org -
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// Copyright (c) 2018-2023 www.open3d.org
|
||
|
// SPDX-License-Identifier: MIT
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <functional>
|
||
|
#include <memory>
|
||
|
#include <string>
|
||
|
|
||
|
// NVCC does not support deprecated attribute on Windows prior to v11.
|
||
|
#if defined(__CUDACC__) && defined(_MSC_VER) && __CUDACC_VER_MAJOR__ < 11
|
||
|
#ifndef FMT_DEPRECATED
|
||
|
#define FMT_DEPRECATED
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#include <fmt/core.h>
|
||
|
#include <fmt/printf.h>
|
||
|
#include <fmt/ranges.h>
|
||
|
|
||
|
#define DEFAULT_IO_BUFFER_SIZE 1024
|
||
|
|
||
|
#include "open3d/Macro.h"
|
||
|
|
||
|
// Mimic "macro in namespace" by concatenating `utility::` and a macro.
|
||
|
// Ref: https://stackoverflow.com/a/11791202
|
||
|
//
|
||
|
// We avoid using (format, ...) since in this case __VA_ARGS__ can be
|
||
|
// empty, and the behavior of pruning trailing comma with ##__VA_ARGS__ is not
|
||
|
// officially standard.
|
||
|
// Ref: https://stackoverflow.com/a/28074198
|
||
|
//
|
||
|
// __PRETTY_FUNCTION__ has to be converted, otherwise a bug regarding [noreturn]
|
||
|
// will be triggered.
|
||
|
// Ref: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94742
|
||
|
|
||
|
// LogError throws now a runtime_error with the given error message. This
|
||
|
// should be used if there is no point in continuing the given algorithm at
|
||
|
// some point and the error is not returned in another way (e.g., via a
|
||
|
// bool/int as return value).
|
||
|
//
|
||
|
// Usage : utility::LogError(format_string, arg0, arg1, ...);
|
||
|
// Example: utility::LogError("name: {}, age: {}", "dog", 5);
|
||
|
#define LogError(...) \
|
||
|
Logger::LogError_(__FILE__, __LINE__, \
|
||
|
static_cast<const char *>(OPEN3D_FUNCTION), __VA_ARGS__)
|
||
|
|
||
|
// LogWarning is used if an error occurs, but the error is also signaled
|
||
|
// via a return value (i.e., there is no need to throw an exception). This
|
||
|
// warning should further be used, if the algorithms encounters a state
|
||
|
// that does not break its continuation, but the output is likely not to be
|
||
|
// what the user expected.
|
||
|
//
|
||
|
// Usage : utility::LogWarning(format_string, arg0, arg1, ...);
|
||
|
// Example: utility::LogWarning("name: {}, age: {}", "dog", 5);
|
||
|
#define LogWarning(...) \
|
||
|
Logger::LogWarning_(__FILE__, __LINE__, \
|
||
|
static_cast<const char *>(OPEN3D_FUNCTION), \
|
||
|
__VA_ARGS__)
|
||
|
|
||
|
// LogInfo is used to inform the user with expected output, e.g, pressed a
|
||
|
// key in the visualizer prints helping information.
|
||
|
//
|
||
|
// Usage : utility::LogInfo(format_string, arg0, arg1, ...);
|
||
|
// Example: utility::LogInfo("name: {}, age: {}", "dog", 5);
|
||
|
#define LogInfo(...) \
|
||
|
Logger::LogInfo_(__FILE__, __LINE__, \
|
||
|
static_cast<const char *>(OPEN3D_FUNCTION), __VA_ARGS__)
|
||
|
|
||
|
// LogDebug is used to print debug/additional information on the state of
|
||
|
// the algorithm.
|
||
|
//
|
||
|
// Usage : utility::LogDebug(format_string, arg0, arg1, ...);
|
||
|
// Example: utility::LogDebug("name: {}, age: {}", "dog", 5);
|
||
|
#define LogDebug(...) \
|
||
|
Logger::LogDebug_(__FILE__, __LINE__, \
|
||
|
static_cast<const char *>(OPEN3D_FUNCTION), __VA_ARGS__)
|
||
|
|
||
|
namespace open3d {
|
||
|
namespace utility {
|
||
|
|
||
|
enum class VerbosityLevel {
|
||
|
/// LogError throws now a runtime_error with the given error message. This
|
||
|
/// should be used if there is no point in continuing the given algorithm at
|
||
|
/// some point and the error is not returned in another way (e.g., via a
|
||
|
/// bool/int as return value).
|
||
|
Error = 0,
|
||
|
/// LogWarning is used if an error occurs, but the error is also signaled
|
||
|
/// via a return value (i.e., there is no need to throw an exception). This
|
||
|
/// warning should further be used, if the algorithms encounters a state
|
||
|
/// that does not break its continuation, but the output is likely not to be
|
||
|
/// what the user expected.
|
||
|
Warning = 1,
|
||
|
/// LogInfo is used to inform the user with expected output, e.g, pressed a
|
||
|
/// key in the visualizer prints helping information.
|
||
|
Info = 2,
|
||
|
/// LogDebug is used to print debug/additional information on the state of
|
||
|
/// the algorithm.
|
||
|
Debug = 3,
|
||
|
};
|
||
|
|
||
|
/// Logger class should be used as a global singleton object (GetInstance()).
|
||
|
class Logger {
|
||
|
public:
|
||
|
Logger(Logger const &) = delete;
|
||
|
void operator=(Logger const &) = delete;
|
||
|
|
||
|
/// Get Logger global singleton instance.
|
||
|
static Logger &GetInstance();
|
||
|
|
||
|
/// Overwrite the default print function, this is useful when you want to
|
||
|
/// redirect prints rather than printing to stdout. For example, in Open3D's
|
||
|
/// python binding, the default print function is replaced with py::print().
|
||
|
///
|
||
|
/// \param print_fcn The function for printing. It should take a string
|
||
|
/// input and returns nothing.
|
||
|
void SetPrintFunction(std::function<void(const std::string &)> print_fcn);
|
||
|
|
||
|
/// Reset the print function to the default one (print to console).
|
||
|
void ResetPrintFunction();
|
||
|
|
||
|
/// Get the print function used by the Logger.
|
||
|
const std::function<void(const std::string &)> GetPrintFunction();
|
||
|
|
||
|
/// Set global verbosity level of Open3D.
|
||
|
///
|
||
|
/// \param verbosity_level Messages with equal or less than verbosity_level
|
||
|
/// verbosity will be printed.
|
||
|
void SetVerbosityLevel(VerbosityLevel verbosity_level);
|
||
|
|
||
|
/// Get global verbosity level of Open3D.
|
||
|
VerbosityLevel GetVerbosityLevel() const;
|
||
|
|
||
|
template <typename... Args>
|
||
|
static void LogError_ [[noreturn]] (const char *file,
|
||
|
int line,
|
||
|
const char *function,
|
||
|
const char *format,
|
||
|
Args &&... args) {
|
||
|
if (sizeof...(Args) > 0) {
|
||
|
Logger::GetInstance().VError(
|
||
|
file, line, function,
|
||
|
FormatArgs(format, fmt::make_format_args(args...)));
|
||
|
} else {
|
||
|
Logger::GetInstance().VError(file, line, function,
|
||
|
std::string(format));
|
||
|
}
|
||
|
}
|
||
|
template <typename... Args>
|
||
|
static void LogWarning_(const char *file,
|
||
|
int line,
|
||
|
const char *function,
|
||
|
const char *format,
|
||
|
Args &&... args) {
|
||
|
if (Logger::GetInstance().GetVerbosityLevel() >=
|
||
|
VerbosityLevel::Warning) {
|
||
|
if (sizeof...(Args) > 0) {
|
||
|
Logger::GetInstance().VWarning(
|
||
|
file, line, function,
|
||
|
FormatArgs(format, fmt::make_format_args(args...)));
|
||
|
} else {
|
||
|
Logger::GetInstance().VWarning(file, line, function,
|
||
|
std::string(format));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
template <typename... Args>
|
||
|
static void LogInfo_(const char *file,
|
||
|
int line,
|
||
|
const char *function,
|
||
|
const char *format,
|
||
|
Args &&... args) {
|
||
|
if (Logger::GetInstance().GetVerbosityLevel() >= VerbosityLevel::Info) {
|
||
|
if (sizeof...(Args) > 0) {
|
||
|
Logger::GetInstance().VInfo(
|
||
|
file, line, function,
|
||
|
FormatArgs(format, fmt::make_format_args(args...)));
|
||
|
} else {
|
||
|
Logger::GetInstance().VInfo(file, line, function,
|
||
|
std::string(format));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
template <typename... Args>
|
||
|
static void LogDebug_(const char *file,
|
||
|
int line,
|
||
|
const char *function,
|
||
|
const char *format,
|
||
|
Args &&... args) {
|
||
|
if (Logger::GetInstance().GetVerbosityLevel() >=
|
||
|
VerbosityLevel::Debug) {
|
||
|
if (sizeof...(Args) > 0) {
|
||
|
Logger::GetInstance().VDebug(
|
||
|
file, line, function,
|
||
|
FormatArgs(format, fmt::make_format_args(args...)));
|
||
|
} else {
|
||
|
Logger::GetInstance().VDebug(file, line, function,
|
||
|
std::string(format));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
Logger();
|
||
|
static std::string FormatArgs(const char *format, fmt::format_args args) {
|
||
|
std::string err_msg = fmt::vformat(format, args);
|
||
|
return err_msg;
|
||
|
}
|
||
|
void VError [[noreturn]] (const char *file,
|
||
|
int line,
|
||
|
const char *function,
|
||
|
const std::string &message) const;
|
||
|
void VWarning(const char *file,
|
||
|
int line,
|
||
|
const char *function,
|
||
|
const std::string &message) const;
|
||
|
void VInfo(const char *file,
|
||
|
int line,
|
||
|
const char *function,
|
||
|
const std::string &message) const;
|
||
|
void VDebug(const char *file,
|
||
|
int line,
|
||
|
const char *function,
|
||
|
const std::string &message) const;
|
||
|
|
||
|
private:
|
||
|
struct Impl;
|
||
|
std::unique_ptr<Impl> impl_;
|
||
|
};
|
||
|
|
||
|
/// Set global verbosity level of Open3D
|
||
|
///
|
||
|
/// \param level Messages with equal or less than verbosity_level verbosity will
|
||
|
/// be printed.
|
||
|
void SetVerbosityLevel(VerbosityLevel level);
|
||
|
|
||
|
/// Get global verbosity level of Open3D.
|
||
|
VerbosityLevel GetVerbosityLevel();
|
||
|
|
||
|
class VerbosityContextManager {
|
||
|
public:
|
||
|
VerbosityContextManager(VerbosityLevel level) : level_(level) {}
|
||
|
|
||
|
void Enter() {
|
||
|
level_backup_ = Logger::GetInstance().GetVerbosityLevel();
|
||
|
Logger::GetInstance().SetVerbosityLevel(level_);
|
||
|
}
|
||
|
|
||
|
void Exit() { Logger::GetInstance().SetVerbosityLevel(level_backup_); }
|
||
|
|
||
|
private:
|
||
|
VerbosityLevel level_;
|
||
|
VerbosityLevel level_backup_;
|
||
|
};
|
||
|
|
||
|
} // namespace utility
|
||
|
} // namespace open3d
|