18 #include <QStringList> 30 #include <sys/syscall.h> 31 #elif defined(__FreeBSD__) 33 #include <sys/ucontext.h> 36 #elif defined(Q_OS_MAC) 37 #include <mach/mach.h> 72 int Line, LogLevel Level,
int Type, quint64 Mask)
74 return new LogItem(File, Function, Line, Level, Type, Mask);
88 LogItem(
const char *File,
const char *Function,
89 int Line, LogLevel Level,
int Type, quint64 Mask)
91 threadId((uint64_t)(QThread::currentThreadId())),
93 line(Line), type(Type),
97 function(Function), threadName(nullptr),
114 #if HAVE_GETTIMEOFDAY 116 gettimeofday(&tv,
nullptr);
120 QDateTime date = QDateTime::currentDateTime();
121 QTime time = date.time();
122 epoch = date.toTime_t();
123 usec = time.msec() * 1000;
126 localtime_r(&epoch, &tm);
138 tid = (int64_t)syscall(SYS_gettid);
139 #elif defined(__FreeBSD__) 141 int dummy = thr_self( &lwpid );
143 tid = (int64_t)lwpid;
144 #elif defined(Q_OS_MAC) 145 tid = (int64_t)mach_thread_self();
159 const char *
function;
173 while (!m_aborted || !
gLogQueue.isEmpty())
177 m_waitEmpty.wakeAll();
178 m_waitNotEmpty.wait(lock.mutex(), 100);
216 m_waitNotEmpty.wakeAll();
223 while (!m_aborted && !
gLogQueue.isEmpty() && t.elapsed() < TimeoutMS)
225 m_waitNotEmpty.wakeAll();
226 int left = TimeoutMS - t.elapsed();
263 QList<LoggerBase *>::iterator it;
278 #define TIMESTAMP_MAX 30 279 #define MAX_STRING_LENGTH (LOGLINE_MAX+120) 285 QString name { QStringLiteral(
"") };
286 bool additive {
false };
287 QString helpText { QStringLiteral(
"") };
294 QString name { QStringLiteral(
"") };
295 char shortname {
'?' };
314 void AddVerbose(uint64_t mask, QString name,
bool additive, QString helptext);
315 void AddLogLevel(
int value, QString name,
char shortname);
337 (
const struct tm *)&Item->
tm );
338 snprintf(usPart, 5,
".%03d", (
int)(Item->
usec));
339 strcat(timestamp, usPart);
348 shortname = (*it).shortname;
358 snprintf(fileline, 50,
"%s (%s:%d)", Item->
function, Item->
file, Item->
line);
363 timestamp, shortname, getpid(), tid, threadName, fileline,
368 return line.trimmed();
375 m_errorsOnly(ErrorsOnly),
381 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Logging to the console"));
389 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Moving '%1' to '%2'").arg(
m_fileName, old));
398 if (!
m_file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Truncate | QIODevice::Text | QIODevice::Unbuffered))
400 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to open %1 for logging").arg(
m_fileName));
404 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Logging to '%1'").arg(
m_fileName));
414 __LINE__, LOG_INFO,
kMessage, VB_GENERAL);
416 strcpy(item->
message,
m_file.isOpen() ?
"Closing file logger." :
"Closing console logger.");
431 QByteArray line =
GetLine(Item);
438 int error =
m_file.isOpen() ?
m_file.write(Line) : write(1, Line, Line.size() );
441 LOG(VB_GENERAL, LOG_ERR,
442 QStringLiteral(
"Closed Log output due to errors"));
461 TorcHTTPService(this, QStringLiteral(
"log"), QStringLiteral(
"log"),
WebLogger::staticMetaObject, QStringLiteral(
"event")),
473 if (event && event->type() == QEvent::Timer)
476 bool haschanged = changed;
487 return QObject::event(event);
498 if (!
log.open(QIODevice::ReadOnly))
500 QByteArray result =
log.readAll();
516 bool filter = (Item->
mask & VB_NETWORK) && (Item->
level >= LOG_DEBUG);
519 QByteArray line =
GetLine(Item);
536 static const char *unknown =
"QRunnable";
539 return (
char*)unknown;
549 threadName = (
char*)unknown;
588 void PrintLogLine(uint64_t Mask, LogLevel Level,
const char *File,
int Line,
589 const char *Function,
const char *Format, ... )
592 type |= (Mask & VB_FLUSH) ?
kFlush : 0;
599 va_start(arguments, Format);
627 mask.replace(QRegExp(
" "), QStringLiteral(
","));
628 mask.remove(QRegExp(
"^,"));
637 for (
int i = 0; i < gLogPropagationOpts.
quiet; i++)
643 return gLogPropagationOpts.
quiet;
647 const QString &Level,
bool Propagate)
661 if (gLogThread->isRunning())
665 LOG(VB_GENERAL, LOG_NOTICE, QStringLiteral(
"Setting level to LOG_%1")
668 gLogPropagationOpts.
propagate = Propagate;
669 gLogPropagationOpts.
quiet = quiet;
673 QFileInfo finfo(Logfile);
674 QString path = finfo.path();
675 gLogPropagationOpts.
path = path;
680 new FileLogger(QStringLiteral(
""), progress, quiet);
682 if (!Logfile.isEmpty())
700 gLogThread =
nullptr;
739 item->
threadName = strdup((
char *)QThread::currentThread()->objectName().toLocal8Bit().constData());
770 if ((*it).name == level.toLower() )
771 return (LogLevel)(*it).value;
786 LoglevelMap::iterator it =
gLoglevelMap.find((
int)level);
789 return QStringLiteral(
"unknown");
794 void AddVerbose(uint64_t mask, QString name,
bool additive, QString helptext)
802 name = name.toLower();
819 name = name.toLower();
833 #undef TORCLOGGINGDEFS_H_ 834 #define _IMPLEMENT_VERBOSE 843 m_verbose.replace(QRegExp(
" "), QStringLiteral(
","));
844 m_verbose.remove(QRegExp(
"^,"));
846 cerr <<
"Verbose debug levels.\n" 847 "Accepts any combination (separated by comma) of:\n\n";
849 for (VerboseMap::Iterator vit =
gVerboseMap.begin();
852 QString name = QStringLiteral(
" %1").arg(vit.value().name, -15,
' ');
853 if (vit.value().helpText.isEmpty())
855 cerr << name.toLocal8Bit().constData() <<
" - " <<
856 vit.value().helpText.toLocal8Bit().constData() << endl;
860 "The default for this program appears to be: '-v " <<
861 m_verbose.toLocal8Bit().constData() <<
"'\n\n" 862 "Most options are additive except for 'none' and 'all'.\n" 863 "These two are semi-exclusive and take precedence over any\n" 864 "other options. However, you may use something like\n" 865 "'-v none,jobqueue' to receive only JobQueue related messages\n" 866 "and override the default verbosity level.\n\n" 867 "Additive options may also be subtracted from 'all' by\n" 868 "prefixing them with 'no', so you may use '-v all,nodatabase'\n" 869 "to view all but database debug messages.\n\n" 870 "Some debug levels may not apply to this program.\n\n";
885 if (arg.startsWith(
'-'))
887 cerr <<
"Invalid or missing argument to -v/--verbose option\n";
891 QStringList verboseOpts = arg.split(QRegExp(
"\\W+"));
892 for (QStringList::Iterator it = verboseOpts.begin();
893 it != verboseOpts.end(); ++it )
895 option = (*it).toLower();
896 bool reverseOption =
false;
898 if (option != QStringLiteral(
"none") && option.left(2) == QStringLiteral(
"no"))
900 reverseOption =
true;
901 option = option.right(option.length() - 2);
904 if (option == QStringLiteral(
"help"))
909 else if (option == QStringLiteral(
"important"))
911 cerr <<
"The \"important\" log mask is no longer valid.\n";
913 else if (option == QStringLiteral(
"extra"))
915 cerr <<
"The \"extra\" log mask is no longer valid. Please try " 916 "--loglevel debug instead.\n";
918 else if (option == QStringLiteral(
"default"))
961 cerr <<
"Unknown argument for -v/--verbose: " <<
962 option.toLocal8Bit().constData() << endl;;
980 return QStringLiteral(
"%1 (%2)").arg(strerror(errnum)).arg(errnum);
LoggingThread * gLogThread
bool Flush(int TimeoutMS=200000)
LoggerBase(const QString &FileName)
#define TORC_EXIT_INVALID_CMDLINE
void SubscriberDeleted(QObject *Subscriber)
void PrintLogLine(uint64_t Mask, LogLevel Level, const char *File, int Line, const char *Function, const char *Format,...)
void AddLogLevel(int value, QString name, char shortname)
QHash< uint64_t, int64_t > gLogThreadtidHash
int ParseVerboseArgument(const QString &arg)
static void Delete(LogItem *Item)
bool Logmsg(LogItem *Item) override
QQueue< LogItem * > gLogQueue
bool PrintLine(QByteArray &Line) override
QList< LoggerBase * > gLoggerList
WebLogger(const QString &Filename)
int64_t GetThreadTid(LogItem *item)
QByteArray GetLine(LogItem *Item)
Serves log content to registered subscribers and HTTP clients.
QString gLogPropagationArgs
bool event(QEvent *event) override
void CalculateLogPropagation(void)
QString GetLogLevelName(LogLevel level)
char * GetThreadName(LogItem *item)
QString gVerboseDefaultStr
bool Logmsg(LogItem *Item) override
QMap< int, LoglevelDef > LoglevelMap
const uint64_t gVerboseDefaultInt
bool GetQuietLogPropagation(void)
QHash< uint64_t, char * > gLogThreadHash
void HandleSubscriberDeleted(QObject *Subscriber)
#define MAX_STRING_LENGTH
QReadWriteLock m_httpServiceLock
LogPropagateOpts gLogPropagationOpts
#define LOG(_MASK_, _LEVEL_, _STRING_)
void RegisterLoggingThread(void)
FileLogger(const QString &Filename, bool ErrorsOnly, int Quiet)
uint64_t gUserDefaultValueInt
QMap< QString, VerboseDef > VerboseMap
void StartLogging(const QString &Logfile, int progress, int quiet, const QString &Level, bool Propagate)
LogLevel GetLogLevel(const QString &level)
LogItem(const char *File, const char *Function, int Line, LogLevel Level, int Type, quint64 Mask)
static LogItem * Create(const char *File, const char *Function, int Line, LogLevel Level, int Type, quint64 Mask)
void HandleItem(LogItem *Item)
QString gUserDefaultValueStr
bool gHaveUserDefaultValues
char message[LOGLINE_MAX+1]
QString LogErrorToString(int errnum)
A Torc specific wrapper around QThread.
void AddVerbose(uint64_t mask, QString name, bool additive, QString helptext)
void DeregisterLoggingThread(void)