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