log.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <span>
  5. #include <string_view>
  6. namespace sunrise::core::log {
  7. /** 1 KiB caps each serialized event, with room for a trailing null byte. */
  8. inline constexpr std::size_t kLineCapacity = 1024;
  9. /** Subsystem owning one structured log event. */
  10. enum class Channel : std::size_t {
  11. core,
  12. client,
  13. state,
  14. server,
  15. middleware,
  16. count,
  17. };
  18. /** Minimum severity accepted by one log channel. */
  19. enum class Level : unsigned char {
  20. error,
  21. warn,
  22. info,
  23. debug,
  24. off,
  25. };
  26. /** Process-wide logging thresholds and sink selection. */
  27. struct Settings {
  28. std::array<Level, static_cast<std::size_t>(Channel::count)> levels{};
  29. bool debuggerSink{true};
  30. bool fileSink{false};
  31. };
  32. /** Returns logging defaults with persistent output disabled. */
  33. [[nodiscard]] Settings defaults() noexcept;
  34. /** Starts configured logging sinks relative to the DLL module. */
  35. [[nodiscard]] bool initialize(void* module, const Settings& settings) noexcept;
  36. /** Closes active sinks and clears the bounded in-memory log view. */
  37. void shutdown() noexcept;
  38. /** @return True while the channel threshold admits this severity. */
  39. [[nodiscard]] bool accepts(Channel channel, Level level) noexcept;
  40. /** Emits one structured event when allowed by the channel threshold. */
  41. void write(Channel channel, Level level, std::string_view event) noexcept;
  42. /**
  43. * Formats and emits one structured event when allowed by the channel threshold.
  44. *
  45. * The line is built in `kLineCapacity` storage and truncated to fit, which is what every caller
  46. * that spelled out its own array and `snprintf` did by hand. Nothing is formatted for a level the
  47. * channel refuses, so a debug line costs nothing when debug is off.
  48. *
  49. * @param channel Subsystem owning the event.
  50. * @param level Severity of the event.
  51. * @param format printf-style format; `%s` arguments must be NUL-terminated.
  52. */
  53. void writef(Channel channel, Level level, const char* format, ...) noexcept;
  54. /**
  55. * Emits one debug event carrying a duration in the ms field.
  56. * Timing is diagnostic, so it stays off at the levels a normal run uses.
  57. * @param channel Channel owning the measured boundary.
  58. * @param event Event and phase text the duration is appended to.
  59. * @param startedTick GetTickCount64 value taken when the boundary began.
  60. * @param result Outcome text for the log line.
  61. */
  62. void write_elapsed(Channel channel,
  63. std::string_view event,
  64. unsigned long long startedTick,
  65. std::string_view result) noexcept;
  66. /**
  67. * Appends bytes as uppercase hex to a line that already holds its key prefix.
  68. * Stops before the first pair that would not fit, so a long payload truncates.
  69. * @param line Line storage holding the prefix.
  70. * @param length Bytes already written, raised by two for each encoded byte.
  71. * @param bytes Borrowed payload to encode.
  72. * @return True when every byte fit.
  73. */
  74. bool append_hex(std::span<char> line,
  75. std::size_t& length,
  76. std::span<const std::byte> bytes) noexcept;
  77. /**
  78. * Reports whether any thread is inside a sink write.
  79. * A sink holds an operating system lock this process shares, so a thread suspended there
  80. * blocks the next writer. Nothing may suspend process threads while this is true.
  81. * @return True while a sink write is in progress.
  82. */
  83. [[nodiscard]] bool writers_active() noexcept;
  84. /**
  85. * Writes one line straight to the debugger, bypassing the sinks and every threshold.
  86. * Settings are read before the sinks exist, so a boot failure there has no other channel.
  87. */
  88. void early(std::string_view event) noexcept;
  89. } // namespace sunrise::core::log