MythTV  master
loggingserver.cpp
Go to the documentation of this file.
1 #include <QAtomicInt>
2 #include <QMutex>
3 #include <QMutexLocker>
4 #include <QWaitCondition>
5 #include <QList>
6 #include <QQueue>
7 #include <QHash>
8 #include <QCoreApplication>
9 #include <QFileInfo>
10 #include <QStringList>
11 #include <QMap>
12 #include <QRegExp>
13 #include <QSocketNotifier>
14 #include <iostream>
15 
16 using namespace std;
17 
18 #include "mythlogging.h"
19 #include "logging.h"
20 #include "loggingserver.h"
21 #include "mythdb.h"
22 #include "mythcorecontext.h"
23 #include "mythsignalingtimer.h"
24 #include "dbutil.h"
25 #include "exitcodes.h"
26 #include "compat.h"
27 
28 #include <cstdlib>
29 #ifndef _WIN32
30 #include <mythsyslog.h>
31 #if CONFIG_SYSTEMD_JOURNAL
32 #define SD_JOURNAL_SUPPRESS_LOCATION 1
33 #include <systemd/sd-journal.h>
34 #endif
35 #endif
36 #include <cstdarg>
37 #include <cstring>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <fcntl.h>
41 #include <cstdio>
42 #include <unistd.h>
43 #if HAVE_GETTIMEOFDAY
44 #include <sys/time.h>
45 #endif
46 #include <csignal>
47 
48 // Various ways to get to thread's tid
49 #if defined(linux)
50 #include <sys/syscall.h>
51 #elif defined(__FreeBSD__)
52 extern "C" {
53 #include <sys/ucontext.h>
54 #include <sys/thr.h>
55 }
56 #elif CONFIG_DARWIN
57 #include <mach/mach.h>
58 #endif
59 
60 static QMutex loggerMapMutex;
61 static QMap<QString, LoggerBase *> loggerMap;
62 
64 
65 using LoggerList = QList<LoggerBase *>;
66 
69  qlonglong m_itemEpoch;
70 };
71 using ClientMap = QMap<QString, LoggerListItem *>;
72 
73 using ClientList = QList<QString>;
74 using RevClientMap = QMap<LoggerBase *, ClientList *>;
75 
76 static QMutex logClientMapMutex;
78 static QAtomicInt logClientCount;
79 
80 static QMutex logRevClientMapMutex;
82 
83 static QMutex logMsgListMutex;
85 static QWaitCondition logMsgListNotEmpty;
86 
90 LoggerBase::LoggerBase(const char *string)
91 {
92  QMutexLocker locker(&loggerMapMutex);
93  if (string)
94  {
95  m_handle = strdup(string);
96  loggerMap.insert(QString(m_handle), this);
97  }
98  else
99  {
100  m_handle = nullptr;
101  loggerMap.insert(QString(""), this);
102  }
103 }
104 
105 
109 {
110  QMutexLocker locker(&loggerMapMutex);
111  loggerMap.remove(QString(m_handle));
112 
113  if (m_handle)
114  free(m_handle);
115 }
116 
117 
122 {
123  m_fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0664);
124  m_opened = (m_fd != -1);
125  LOG(VB_GENERAL, LOG_INFO, QString("Added logging to %1")
126  .arg(filename));
127 }
128 
129 
132 {
133  if( m_opened )
134  {
135  LOG(VB_GENERAL, LOG_INFO, QString("Removed logging to %1")
136  .arg(m_handle));
137  close(m_fd);
138  m_fd = -1;
139  m_opened = false;
140  }
141 }
142 
143 FileLogger *FileLogger::create(const QString& filename, QMutex *mutex)
144 {
145  QByteArray ba = filename.toLocal8Bit();
146  const char *file = ba.constData();
147  FileLogger *logger =
148  dynamic_cast<FileLogger *>(loggerMap.value(filename, nullptr));
149 
150  if (logger)
151  return logger;
152 
153  // Need to add a new FileLogger
154  mutex->unlock();
155  // inserts into loggerMap
156  logger = new FileLogger(file);
157  mutex->lock();
158 
159  auto *clients = new ClientList;
160  logRevClientMap.insert(logger, clients);
161  return logger;
162 }
163 
167 {
168  close(m_fd);
169 
170  m_fd = open(m_handle, O_WRONLY|O_CREAT|O_APPEND, 0664);
171  m_opened = (m_fd != -1);
172  LOG(VB_GENERAL, LOG_INFO, QString("Rolled logging on %1") .arg(m_handle));
173 }
174 
178 {
179  if (!m_opened)
180  return false;
181 
182  QString timestamp = item->getTimestampUs();
183  QChar shortname = item->getLevelChar();
184 
185  std::string line;
186  if( item->tid() )
187  {
188  line = qPrintable(QString("%1 %2 [%3/%4] %5 %6:%7 (%8) - %9\n")
189  .arg(timestamp, shortname,
190  QString::number(item->pid()),
191  QString::number(item->tid()),
192  item->threadName(), item->file(),
193  QString::number(item->line()),
194  item->function(),
195  item->message()));
196  }
197  else
198  {
199  line = qPrintable(QString("%1 %2 [%3] %5 %6:%7 (%8) - %9\n")
200  .arg(timestamp, shortname,
201  QString::number(item->pid()),
202  item->threadName(), item->file(),
203  QString::number(item->line()),
204  item->function(),
205  item->message()));
206  }
207 
208  int result = write(m_fd, line.data(), line.size());
209 
210  if( result == -1 )
211  {
212  LOG(VB_GENERAL, LOG_ERR,
213  QString("Closed Log output on fd %1 due to errors").arg(m_fd));
214  m_opened = false;
215  close( m_fd );
216  return false;
217  }
218  return true;
219 }
220 
221 #ifndef _WIN32
222 SyslogLogger::SyslogLogger(bool open) :
225  LoggerBase(nullptr)
226 {
227  if (open)
228  {
229  openlog(nullptr, LOG_NDELAY, 0 );
230  m_opened = true;
231  }
232 
233  LOG(VB_GENERAL, LOG_INFO, "Added syslogging");
234 }
235 
238 {
239  LOG(VB_GENERAL, LOG_INFO, "Removing syslogging");
240  if (m_opened)
241  closelog();
242 }
243 
244 SyslogLogger *SyslogLogger::create(QMutex *mutex, bool open)
245 {
247  dynamic_cast<SyslogLogger *>(loggerMap.value("", nullptr));
248 
249  if (logger)
250  return logger;
251 
252  // Need to add a new FileLogger
253  mutex->unlock();
254  // inserts into loggerMap
255  logger = new SyslogLogger(open);
256  mutex->lock();
257 
258  auto *clients = new ClientList;
259  logRevClientMap.insert(logger, clients);
260  return logger;
261 }
262 
263 
267 {
268  if (!m_opened || item->facility() <= 0)
269  return false;
270 
271  char shortname = item->getLevelChar();
272  syslog(item->level() | item->facility(), "%s[%d]: %c %s %s:%d (%s) %s",
273  item->rawAppName(), item->pid(), shortname, item->rawThreadName(),
274  item->rawFile(), item->line(), item->rawFunction(),
275  qPrintable(item->message()));
276 
277  return true;
278 }
279 
280 #if CONFIG_SYSTEMD_JOURNAL
281 JournalLogger::JournalLogger() :
283  LoggerBase(nullptr)
284 {
285  LOG(VB_GENERAL, LOG_INFO, "Added journal logging");
286 }
287 
289 JournalLogger::~JournalLogger()
290 {
291  LOG(VB_GENERAL, LOG_INFO, "Removing journal logging");
292 }
293 
294 JournalLogger *JournalLogger::create(QMutex *mutex)
295 {
296  JournalLogger *logger =
297  dynamic_cast<JournalLogger *>(loggerMap.value("", nullptr));
298 
299  if (logger)
300  return logger;
301 
302  // Need to add a new FileLogger
303  mutex->unlock();
304  // inserts into loggerMap
305  logger = new JournalLogger();
306  mutex->lock();
307 
308  auto *clients = new ClientList;
309  logRevClientMap.insert(logger, clients);
310  return logger;
311 }
312 
313 
316 bool JournalLogger::logmsg(LoggingItem *item)
317 {
318  sd_journal_send(
319  "MESSAGE=%s", qUtf8Printable(item->message()),
320  "PRIORITY=%d", item->level(),
321  "CODE_FILE=%s", item->rawFile(),
322  "CODE_LINE=%d", item->line(),
323  "CODE_FUNC=%s", item->rawFunction(),
324  "SYSLOG_IDENTIFIER=%s", item->rawAppName(),
325  "SYSLOG_PID=%d", item->pid(),
326  "MYTH_THREAD=%s", item->rawThreadName(),
327  NULL
328  );
329  return true;
330 }
331 #endif
332 #endif
333 
334 const int DatabaseLogger::kMinDisabledTime = 1000;
335 
338 DatabaseLogger::DatabaseLogger(const char *table) :
339  LoggerBase(table)
340 {
341  m_query = QString(
342  "INSERT INTO %1 "
343  " (host, application, pid, tid, thread, filename, "
344  " line, function, msgtime, level, message) "
345  "VALUES (:HOST, :APP, :PID, :TID, :THREAD, :FILENAME, "
346  " :LINE, :FUNCTION, :MSGTIME, :LEVEL, :MESSAGE)")
347  .arg(m_handle);
348 
349  LOG(VB_GENERAL, LOG_INFO, QString("Added database logging to table %1")
350  .arg(m_handle));
351 
352  m_thread = new DBLoggerThread(this);
353  m_thread->start();
354 }
355 
358 {
359  LOG(VB_GENERAL, LOG_INFO, "Removing database logging");
360 
362 }
363 
364 DatabaseLogger *DatabaseLogger::create(const QString& table, QMutex *mutex)
365 {
366  QByteArray ba = table.toLocal8Bit();
367  const char *tble = ba.constData();
369  dynamic_cast<DatabaseLogger *>(loggerMap.value(table, nullptr));
370 
371  if (logger)
372  return logger;
373 
374  // Need to add a new FileLogger
375  mutex->unlock();
376  // inserts into loggerMap
377  logger = new DatabaseLogger(tble);
378  mutex->lock();
379 
380  auto *clients = new ClientList;
381  logRevClientMap.insert(logger, clients);
382  return logger;
383 }
384 
387 {
388  if( m_thread )
389  {
390  m_thread->stop();
391  m_thread->wait();
392  delete m_thread;
393  m_thread = nullptr;
394  }
395 }
396 
400 {
401  if (!m_thread)
402  return false;
403 
404  if (!m_thread->isRunning())
405  {
406  m_disabledTime.start();
407  }
408 
409  if (!m_disabledTime.isValid() && m_thread->queueFull())
410  {
411  m_disabledTime.start();
412  LOG(VB_GENERAL, LOG_CRIT,
413  "Disabling DB Logging: too many messages queued");
414  return false;
415  }
416 
417  if (m_disabledTime.isValid() && m_disabledTime.hasExpired(kMinDisabledTime))
418  {
419  if (isDatabaseReady() && !m_thread->queueFull())
420  {
421  m_disabledTime.invalidate();
422  LOG(VB_GENERAL, LOG_CRIT, "Reenabling DB Logging");
423  }
424  }
425 
426  if (m_disabledTime.isValid())
427  return false;
428 
429  m_thread->enqueue(item);
430  return true;
431 }
432 
433 
438 {
439  QString timestamp = item->getTimestamp();
440 
441  query.bindValue(":TID", item->tid());
442  query.bindValue(":THREAD", item->threadName());
443  query.bindValue(":FILENAME", item->file());
444  query.bindValue(":LINE", item->line());
445  query.bindValue(":FUNCTION", item->function());
446  query.bindValue(":MSGTIME", timestamp);
447  query.bindValue(":LEVEL", item->level());
448  query.bindValue(":MESSAGE", item->message());
449  query.bindValue(":APP", item->appName());
450  query.bindValue(":PID", item->pid());
451 
452  if (!query.exec())
453  {
454  // Suppress Driver not loaded errors that occur at startup.
455  // and suppress additional errors for one second after the
456  // previous error (to avoid spamming the log).
457  QSqlError err = query.lastError();
458  if ((err.type() != 1
459  || !err.nativeErrorCode().isEmpty()
460  ) &&
461  (!m_errorLoggingTime.isValid() ||
462  (m_errorLoggingTime.hasExpired(1000))))
463  {
464  MythDB::DBError("DBLogging", query);
465  m_errorLoggingTime.start();
466  }
467  return false;
468  }
469 
470  return true;
471 }
472 
476 {
479 }
480 
484 {
485  bool ready = false;
486  MythDB *db = GetMythDB();
487 
488  if ((db) && db->HaveValidDatabase())
489  {
490  if ( !m_loggingTableExists )
492 
493  if ( m_loggingTableExists )
494  ready = true;
495  }
496 
497  return ready;
498 }
499 
503 bool DatabaseLogger::tableExists(const QString &table)
504 {
505  bool result = false;
507  if (query.isConnected())
508  {
509  QString sql = "SELECT COLUMN_NAME "
510  " FROM INFORMATION_SCHEMA.COLUMNS "
511  " WHERE TABLE_SCHEMA = DATABASE() "
512  " AND TABLE_NAME = :TABLENAME "
513  " AND COLUMN_NAME = :COLUMNNAME;";
514  if (query.prepare(sql))
515  {
516  query.bindValue(":TABLENAME", table);
517  query.bindValue(":COLUMNNAME", "function");
518  if (query.exec() && query.next())
519  result = true;
520  }
521  }
522  return result;
523 }
524 
525 
529  MThread("DBLogger"), m_logger(logger),
530  m_queue(new QQueue<LoggingItem *>),
531  m_wait(new QWaitCondition())
532 {
533 }
534 
538 {
539  stop();
540  wait();
541 
542  QMutexLocker qLock(&m_queueMutex);
543  while (!m_queue->empty())
544  m_queue->dequeue()->DecrRef();
545  delete m_queue;
546  delete m_wait;
547  m_queue = nullptr;
548  m_wait = nullptr;
549 }
550 
553 {
554  RunProlog();
555 
556  // Wait a bit before we start logging to the DB.. If we wait too long,
557  // then short-running tasks (like mythpreviewgen) will not log to the db
558  // at all, and that's undesirable.
559  while (true)
560  {
562  break;
563 
564  QMutexLocker locker(&m_queueMutex);
565  m_wait->wait(locker.mutex(), 100);
566  }
567 
568  if (!m_aborted)
569  {
570  // We want the query to be out of scope before the RunEpilog() so
571  // shutdown occurs correctly as otherwise the connection appears still
572  // in use, and we get a qWarning on shutdown.
573  auto *query = new MSqlQuery(MSqlQuery::InitCon());
575 
576  QMutexLocker qLock(&m_queueMutex);
577  while (!m_aborted || !m_queue->isEmpty())
578  {
579  if (m_queue->isEmpty())
580  {
581  m_wait->wait(qLock.mutex(), 100);
582  continue;
583  }
584 
585  LoggingItem *item = m_queue->dequeue();
586  if (!item)
587  continue;
588 
589  if (!item->message().isEmpty())
590  {
591  qLock.unlock();
592  bool logged = m_logger->logqmsg(*query, item);
593  qLock.relock();
594 
595  if (!logged)
596  {
597  m_queue->prepend(item);
598  m_wait->wait(qLock.mutex(), 100);
599  delete query;
602  continue;
603  }
604  }
605 
606  item->DecrRef();
607  }
608 
609  delete query;
610  }
611 
612  RunEpilog();
613 }
614 
617 {
618  QMutexLocker qLock(&m_queueMutex);
619  m_aborted = true;
620  m_wait->wakeAll();
621 }
622 
624 {
625  QMutexLocker qLock(&m_queueMutex);
626  if (!m_aborted)
627  {
628  if (item)
629  {
630  item->IncrRef();
631  }
632  m_queue->enqueue(item);
633  }
634  return true;
635 }
636 
637 
638 #ifndef _WIN32
639 
642 void logSigHup(void)
643 {
644  if (!logForwardThread)
645  return;
646 
647  // This will be running in the thread that's used by SignalHandler
648  // Emit the signal which is connected to a slot that runs in the actual
649  // handling thread.
651 }
652 #endif
653 
654 
657  MThread("LogForward")
658 {
659  moveToThread(qthread());
660 }
661 
664 {
665  stop();
666  wait();
667 }
668 
673 {
674  RunProlog();
675 
676  connect(this, SIGNAL(incomingSigHup(void)), this, SLOT(handleSigHup(void)),
677  Qt::QueuedConnection);
678 
679  qRegisterMetaType<QList<QByteArray> >("QList<QByteArray>");
680 
681  while (!m_aborted)
682  {
683  qApp->processEvents(QEventLoop::AllEvents, 10);
684  qApp->sendPostedEvents(nullptr, QEvent::DeferredDelete);
685 
686  {
687  QMutexLocker lock(&logMsgListMutex);
688  if (logMsgList.isEmpty() &&
689  !logMsgListNotEmpty.wait(lock.mutex(), 90))
690  {
691  continue;
692  }
693 
694  int processed = 0;
695  while (!logMsgList.isEmpty())
696  {
697  processed++;
698  LogMessage *msg = logMsgList.takeFirst();
699  lock.unlock();
700  forwardMessage(msg);
701  delete msg;
702 
703  // Force a processEvents every 128 messages so a busy queue
704  // doesn't preclude timer notifications, etc.
705  if ((processed & 127) == 0)
706  {
707  qApp->processEvents(QEventLoop::AllEvents, 10);
708  qApp->sendPostedEvents(nullptr, QEvent::DeferredDelete);
709  }
710 
711  lock.relock();
712  }
713  }
714  }
715 
716  LoggerList loggers;
717 
718  {
719  QMutexLocker lock(&loggerMapMutex);
720  loggers = loggerMap.values();
721  }
722 
723  while (!loggers.isEmpty())
724  {
725  LoggerBase *logger = loggers.takeFirst();
726  delete logger;
727  }
728 
729  RunEpilog();
730 }
731 
732 
735 {
736 #ifndef _WIN32
737  LOG(VB_GENERAL, LOG_INFO, "SIGHUP received, rolling log files.");
738 
739  /* SIGHUP was sent. Close and reopen debug logfiles */
740  QMutexLocker locker(&loggerMapMutex);
741  QMap<QString, LoggerBase *>::iterator it;
742  for (it = loggerMap.begin(); it != loggerMap.end(); ++it)
743  {
744  it.value()->reopen();
745  }
746 #endif
747 }
748 
750 {
751 #ifdef DUMP_PACKET
752  QList<QByteArray>::const_iterator it = msg->begin();
753  int i = 0;
754  for (; it != msg->end(); ++it, i++)
755  {
756  QByteArray buf = *it;
757  cout << i << ":\t" << buf.size() << endl << "\t"
758  << buf.toHex().constData() << endl << "\t"
759  << buf.constData() << endl;
760  }
761 #endif
762 
763  // First section is the client id
764  QByteArray clientBa = msg->first();
765  QString clientId = QString(clientBa.toHex());
766 
767  QByteArray json = msg->at(1);
768 
769  if (json.size() == 0)
770  {
771  // cout << "invalid msg, no json data " << qPrintable(clientId) << endl;
772  return;
773  }
774 
775  QMutexLocker lock(&logClientMapMutex);
776  LoggerListItem *logItem = logClientMap.value(clientId, nullptr);
777 
778  // cout << "msg " << clientId.toLocal8Bit().constData() << endl;
779  if (logItem)
780  {
781  loggingGetTimeStamp(&logItem->m_itemEpoch, nullptr);
782  }
783  else
784  {
785  LoggingItem *item = LoggingItem::create(json);
786 
787  logClientCount.ref();
788  LOG(VB_FILE, LOG_DEBUG, QString("New Logging Client: ID: %1 (#%2)")
789  .arg(clientId).arg(logClientCount.fetchAndAddOrdered(0)));
790 
791  QMutexLocker lock2(&loggerMapMutex);
792  QMutexLocker lock3(&logRevClientMapMutex);
793 
794  // Need to find or create the loggers
795  auto *loggers = new LoggerList;
796 
797  // FileLogger from logFile
798  QString logfile = item->logFile();
799  if (!logfile.isEmpty())
800  {
801  LoggerBase *logger = FileLogger::create(logfile, lock2.mutex());
802 
803  ClientList *clients = logRevClientMap.value(logger);
804 
805  if (clients)
806  clients->insert(0, clientId);
807 
808  if (logger && loggers)
809  loggers->insert(0, logger);
810  }
811 
812 #ifndef _WIN32
813  // SyslogLogger from facility
814  int facility = item->facility();
815  if (facility > 0)
816  {
817  LoggerBase *logger = SyslogLogger::create(lock2.mutex());
818 
819  ClientList *clients = logRevClientMap.value(logger);
820 
821  if (clients)
822  clients->insert(0, clientId);
823 
824  if (logger && loggers)
825  loggers->insert(0, logger);
826  }
827 
828 #if CONFIG_SYSTEMD_JOURNAL
829  // Journal Logger
830  if (facility == SYSTEMD_JOURNAL_FACILITY)
831  {
832  LoggerBase *logger = JournalLogger::create(lock2.mutex());
833 
834  ClientList *clients = logRevClientMap.value(logger);
835 
836  if (clients)
837  clients->insert(0, clientId);
838 
839  if (logger && loggers)
840  loggers->insert(0, logger);
841  }
842 #endif
843 #endif
844 
845  // DatabaseLogger from table
846  QString table = item->table();
847  if (!table.isEmpty())
848  {
849  LoggerBase *logger = DatabaseLogger::create(table, lock2.mutex());
850 
851  ClientList *clients = logRevClientMap.value(logger);
852 
853  if (clients)
854  clients->insert(0, clientId);
855 
856  if (logger && loggers)
857  loggers->insert(0, logger);
858  }
859 
860  logItem = new LoggerListItem;
861  loggingGetTimeStamp(&logItem->m_itemEpoch, nullptr);
862  logItem->m_itemList = loggers;
863  logClientMap.insert(clientId, logItem);
864 
865  item->DecrRef();
866  }
867 
868  if (logItem && logItem->m_itemList && !logItem->m_itemList->isEmpty())
869  {
870  LoggingItem *item = LoggingItem::create(json);
871  if (!item)
872  return;
873  for (auto *it : qAsConst(*logItem->m_itemList))
874  it->logmsg(item);
875  item->DecrRef();
876  }
877 }
878 
881 {
882  m_aborted = true;
883 }
884 
885 bool logForwardStart(void)
886 {
889 
890  usleep(10000);
892 }
893 
894 void logForwardStop(void)
895 {
896  if (!logForwardThread)
897  return;
898 
900  delete logForwardThread;
901  logForwardThread = nullptr;
902 
903  QMutexLocker locker(&loggerMapMutex);
904  for (auto it = loggerMap.begin(); it != loggerMap.end(); ++it)
905  {
906  it.value()->stopDatabaseAccess();
907  }
908 }
909 
910 void logForwardMessage(const QList<QByteArray> &msg)
911 {
912  auto *message = new LogMessage(msg);
913  QMutexLocker lock(&logMsgListMutex);
914 
915  bool wasEmpty = logMsgList.isEmpty();
916  logMsgList.append(message);
917 
918  if (wasEmpty)
919  logMsgListNotEmpty.wakeAll();
920 }
921 
922 /*
923  * vim:ts=4:sw=4:ai:et:si:sts=4
924  */
logClientCount
static QAtomicInt logClientCount
Definition: loggingserver.cpp:78
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
DatabaseLogger::logqmsg
bool logqmsg(MSqlQuery &query, LoggingItem *item)
Actually insert a log message from the queue into the database.
Definition: loggingserver.cpp:437
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
DatabaseLogger::m_errorLoggingTime
QElapsedTimer m_errorLoggingTime
Elapsed time since DB error logging was last done.
Definition: loggingserver.h:122
FileLogger::m_opened
bool m_opened
true when the logfile is opened
Definition: loggingserver.h:59
logForwardStop
void logForwardStop(void)
Definition: loggingserver.cpp:894
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:292
LoggingItem::threadName
QString threadName
Definition: logging.h:76
dbutil.h
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
loggerMap
static QMap< QString, LoggerBase * > loggerMap
Definition: loggingserver.cpp:61
logClientMapMutex
static QMutex logClientMapMutex
Definition: loggingserver.cpp:76
DBLoggerThread::~DBLoggerThread
~DBLoggerThread() override
DBLoggerThread deconstructor.
Definition: loggingserver.cpp:537
mythdb.h
LogMessageList
QList< LogMessage * > LogMessageList
Definition: loggingserver.h:128
LoggerBase
Base class for the various logging mechanisms.
Definition: loggingserver.h:28
SyslogLogger::logmsg
bool logmsg(LoggingItem *item) override
Process a log message for the logger instance.
DatabaseLogger::create
static DatabaseLogger * create(const QString &table, QMutex *mutex)
Definition: loggingserver.cpp:364
LoggingItem::logFile
QString logFile
Definition: logging.h:79
DatabaseLogger::m_thread
DBLoggerThread * m_thread
The database queue handling thread.
Definition: loggingserver.h:117
FileLogger::logmsg
bool logmsg(LoggingItem *item) override
Process a log message, writing to the logfile.
Definition: loggingserver.cpp:177
logForwardThread
LogForwardThread * logForwardThread
Definition: loggingserver.cpp:63
mythburn.write
def write(text, progress=True)
Definition: mythburn.py:308
DatabaseLogger::tableExists
static bool tableExists(const QString &table)
Checks whether table exists and is ready for writing.
Definition: loggingserver.cpp:503
arg
arg(title).arg(filename).arg(doDelete))
DatabaseLogger::logmsg
bool logmsg(LoggingItem *item) override
Process a log message, queuing it for logging to the database.
Definition: loggingserver.cpp:399
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
logForwardMessage
void logForwardMessage(const QList< QByteArray > &msg)
Definition: loggingserver.cpp:910
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:202
logForwardStart
bool logForwardStart(void)
Definition: loggingserver.cpp:885
LoggingItem::table
QString table
Definition: logging.h:78
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
build_compdb.file
file
Definition: build_compdb.py:55
LoggingItem::tid
qlonglong tid
Definition: logging.h:66
LoggerBase::~LoggerBase
~LoggerBase() override
LoggerBase Deconstructor.
Definition: loggingserver.cpp:108
NULL
#define NULL
Definition: H2645Parser.h:67
DBLoggerThread::DBLoggerThread
DBLoggerThread(DatabaseLogger *logger)
DBLoggerThread constructor.
Definition: loggingserver.cpp:528
LogForwardThread::m_aborted
bool m_aborted
Flag to abort the thread.
Definition: loggingserver.h:143
DatabaseLogger::stopDatabaseAccess
void stopDatabaseAccess(void) override
Stop logging to the database and wait for the thread to stop.
Definition: loggingserver.cpp:386
LoggingItem::level
int level
Definition: logging.h:71
close
#define close
Definition: compat.h:16
SyslogLogger::m_opened
bool m_opened
true when syslog channel open.
Definition: loggingserver.h:77
LoggingItem::rawFunction
const char * rawFunction() const
Definition: logging.h:133
LoggingItem
The logging items that are generated by LOG() and are sent to the console.
Definition: logging.h:62
DatabaseLogger::isDatabaseReady
bool isDatabaseReady(void)
Check if the database is ready for use.
Definition: loggingserver.cpp:483
LoggingItem::getLevelChar
char getLevelChar(void)
Get the message log level as a single character.
Definition: logging.cpp:252
logger
static void logger(cdio_log_level_t level, const char message[])
Definition: cddecoder.cpp:37
DatabaseLogger::m_loggingTableExists
bool m_loggingTableExists
The desired logging table exists.
Definition: loggingserver.h:120
mythlogging.h
DatabaseLogger::m_query
QString m_query
The database query to insert log messages.
Definition: loggingserver.h:118
LogForwardThread
The logging thread that forwards received messages to the consuming loggers via ZeroMQ.
Definition: loggingserver.h:133
DatabaseLogger::kMinDisabledTime
static const int kMinDisabledTime
Minimum time to disable DB logging (in ms)
Definition: loggingserver.h:123
LoggingItem::pid
int pid
Definition: logging.h:65
LogForwardThread::~LogForwardThread
~LogForwardThread() override
LogForwardThread destructor.
Definition: loggingserver.cpp:663
logfile
QString logfile
Definition: backendcontext.cpp:14
DBLoggerThread::stop
void stop(void)
Tell the thread to stop by setting the m_aborted flag.
Definition: loggingserver.cpp:616
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
compat.h
logRevClientMap
static RevClientMap logRevClientMap
Definition: loggingserver.cpp:81
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
LogForwardThread::handleSigHup
static void handleSigHup(void)
SIGHUP handler - reopen all open logfiles for logrollers.
Definition: loggingserver.cpp:734
logMsgList
static LogMessageList logMsgList
Definition: loggingserver.cpp:84
LoggingItem::rawAppName
const char * rawAppName() const
Definition: logging.h:135
LogForwardThread::run
void run(void) override
Run the log forwarding thread.
Definition: loggingserver.cpp:672
MThread::qthread
QThread * qthread(void)
Returns the thread, this will always return the same pointer no matter how often you restart the thre...
Definition: mthread.cpp:242
DatabaseLogger::DatabaseLogger
DatabaseLogger(const char *table)
DatabaseLogger constructor.
Definition: loggingserver.cpp:338
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:634
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:215
DatabaseLogger::DBLoggerThread
friend class DBLoggerThread
Definition: loggingserver.h:102
LoggerBase::LoggerBase
LoggerBase(const char *string)
LoggerBase Constructor.
Definition: loggingserver.cpp:90
LoggingItem::message
QString message
Definition: logging.h:80
LoggingItem::getTimestamp
QString getTimestamp(void) const
Convert numerical timestamp to a readable date and time.
Definition: logging.cpp:237
MSqlQuery::isConnected
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:135
DatabaseLogger::~DatabaseLogger
~DatabaseLogger() override
DatabaseLogger deconstructor.
Definition: loggingserver.cpp:357
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
LoggingItem::appName
QString appName
Definition: logging.h:77
FileLogger::m_fd
int m_fd
contains the file descriptor for the logfile
Definition: loggingserver.h:60
LoggingItem::file
QString file
Definition: logging.h:74
LogForwardThread::LogForwardThread
LogForwardThread()
LogForwardThread constructor.
Definition: loggingserver.cpp:656
SyslogLogger::SyslogLogger
SyslogLogger()
logRevClientMapMutex
static QMutex logRevClientMapMutex
Definition: loggingserver.cpp:80
MSqlQuery::lastError
QSqlError lastError(void) const
Definition: mythdbcon.h:202
DBLoggerThread::m_aborted
volatile bool m_aborted
Used during shutdown to indicate that the thread should stop ASAP.
Definition: loggingserver.h:193
LoggingItem::line
int line
Definition: logging.h:69
ClientMap
QMap< QString, LoggerListItem * > ClientMap
Definition: loggingserver.cpp:71
LoggingItem::getTimestampUs
QString getTimestampUs(void) const
Definition: logging.cpp:244
logClientMap
static ClientMap logClientMap
Definition: loggingserver.cpp:77
DatabaseLogger
Database logger - logs to the MythTV database.
Definition: loggingserver.h:99
LoggerListItem::m_itemList
LoggerList * m_itemList
Definition: loggingserver.cpp:68
loggingGetTimeStamp
void loggingGetTimeStamp(qlonglong *epoch, uint *usec)
Definition: logging.cpp:129
logMsgListNotEmpty
static QWaitCondition logMsgListNotEmpty
Definition: loggingserver.cpp:85
DatabaseLogger::m_disabledTime
QElapsedTimer m_disabledTime
Elapsed time since the DB logging was disabled.
Definition: loggingserver.h:121
LoggerListItem::m_itemEpoch
qlonglong m_itemEpoch
Definition: loggingserver.cpp:69
mythcorecontext.h
FileLogger
File-based logger - used for logfiles and console.
Definition: loggingserver.h:49
LogForwardThread::stop
void stop(void)
Stop the thread by setting the abort flag.
Definition: loggingserver.cpp:880
DatabaseLogger::prepare
void prepare(MSqlQuery &query)
Prepare the database query for use, and bind constant values to it.
Definition: loggingserver.cpp:475
LoggingItem::create
static LoggingItem * create(const char *_file, const char *_function, int _line, LogLevel_t _level, LoggingType _type)
Create a new LoggingItem.
Definition: logging.cpp:574
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
logMsgListMutex
static QMutex logMsgListMutex
Definition: loggingserver.cpp:83
mythsyslog.h
logging.h
FileLogger::~FileLogger
~FileLogger() override
FileLogger deconstructor - close the logfile.
Definition: loggingserver.cpp:131
SyslogLogger::create
static SyslogLogger * create(QMutex *mutex, bool open=true)
DBLoggerThread::enqueue
bool enqueue(LoggingItem *item)
Enqueues a LoggingItem onto the queue for the thread to consume.
Definition: loggingserver.cpp:623
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
LoggingItem::rawFile
const char * rawFile() const
Definition: logging.h:132
MThread::isRunning
bool isRunning(void) const
Definition: mthread.cpp:272
DBLoggerThread::m_logger
DatabaseLogger * m_logger
The associated logger instance.
Definition: loggingserver.h:187
mythsignalingtimer.h
DBLoggerThread::m_queueMutex
QMutex m_queueMutex
Mutex for protecting the queue.
Definition: loggingserver.h:188
LoggingItem::function
QString function
Definition: logging.h:75
ClientList
QList< QString > ClientList
Definition: loggingserver.cpp:73
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:856
SyslogLogger::~SyslogLogger
~SyslogLogger() override
FileLogger::FileLogger
FileLogger(const char *filename)
FileLogger constructor.
Definition: loggingserver.cpp:120
RevClientMap
QMap< LoggerBase *, ClientList * > RevClientMap
Definition: loggingserver.cpp:74
LoggerBase::m_handle
char * m_handle
semi-opaque handle for identifying instance
Definition: loggingserver.h:44
LogForwardThread::incomingSigHup
void incomingSigHup(void)
FileLogger::reopen
void reopen(void) override
Reopen the logfile after a SIGHUP.
Definition: loggingserver.cpp:166
FileLogger::create
static FileLogger * create(const QString &filename, QMutex *mutex)
Definition: loggingserver.cpp:143
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:309
DBLoggerThread::queueFull
bool queueFull(void)
Indicates when the queue is full.
Definition: loggingserver.h:181
LoggingItem::facility
int facility
Definition: logging.h:72
exitcodes.h
loggerMapMutex
static QMutex loggerMapMutex
Definition: loggingserver.cpp:60
LoggerListItem
Definition: loggingserver.cpp:67
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
LogMessage
QList< QByteArray > LogMessage
Definition: loggingserver.h:127
SyslogLogger
Syslog-based logger (not available in Windows)
Definition: loggingserver.h:65
loggingserver.h
query
MSqlQuery query(MSqlQuery::InitCon())
DBLoggerThread::m_queue
QQueue< LoggingItem * > * m_queue
Queue of LoggingItems to insert.
Definition: loggingserver.h:189
LogForwardThread::forwardMessage
static void forwardMessage(LogMessage *msg)
Definition: loggingserver.cpp:749
DBLoggerThread::run
void run(void) override
Start the thread.
Definition: loggingserver.cpp:552
LoggingItem::rawThreadName
const char * rawThreadName() const
Definition: logging.h:134
LoggerList
QList< LoggerBase * > LoggerList
Definition: loggingserver.cpp:65
DBLoggerThread::m_wait
QWaitCondition * m_wait
Wait condition used for waiting for the queue to not be full.
Definition: loggingserver.h:190
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808