diff options
| author | Dan Engelbrecht <[email protected]> | 2022-09-13 11:35:38 +0200 |
|---|---|---|
| committer | Dan Engelbrecht <[email protected]> | 2022-09-13 11:35:38 +0200 |
| commit | 6e17e4ae9d4be442394399c8bc74b4cf38acfe61 (patch) | |
| tree | d38c3d5d2b75bbaf6eb7e4495d2be9f3d03e2bff | |
| parent | Merge remote-tracking branch 'origin/main' into de/new-upstream-api-with-sepa... (diff) | |
| parent | Add pkg-config requirement to README.md (diff) | |
| download | zen-6e17e4ae9d4be442394399c8bc74b4cf38acfe61.tar.xz zen-6e17e4ae9d4be442394399c8bc74b4cf38acfe61.zip | |
Merge remote-tracking branch 'origin/main' into de/new-upstream-api-with-separate-policy
| -rw-r--r-- | .github/workflows/create_release.yml | 27 | ||||
| -rw-r--r-- | CHANGELOG.md | 4 | ||||
| -rw-r--r-- | README.md | 6 | ||||
| -rw-r--r-- | VERSION.txt | 2 | ||||
| -rw-r--r-- | zencore/include/zencore/logging.h | 20 | ||||
| -rw-r--r-- | zenserver/diag/logging.cpp | 157 | ||||
| -rw-r--r-- | zenserver/zenserver.cpp | 23 |
7 files changed, 210 insertions, 29 deletions
diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index 9e3a430a9..78ed375ae 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -195,6 +195,23 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Read VERSION.txt + id: read_version + uses: andstor/file-reader-action@v1 + with: + path: "VERSION.txt" + + - name: Get Sentry CLI + run: | + curl -sL https://sentry.io/get-cli/ | bash + ls -la ./scripts + env: + INSTALL_DIR: ./scripts + + - name: Create Release in Sentry + run: | + scripts/sentry-cli --auth-token ${{ secrets.SENTRY_API_KEY }} releases new --org to --project zen-server ${{steps.read_version.outputs.contents}} + - name: Download Linux artifacts uses: actions/download-artifact@v1 with: @@ -223,12 +240,6 @@ jobs: with: path: "CHANGELOG.tmp" - - name: Read VERSION.txt - id: read_version - uses: andstor/file-reader-action@v1 - with: - path: "VERSION.txt" - - name: Check prerelease id: get-prerelease uses: haya14busa/action-cond@v1 @@ -252,3 +263,7 @@ jobs: linux/zenserver-linux.zip win64/zenserver-win64.zip macos/zenserver-macos.zip + + - name: Finalize Release in Sentry + run: | + scripts/sentry-cli --auth-token ${{ secrets.SENTRY_API_KEY }} releases finalize --org to --project zen-server ${{steps.read_version.outputs.contents}} diff --git a/CHANGELOG.md b/CHANGELOG.md index 352b1e894..6cd94a99a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ ## +- Feature: Adding a `.json` extension to the `--abslog` option will make zenserver log in json format to file +- Feature: Create release in Sentry and use `sentry_options_set_release` to associate the executable + +## v0.1.5 - Bugfix: Don't fail entire request if GetCacheValue from Horde fails for a single value ## v0.1.4 @@ -107,6 +107,12 @@ To build some of the packages from vcpkg you may need some additional tools. sudo apt-get install build-essential ``` +Some of the dependencies in `vckpg` needs `pkg-config` so make sure to install that as well. + +``` +sudo apt-get install pkg-config +``` + Some of Zen's third party dependencies are provided by Microsoft's `vcpkg` C++ library manager. After cloning the project there is an initialisation step. diff --git a/VERSION.txt b/VERSION.txt index def9a0154..41e9b109b 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -0.1.5
\ No newline at end of file +0.1.6-pre6
\ No newline at end of file diff --git a/zencore/include/zencore/logging.h b/zencore/include/zencore/logging.h index 7c2deeed7..45dbd8c56 100644 --- a/zencore/include/zencore/logging.h +++ b/zencore/include/zencore/logging.h @@ -129,18 +129,18 @@ struct LogCategory Log().warn(fmtstr##sv, ##__VA_ARGS__); \ } while (false) -#define ZEN_ERROR(fmtstr, ...) \ - do \ - { \ - using namespace std::literals; \ - Log().error(fmtstr##sv, ##__VA_ARGS__); \ +#define ZEN_ERROR(fmtstr, ...) \ + do \ + { \ + using namespace std::literals; \ + Log().log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, spdlog::level::err, fmtstr##sv, ##__VA_ARGS__); \ } while (false) -#define ZEN_CRITICAL(fmtstr, ...) \ - do \ - { \ - using namespace std::literals; \ - Log().critical(fmtstr##sv, ##__VA_ARGS__); \ +#define ZEN_CRITICAL(fmtstr, ...) \ + do \ + { \ + using namespace std::literals; \ + Log().log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, spdlog::level::critical, fmtstr##sv, ##__VA_ARGS__); \ } while (false) #define ZEN_CONSOLE(fmtstr, ...) \ diff --git a/zenserver/diag/logging.cpp b/zenserver/diag/logging.cpp index a5620a642..7d4e458cc 100644 --- a/zenserver/diag/logging.cpp +++ b/zenserver/diag/logging.cpp @@ -178,6 +178,149 @@ private: std::string m_LogId; }; +class json_formatter final : public spdlog::formatter +{ +public: + json_formatter(std::string_view LogId) : m_LogId(LogId) {} + + virtual std::unique_ptr<formatter> clone() const override { return std::make_unique<json_formatter>(m_LogId); } + + virtual void format(const details::log_msg& msg, memory_buf_t& dest) override + { + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::seconds; + + auto secs = std::chrono::duration_cast<seconds>(msg.time.time_since_epoch()); + if (secs != m_LastLogSecs) + { + m_CachedTm = os::localtime(log_clock::to_time_t(msg.time)); + m_LastLogSecs = secs; + } + + const auto& tm_time = m_CachedTm; + + // cache the date/time part for the next second. + + if (m_CacheTimestamp != secs || m_CachedDatetime.size() == 0) + { + m_CachedDatetime.clear(); + + fmt_helper::append_int(tm_time.tm_year + 1900, m_CachedDatetime); + m_CachedDatetime.push_back('-'); + + fmt_helper::pad2(tm_time.tm_mon + 1, m_CachedDatetime); + m_CachedDatetime.push_back('-'); + + fmt_helper::pad2(tm_time.tm_mday, m_CachedDatetime); + m_CachedDatetime.push_back(' '); + + fmt_helper::pad2(tm_time.tm_hour, m_CachedDatetime); + m_CachedDatetime.push_back(':'); + + fmt_helper::pad2(tm_time.tm_min, m_CachedDatetime); + m_CachedDatetime.push_back(':'); + + fmt_helper::pad2(tm_time.tm_sec, m_CachedDatetime); + + m_CachedDatetime.push_back('.'); + + m_CacheTimestamp = secs; + } + dest.append("{"sv); + dest.append("\"time\": \""sv); + dest.append(m_CachedDatetime.begin(), m_CachedDatetime.end()); + auto millis = fmt_helper::time_fraction<milliseconds>(msg.time); + fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest); + dest.append("\", "sv); + + dest.append("\"status\": \""sv); + dest.append(level::to_string_view(msg.level)); + dest.append("\", "sv); + + dest.append("\"source\": \""sv); + dest.append("zenserver"sv); + dest.append("\", "sv); + + if (!m_LogId.empty()) + { + dest.append("\"id\": \""sv); + dest.append(m_LogId); + dest.append("\", "sv); + } + + if (msg.logger_name.size() > 0) + { + dest.append("\"service\": \""sv); + dest.append(msg.logger_name); + dest.append("\", "sv); + } + + if (msg.thread_id != 0) + { + dest.append("\"thread\": \""sv); + fmt_helper::pad_uint(msg.thread_id, 0, dest); + dest.append("\", "sv); + } + + if (!msg.source.empty()) + { + dest.append("\"file\": \""sv); + WriteEscapedString(dest, details::short_filename_formatter<details::null_scoped_padder>::basename(msg.source.filename)); + dest.append("\","sv); + + dest.append("\"line\": \""sv); + dest.append(fmt::format("{}", msg.source.line)); + dest.append("\","sv); + + dest.append("\"function\": \""sv); + WriteEscapedString(dest, msg.source.funcname); + dest.append("\", "sv); + } + + dest.append("\"message\": \""sv); + WriteEscapedString(dest, msg.payload); + dest.append("\""sv); + + dest.append("}\n"sv); + } + +private: + static inline const std::unordered_map<char, std::string_view> SpecialCharacterMap{{'\b', "\\b"sv}, + {'\f', "\\f"sv}, + {'\n', "\\n"sv}, + {'\r', "\\r"sv}, + {'\t', "\\t"sv}, + {'"', "\\\""sv}, + {'\\', "\\\\"sv}}; + + static void WriteEscapedString(memory_buf_t& dest, const spdlog::string_view_t& payload) + { + const char* RangeStart = payload.begin(); + for (const char* It = RangeStart; It != payload.end(); ++It) + { + if (auto SpecialIt = SpecialCharacterMap.find(*It); SpecialIt != SpecialCharacterMap.end()) + { + if (RangeStart != It) + { + dest.append(RangeStart, It); + } + dest.append(SpecialIt->second); + RangeStart = It + 1; + } + } + if (RangeStart != payload.end()) + { + dest.append(RangeStart, payload.end()); + } + }; + + std::tm m_CachedTm{0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::chrono::seconds m_LastLogSecs{0}; + std::chrono::seconds m_CacheTimestamp{0}; + memory_buf_t m_CachedDatetime; + std::string m_LogId; +}; } // namespace logging bool @@ -350,13 +493,21 @@ InitializeLogging(const ZenServerOptions& GlobalOptions) spdlog::flush_every(std::chrono::seconds{2}); spdlog::set_formatter(std::make_unique<logging::full_formatter>(GlobalOptions.LogId, std::chrono::system_clock::now())); - FileSink->set_pattern("[%C-%m-%d.%e %T] [%n] [%l] %v"); - - spdlog::info("log starting at {:%FT%T%z}", std::chrono::system_clock::now()); + if (GlobalOptions.AbsLogFile.extension() == ".json") + { + FileSink->set_formatter(std::make_unique<logging::json_formatter>(GlobalOptions.LogId)); + } + else + { + FileSink->set_pattern("[%C-%m-%d.%e %T] [%n] [%l] %v"); + } + DefaultLogger.info("log starting at {:%FT%T%z}", std::chrono::system_clock::now()); } void ShutdownLogging() { + auto& DefaultLogger = zen::logging::Default(); + DefaultLogger.info("log ending at {:%FT%T%z}", std::chrono::system_clock::now()); zen::logging::ShutdownLogging(); } diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp index 9e15b0c64..1c94d80b7 100644 --- a/zenserver/zenserver.cpp +++ b/zenserver/zenserver.cpp @@ -948,7 +948,7 @@ ZenEntryPoint::Run() { #if ZEN_USE_SENTRY std::string SentryDatabasePath = PathToUtf8(m_ServerOptions.DataDir / ".sentry-native"); - + int SentryErrorCode = 0; if (m_ServerOptions.NoSentry == false) { sentry_options_t* SentryOptions = sentry_options_new(); @@ -956,16 +956,10 @@ ZenEntryPoint::Run() sentry_options_set_database_path(SentryOptions, SentryDatabasePath.c_str()); sentry_options_set_logger(SentryOptions, SentryLogFunction, this); sentry_options_add_attachment(SentryOptions, m_ServerOptions.AbsLogFile.string().c_str()); + sentry_options_set_release(SentryOptions, ZEN_CFG_VERSION); // sentry_options_set_debug(SentryOptions, 1); - if (int ErrorCode = sentry_init(SentryOptions); ErrorCode == 0) - { - printf("sentry initialized"); - } - else - { - printf("sentry_init returned failure! (error code: %d)", ErrorCode); - } + SentryErrorCode = sentry_init(SentryOptions); } auto _ = zen::MakeGuard([] { sentry_close(); }); @@ -1001,6 +995,17 @@ ZenEntryPoint::Run() InitializeLogging(ServerOptions); +#if ZEN_USE_SENTRY + if (SentryErrorCode == 0) + { + ZEN_INFO("sentry initialized"); + } + else + { + ZEN_WARN("sentry_init returned failure! (error code: {})", SentryErrorCode); + } +#endif + MaximizeOpenFileCount(); ZEN_INFO(ZEN_APP_NAME " - using lock file at '{}'", LockFilePath); |