34 #include <sys/syscall.h>
35#elif defined(__APPLE__) && defined(__MACH__)
40 #include <boost/python.hpp>
41namespace bp = boost::python;
45uint32_t currentThreadId() {
47 return syscall(SYS_gettid);
48#elif defined(__APPLE__) && defined(__MACH__)
50 pthread_threadid_np(NULL, &tid64);
51 return static_cast<uint32_t
>(tid64);
57std::string loggerComponent(
const std::string& name) {
58 const std::string prefix =
"pyrogue.";
62 if (name.rfind(prefix, 0) == 0) start = prefix.size();
63 end = name.find(
'.', start);
64 if (end == std::string::npos)
return name.substr(start);
65 return name.substr(start, end - start);
80std::mutex rogue::Logging::levelMtx_;
83std::vector<rogue::LogFilter*> rogue::Logging::filters_;
86std::vector<rogue::Logging*> rogue::Logging::loggers_;
89bool rogue::Logging::forwardPython_ =
false;
92bool rogue::Logging::emitStdout_ =
true;
101 if (name.rfind(
"pyrogue.", 0) == 0)
return name;
102 if (name ==
"pyrogue")
return name;
103 return "pyrogue." + name;
107 name_ = normalizeName(name);
111 loggers_.push_back(
this);
114 if (!quiet) warning(
"Starting logger with level = %" PRIu32, level_.load());
118 std::vector<rogue::Logging*>::iterator it;
121 for (it = loggers_.begin(); it < loggers_.end(); ++it) {
130void rogue::Logging::updateLevelLocked() {
131 std::vector<rogue::LogFilter*>::iterator it;
132 uint32_t level = gblLevel_;
134 for (it = filters_.begin(); it < filters_.end(); ++it) {
135 if (name_.find((*it)->name_) == 0) {
136 if ((*it)->level_ < level) level = (*it)->level_;
144 std::vector<rogue::Logging*>::iterator it;
148 for (it = loggers_.begin(); it < loggers_.end(); ++it) (*it)->updateLevelLocked();
153 std::vector<rogue::Logging*>::iterator it;
159 filters_.push_back(flt);
161 for (it = loggers_.begin(); it < loggers_.end(); ++it) (*it)->updateLevelLocked();
168 forwardPython_ = enable;
175 enable = forwardPython_;
182 emitStdout_ = enable;
189 enable = emitStdout_;
194void rogue::Logging::intLog(uint32_t level,
const char* fmt, va_list args) {
195 if (level < level_.load())
return;
199 vsnprintf(buffer,
sizeof(buffer), fmt, args);
200 gettimeofday(&tme, NULL);
202 printf(
"%" PRIi64
".%06" PRIi64
":%s: %s\n",
203 static_cast<int64_t
>(tme.tv_sec),
204 static_cast<int64_t
>(tme.tv_usec),
210 if (forwardPython()) {
213 bp::object logging = bp::import(
"logging");
214 bp::object logger = logging.attr(
"getLogger")(name_);
216 if (bp::extract<bool>(logger.attr(
"isEnabledFor")(level))) {
218 uint32_t tid = currentThreadId();
219 uint32_t pid =
static_cast<uint32_t
>(getpid());
220 double created =
static_cast<double>(tme.tv_sec) + (
static_cast<double>(tme.tv_usec) / 1000000.0);
221 std::string component = loggerComponent(name_);
223 record[
"name"] = name_;
224 record[
"msg"] = buffer;
225 record[
"args"] = bp::tuple();
226 record[
"levelno"] = level;
227 record[
"levelname"] = logging.attr(
"getLevelName")(level);
228 record[
"pathname"] =
"<rogue>";
229 record[
"filename"] =
"<rogue>";
230 record[
"module"] =
"rogue";
231 record[
"exc_info"] = bp::object();
232 record[
"exc_text"] = bp::object();
233 record[
"stack_info"] = bp::object();
234 record[
"lineno"] = 0;
235 record[
"funcName"] =
"<rogue>";
236 record[
"created"] = created;
237 record[
"msecs"] =
static_cast<double>(tme.tv_usec) / 1000.0;
238 record[
"relativeCreated"] = 0.0;
239 record[
"thread"] = tid;
240 record[
"threadName"] =
"rogue";
241 record[
"process"] = pid;
242 record[
"processName"] =
"rogue";
243 record[
"rogue_cpp"] =
true;
244 record[
"rogue_tid"] = tid;
245 record[
"rogue_pid"] = pid;
246 record[
"rogue_logger"] = name_;
247 record[
"rogue_timestamp"] = created;
248 record[
"rogue_component"] = component;
250 logger.attr(
"handle")(logging.attr(
"makeLogRecord")(record));
252 }
catch (
const bp::error_already_set&) {
262 intLog(level, fmt, arg);
302 uint32_t tid = currentThreadId();
303 this->log(Thread,
"PID=%" PRIu32
", TID=%" PRIu32, getpid(), tid);
312 bp::class_<rogue::Logging, rogue::LoggingPtr, boost::noncopyable>(
"Logging", bp::no_init)
314 .staticmethod(
"setLevel")
316 .staticmethod(
"setFilter")
318 .staticmethod(
"setForwardPython")
320 .staticmethod(
"forwardPython")
322 .staticmethod(
"setEmitStdout")
324 .staticmethod(
"emitStdout")
326 .staticmethod(
"normalizeName")
Per-logger level override filter entry.
~Logging()
Destroys the logger instance.
void info(const char *fmt,...)
Emits a formatted message at Info level.
static const uint32_t Thread
Thread-trace severity level constant.
static void setEmitStdout(bool enable)
Enables or disables direct stdout emission of Rogue C++ logs.
static bool forwardPython()
Returns whether Rogue C++ logs are currently forwarded to Python logging.
void logThreadId()
Emits the current thread id through this logger.
static void setup_python()
Registers Python bindings for Logging.
Logging(const std::string &name, bool quiet=false)
Constructs a logger.
static std::shared_ptr< rogue::Logging > create(const std::string &name, bool quiet=false)
Creates a logger instance.
static void setForwardPython(bool enable)
Enables or disables forwarding Rogue C++ logs into Python logging.
static bool emitStdout()
Returns whether Rogue C++ logs are currently emitted to stdout.
static void setFilter(const std::string &filter, uint32_t level)
Sets name-based filter level override.
void warning(const char *fmt,...)
Emits a formatted message at Warning level.
const std::string & name() const
Returns the fully-qualified emitted logger name.
static const uint32_t Debug
Debug severity level constant.
void log(uint32_t level, const char *fmt,...)
Emits a formatted log message at a specified level.
static const uint32_t Error
Error severity level constant.
static const uint32_t Info
Informational severity level constant.
static std::string normalizeName(const std::string &name)
Normalizes logger names to the emitted Rogue namespace.
static const uint32_t Warning
Warning severity level constant.
static void setLevel(uint32_t level)
Sets the global default logging level.
void critical(const char *fmt,...)
Emits a formatted message at Critical level.
void debug(const char *fmt,...)
Emits a formatted message at Debug level.
static const uint32_t Critical
Critical severity level constant.
void error(const char *fmt,...)
Emits a formatted message at Error level.
RAII helper that acquires the Python GIL for a scope.
std::shared_ptr< rogue::Logging > LoggingPtr
Shared pointer alias for Logging.