Log.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. //
  2. // Created by Tobias Hieta on 07/03/16.
  3. //
  4. #include "Log.h"
  5. #include <QtQml>
  6. #include <QGuiApplication>
  7. #include <iostream>
  8. #include "shared/Names.h"
  9. #include "shared/Paths.h"
  10. #include "settings/SettingsComponent.h"
  11. #include "Version.h"
  12. int logLevel = 0;
  13. bool logToTerminal = false;
  14. QHash<QtMsgType, int> messageLevelValue({{QtDebugMsg, 1}, {QtInfoMsg, 2}, {QtWarningMsg, 3}, {QtCriticalMsg, 4}, {QtFatalMsg, 5}});
  15. /////////////////////////////////////////////////////////////////////////////////////////
  16. // adapted from https://stackoverflow.com/a/62390212
  17. static void qtMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg)
  18. {
  19. static QMutex mutex;
  20. QMutexLocker lock(&mutex);
  21. if (messageLevelValue[type] < logLevel && type != QtFatalMsg)
  22. return;
  23. static QFile logFile(Paths::logDir(Names::MainName() + ".log"));
  24. static bool logFileIsOpen = logFile.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text);
  25. QString message = qFormatLogMessage(type, context, msg);
  26. Log::CensorAuthTokens(message);
  27. if (logToTerminal) {
  28. std::cerr << qPrintable(message) << std::endl;
  29. }
  30. if (logFileIsOpen) {
  31. logFile.write(message.toUtf8() + '\n');
  32. logFile.flush();
  33. }
  34. if (type == QtFatalMsg)
  35. abort();
  36. }
  37. /////////////////////////////////////////////////////////////////////////////////////////
  38. static void elidePattern(QString& msg, const QString& substring, int chars)
  39. {
  40. int start = 0;
  41. while (true)
  42. {
  43. start = msg.indexOf(substring, start);
  44. if (start < 0 || start + substring.length() + chars > msg.length())
  45. break;
  46. start += substring.length();
  47. for (int n = 0; n < chars; n++)
  48. msg[start + n] = QChar('x');
  49. }
  50. }
  51. /////////////////////////////////////////////////////////////////////////////////////////
  52. void Log::CensorAuthTokens(QString& msg)
  53. {
  54. elidePattern(msg, "api_key=", 32);
  55. elidePattern(msg, "X-MediaBrowser-Token%3D", 32);
  56. elidePattern(msg, "X-MediaBrowser-Token=", 32);
  57. elidePattern(msg, "api_key=", 32);
  58. elidePattern(msg, "ApiKey=", 32);
  59. elidePattern(msg, "AccessToken=", 32);
  60. elidePattern(msg, "AccessToken\":\"", 32);
  61. }
  62. /////////////////////////////////////////////////////////////////////////////////////////
  63. static int logLevelFromString(const QString& str)
  64. {
  65. if (str == "trace") return 0;
  66. if (str == "debug") return 1;
  67. if (str == "info") return 2;
  68. if (str == "warn") return 3;
  69. if (str == "error") return 4;
  70. if (str == "fatal") return 5;
  71. // if not valid, use default
  72. return 1;
  73. }
  74. /////////////////////////////////////////////////////////////////////////////////////////
  75. void Log::UpdateLogLevel()
  76. {
  77. QString level = SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "logLevel").toString();
  78. if (level.size())
  79. {
  80. qInfo() << "Setting log level to:" << level;
  81. logLevel = logLevelFromString(level);
  82. }
  83. }
  84. /////////////////////////////////////////////////////////////////////////////////////////
  85. bool Log::ShouldLogInfo()
  86. {
  87. return logLevel <= 2;
  88. }
  89. /////////////////////////////////////////////////////////////////////////////////////////
  90. void Log::Init()
  91. {
  92. // Note where the logfile is going to be
  93. qDebug() << "Logging to " << qPrintable(Paths::logDir(Names::MainName() + ".log"));
  94. qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss.zzz} [%{type}] %{function} @ %{line} - %{message}");
  95. qInstallMessageHandler(qtMessageOutput);
  96. qInfo() << "Starting Jellyfin Media Player version:" << qPrintable(Version::GetVersionString()) << "build date:" << qPrintable(Version::GetBuildDate());
  97. qInfo() << qPrintable(QString(" Running on: %1 [%2] arch %3").arg(QSysInfo::prettyProductName()).arg(QSysInfo::kernelVersion()).arg(QSysInfo::currentCpuArchitecture()));
  98. qInfo() << " Qt Version:" << QT_VERSION_STR << qPrintable(QString("[%1]").arg(QSysInfo::buildAbi()));
  99. }
  100. /////////////////////////////////////////////////////////////////////////////////////////
  101. void Log::EnableTerminalOutput()
  102. {
  103. logToTerminal = true;
  104. }
  105. /////////////////////////////////////////////////////////////////////////////////////////
  106. void Log::Uninit()
  107. {
  108. qInstallMessageHandler(0);
  109. }