diff --git a/CMakeLists.txt b/CMakeLists.txt index c4b0c0a2..1db726dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ option(BUILD_SHARED_LIBS "build shared libraries instead of static" ON) option(ENABLE_CACHE_ALIGN "enable optional cache align requirement" OFF) option(MC_QUEUE "use moody-camel queue" OFF) option(TRACY_ENABLE "enable tracy profiler" OFF) +option(ENABLE_ALTIMETER "enable altimeter logging" OFF) if(NOT DEFINED SHARKSFIN_IMPLEMENTATION) set( @@ -63,6 +64,10 @@ find_package(Boost find_package(TBB REQUIRED) find_package(Protobuf REQUIRED) find_package(mpdecpp REQUIRED) +if (ENABLE_ALTIMETER) + find_package(altimeter REQUIRED) + find_package(fmt REQUIRED) +endif() include(GNUInstallDirs) include(CMakePackageConfigHelpers) include(CompileOptions) diff --git a/include/tateyama/altimeter/events.h b/include/tateyama/altimeter/events.h new file mode 100644 index 00000000..97fc0980 --- /dev/null +++ b/include/tateyama/altimeter/events.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018-2024 Project Tsurugi. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +// +// The following uses the same style as altimeter/logger/examples/altimeter/main.cpp +// +namespace tateyama::altimeter { +// log category list +namespace log_category { +static constexpr std::string_view event = "event"; +static constexpr std::string_view audit = "audit"; +} // namespace log_category + +// event log type list +namespace log_type::event { +static constexpr std::string_view session_start = "session_start"; +static constexpr std::string_view session_end = "session_end"; +} // namespace log_type::event + +// event log item list +namespace log_item::event { +static constexpr std::string_view user = "user"; +static constexpr std::string_view dbname = "dbname"; +static constexpr std::string_view pid = "pid"; +static constexpr std::string_view remote_host = "remote_host"; +static constexpr std::string_view application_name = "application_name"; +static constexpr std::string_view session_id = "session_id"; +} + +// event log level list +namespace log_level::event { +static constexpr int error = 30; +static constexpr int info = 50; +} // namespace log_level::event + +} // tateyama::altimeter diff --git a/include/tateyama/status/resource/bridge.h b/include/tateyama/status/resource/bridge.h index d8eeab2f..18485858 100644 --- a/include/tateyama/status/resource/bridge.h +++ b/include/tateyama/status/resource/bridge.h @@ -116,7 +116,7 @@ class bridge : public framework::resource { /** * @brief get proc_mutex file name */ - std::string_view mutex_file(); + [[nodiscard]] std::string_view mutex_file() const noexcept; /** * @brief remove session from ipc sessions @@ -140,6 +140,11 @@ class bridge : public framework::resource { return *database_info_; } + /** + * @brief returns the database name + */ + [[nodiscard]] std::string_view database_name() const; + private: bool deactivated_{false}; diff --git a/include/tateyama/status/resource/core.h b/include/tateyama/status/resource/core.h index 056820d6..910dc9e4 100644 --- a/include/tateyama/status/resource/core.h +++ b/include/tateyama/status/resource/core.h @@ -120,6 +120,9 @@ class resource_status_memory { void set_database_name(std::string_view name) { database_name_ = name; } + [[nodiscard]] std::string_view get_database_name() const { + return database_name_; + } void add_shm_entry(std::size_t session_id, std::size_t index) { sessions_.at(index) = session_id; } @@ -214,6 +217,9 @@ class resource_status_memory { void set_database_name(std::string_view name) { resource_status_->set_database_name(name); } + [[nodiscard]] std::string_view get_database_name() { + return resource_status_->get_database_name(); + } void add_shm_entry(std::size_t session_id, std::size_t index) { resource_status_->add_shm_entry(session_id, index); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 366d5d23..b8d4705d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -102,6 +102,13 @@ if(MC_QUEUE) target_compile_definitions(${ENGINE} PUBLIC MC_QUEUE) endif() +if (ENABLE_ALTIMETER) + target_link_libraries(${ENGINE} + PRIVATE altimeter + ) + target_compile_definitions(${ENGINE} PUBLIC ALTIMETER) +endif() + # Boost.Thread doesn't seem to allow multiple versions to coexist. # This version definition should be shared with caller at least. target_compile_definitions(${ENGINE} PUBLIC BOOST_THREAD_VERSION=4) diff --git a/src/tateyama/endpoint/altimeter/logger.h b/src/tateyama/endpoint/altimeter/logger.h new file mode 100644 index 00000000..69f42bf6 --- /dev/null +++ b/src/tateyama/endpoint/altimeter/logger.h @@ -0,0 +1,80 @@ +/* + * Copyright 2018-2024 Project Tsurugi. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace tateyama::endpoint::altimeter { +// +// The following two methods are created with reference to altimeter/logger/examples/altimeter/main.cpp +// + +using namespace tateyama::altimeter; + +static inline void session_start(const tateyama::api::server::database_info& database_info, const tateyama::api::server::session_info& session_info) { + if (::altimeter::logger::is_log_on(log_category::event, + log_level::event::info)) { + ::altimeter::log_item log_item; + log_item.category(log_category::event); + log_item.type(log_type::event::session_start); + log_item.level(log_level::event::info); + if (auto database_name = database_info.name(); !database_name.empty()) { + log_item.add(log_item::event::dbname, database_name); + } + log_item.add(log_item::event::pid, static_cast(database_info.process_id())); + if (auto connection_information = session_info.connection_information(); !connection_information.empty()) { + log_item.add(log_item::event::remote_host, connection_information); + } + if (auto application_name = session_info.application_name(); !application_name.empty()) { + log_item.add(log_item::event::application_name, application_name); + } + log_item.add(log_item::event::session_id, static_cast(session_info.id())); + ::altimeter::logger::log(log_item); + } +} + +static inline void session_end(const tateyama::api::server::database_info& database_info, const tateyama::api::server::session_info& session_info) { + if (::altimeter::logger::is_log_on(log_category::event, + log_level::event::info)) { + ::altimeter::log_item log_item; + log_item.category(log_category::event); + log_item.type(log_type::event::session_end); + log_item.level(log_level::event::info); + if (auto database_name = database_info.name(); !database_name.empty()) { + log_item.add(log_item::event::dbname, database_name); + } + log_item.add(log_item::event::pid, static_cast(database_info.process_id())); + if (auto connection_information = session_info.connection_information(); !connection_information.empty()) { + log_item.add(log_item::event::remote_host, connection_information); + } + if (auto application_name = session_info.application_name(); !application_name.empty()) { + log_item.add(log_item::event::application_name, application_name); + } + log_item.add(log_item::event::session_id, static_cast(session_info.id())); + ::altimeter::logger::log(log_item); + } +} + +} // tateyama::endpoint::altimeter diff --git a/src/tateyama/endpoint/ipc/bootstrap/server_wires_impl.h b/src/tateyama/endpoint/ipc/bootstrap/server_wires_impl.h index 52133e44..35e845ab 100644 --- a/src/tateyama/endpoint/ipc/bootstrap/server_wires_impl.h +++ b/src/tateyama/endpoint/ipc/bootstrap/server_wires_impl.h @@ -596,6 +596,7 @@ class connection_container public: explicit connection_container(std::string_view name, std::size_t n) : name_(name) { + boost::interprocess::shared_memory_object::remove(name_.c_str()); try { boost::interprocess::permissions unrestricted_permissions; unrestricted_permissions.set_unrestricted(); diff --git a/src/tateyama/endpoint/ipc/bootstrap/worker.cpp b/src/tateyama/endpoint/ipc/bootstrap/worker.cpp index 33eaaca8..92eced91 100644 --- a/src/tateyama/endpoint/ipc/bootstrap/worker.cpp +++ b/src/tateyama/endpoint/ipc/bootstrap/worker.cpp @@ -17,7 +17,10 @@ #include "worker.h" -#include +// #include +#ifdef ALTIMETER +#include "tateyama/endpoint/altimeter/logger.h" +#endif #include "tateyama/endpoint/ipc/ipc_request.h" #include "tateyama/endpoint/ipc/ipc_response.h" @@ -40,6 +43,9 @@ void Worker::run() VLOG(log_debug_timing_event) << "/:tateyama:timing:session:started " << session_id_; +#ifdef ALTIMETER + tateyama::endpoint::altimeter::session_start(database_info_, session_info_); +#endif while(true) { try { auto h = request_wire_container_->peep(true); @@ -61,6 +67,9 @@ void Worker::run() } clean_up_(); VLOG_LP(log_trace) << "destroy session wire: session_id = " << std::to_string(session_id_); +#ifdef ALTIMETER + tateyama::endpoint::altimeter::session_end(database_info_, session_info_); +#endif VLOG(log_debug_timing_event) << "/:tateyama:timing:session:finished " << session_id_; terminated_ = true; diff --git a/src/tateyama/endpoint/stream/bootstrap/stream_worker.cpp b/src/tateyama/endpoint/stream/bootstrap/stream_worker.cpp index b52948da..fadabc36 100644 --- a/src/tateyama/endpoint/stream/bootstrap/stream_worker.cpp +++ b/src/tateyama/endpoint/stream/bootstrap/stream_worker.cpp @@ -15,6 +15,9 @@ */ #include "stream_worker.h" +#ifdef ALTIMETER +#include "tateyama/endpoint/altimeter/logger.h" +#endif #include "tateyama/endpoint/stream/stream_request.h" #include "tateyama/endpoint/stream/stream_response.h" @@ -45,6 +48,9 @@ void stream_worker::run() #endif VLOG(log_debug_timing_event) << "/:tateyama:timing:session:started " << session_id_; +#ifdef ALTIMETER + tateyama::endpoint::altimeter::session_start(database_info_, session_info_); +#endif while(true) { std::uint16_t slot{}; std::string payload{}; @@ -59,6 +65,9 @@ void stream_worker::run() static_cast>(std::move(response))); request = nullptr; } +#ifdef ALTIMETER + tateyama::endpoint::altimeter::session_end(database_info_, session_info_); +#endif VLOG(log_debug_timing_event) << "/:tateyama:timing:session:finished " << session_id_; } diff --git a/src/tateyama/status/resource/bridge.cpp b/src/tateyama/status/resource/bridge.cpp index b0cf4d45..b41b394b 100644 --- a/src/tateyama/status/resource/bridge.cpp +++ b/src/tateyama/status/resource/bridge.cpp @@ -95,13 +95,20 @@ void bridge::mutex_file(std::string_view file_name) { } } -std::string_view bridge::mutex_file() { +std::string_view bridge::mutex_file() const noexcept { if (resource_status_memory_) { return resource_status_memory_->mutex_file(); } return {}; } +std::string_view bridge::database_name() const { + if (resource_status_memory_) { + return resource_status_memory_->get_database_name(); + } + throw std::runtime_error("resource_status_memory is not ready."); +} + void bridge::set_maximum_sessions(std::size_t n) { if (resource_status_memory_) { return resource_status_memory_->set_maximum_sessions(n);