logger.d 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * pixiv_down - CLI-based downloading tool for https://www.pixiv.net.
  3. * Copyright (C) 2024 Mio
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, version 3 of the License.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. */
  17. module app.logger;
  18. import std.experimental.logger;
  19. import app.pd_version: VCS_TAG;
  20. // dup (app.d); should be moved to config file.
  21. enum PIXIV_DOWN_VERSION_STRING = "2024.10.0";
  22. void initializeLogger()
  23. {
  24. import std.process : environment;
  25. import std.stdio : stderr;
  26. import std.uni : toLower;
  27. LogLevel level = LogLevel.warning;
  28. if ("PIXIV_DOWN_LOG_LEVEL" in environment) {
  29. const value = environment["PIXIV_DOWN_LOG_LEVEL"].toLower;
  30. switch(value) {
  31. case "all":
  32. level = LogLevel.all;
  33. break;
  34. case "trace":
  35. level = LogLevel.trace;
  36. break;
  37. case "info":
  38. level = LogLevel.info;
  39. break;
  40. case "debug":
  41. stderr.writeln("NOTE: The 'debug' log level is no longer supported.");
  42. stderr.writeln(" Falling back to 'warning'.");
  43. level = LogLevel.warning;
  44. break;
  45. case "warning":
  46. level = LogLevel.warning;
  47. break;
  48. case "error":
  49. level = LogLevel.error;
  50. break;
  51. case "fatal":
  52. level = LogLevel.fatal;
  53. break;
  54. default:
  55. stderr.writeln("Unknown log level: ", level);
  56. stderr.writeln("Supported values are: trace, info, warning, error, and fatal.");
  57. break;
  58. }
  59. }
  60. static if (__VERSION__ < 2101L) {
  61. sharedLog = new PDLogger(level);
  62. } else {
  63. sharedLog = cast(shared(PDLogger))new PDLogger(level);
  64. }
  65. logCompilationInfo();
  66. }
  67. private void logCompilationInfo()
  68. {
  69. const bits = (void*).sizeof == 8 ? "64" : "32";
  70. version (linux)
  71. const system = "Linux";
  72. else version (Windows)
  73. const system = "Windows";
  74. else version (OSX)
  75. const system = "macOS";
  76. else
  77. const system = "Unknown";
  78. infof("pixiv_down %s (%s) started", PIXIV_DOWN_VERSION_STRING, VCS_TAG);
  79. infof("Running on %s | %s-bit build | %s %,?d", system, bits, __VENDOR__, '.', __VERSION__);
  80. }
  81. class PDLogger : FileLogger {
  82. import std.concurrency : Tid;
  83. import std.datetime.systime : SysTime;
  84. import mlib.directories;
  85. private ProjectDirectories projectDirs;
  86. const string fileName;
  87. this(const LogLevel level = LogLevel.all) @safe
  88. {
  89. import std.file: exists, remove;
  90. import std.path: buildPath;
  91. projectDirs = getProjectDirectories(null, "YumeNeru Software", "pixiv_down");
  92. fileName = buildPath(projectDirs.stateDir, "pixiv_down.log");
  93. if (exists(fileName))
  94. {
  95. remove(fileName);
  96. }
  97. super(fileName, level);
  98. }
  99. override protected void beginLogMsg(string file, int line, string funcName,
  100. string prettyFuncName, string moduleName, LogLevel logLevel, Tid threadId,
  101. SysTime timestamp, Logger logger)
  102. {
  103. import std.conv : to;
  104. import std.datetime : DateTime;
  105. import std.format : formattedWrite;
  106. import std.string : toUpper;
  107. static if (__VERSION__ <= 2076L) {
  108. auto lt = this.file.lockingTextWriter();
  109. } else {
  110. auto lt = this.file_.lockingTextWriter();
  111. }
  112. auto dt = cast(DateTime)timestamp;
  113. formattedWrite(lt, "%s | %s | %5s | %-10s | ", dt.date.toISOExtString(),
  114. dt.timeOfDay.toISOExtString(), to!string(logLevel).toUpper, moduleName);
  115. }
  116. }