You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
2.1KB

  1. #include <common.hpp>
  2. #include <asset.hpp>
  3. #include <settings.hpp>
  4. #include <system.hpp>
  5. #include <mutex>
  6. namespace rack {
  7. namespace logger {
  8. static FILE* outputFile = NULL;
  9. static int64_t startTime = 0;
  10. static std::mutex logMutex;
  11. void init() {
  12. startTime = system::getNanoseconds();
  13. if (settings::devMode) {
  14. outputFile = stderr;
  15. }
  16. else {
  17. outputFile = std::fopen(asset::logPath.c_str(), "w");
  18. if (!outputFile) {
  19. std::fprintf(stderr, "Could not open log at %s\n", asset::logPath.c_str());
  20. }
  21. }
  22. }
  23. void destroy() {
  24. if (outputFile && outputFile != stderr) {
  25. // Print end token so we know if the logger exited cleanly.
  26. std::fprintf(outputFile, "END");
  27. std::fclose(outputFile);
  28. }
  29. }
  30. static const char* const levelLabels[] = {
  31. "debug",
  32. "info",
  33. "warn",
  34. "fatal"
  35. };
  36. static const int levelColors[] = {
  37. 35,
  38. 34,
  39. 33,
  40. 31
  41. };
  42. static void logVa(Level level, const char* filename, int line, const char* format, va_list args) {
  43. std::lock_guard<std::mutex> lock(logMutex);
  44. if (!outputFile)
  45. return;
  46. int64_t nowTime = system::getNanoseconds();
  47. double duration = (nowTime - startTime) / 1e9;
  48. if (outputFile == stderr)
  49. std::fprintf(outputFile, "\x1B[%dm", levelColors[level]);
  50. std::fprintf(outputFile, "[%.03f %s %s:%d] ", duration, levelLabels[level], filename, line);
  51. if (outputFile == stderr)
  52. std::fprintf(outputFile, "\x1B[0m");
  53. std::vfprintf(outputFile, format, args);
  54. std::fprintf(outputFile, "\n");
  55. std::fflush(outputFile);
  56. }
  57. void log(Level level, const char* filename, int line, const char* format, ...) {
  58. va_list args;
  59. va_start(args, format);
  60. logVa(level, filename, line, format, args);
  61. va_end(args);
  62. }
  63. bool isTruncated() {
  64. if (settings::devMode)
  65. return false;
  66. // Open existing log file
  67. FILE* file = std::fopen(asset::logPath.c_str(), "r");
  68. if (!file)
  69. return false;
  70. DEFER({
  71. std::fclose(file);
  72. });
  73. // Seek to last 3 characters
  74. std::fseek(file, -3, SEEK_END);
  75. char str[3];
  76. if (std::fread(str, 1, 3, file) != 3)
  77. return true;
  78. if (std::memcmp(str, "END", 3) != 0)
  79. return true;
  80. return false;
  81. }
  82. } // namespace logger
  83. } // namespace rack