From 4ce38a8356ce4540ac09051ae1f5c66bc0699823 Mon Sep 17 00:00:00 2001 From: cookjosh <95898644+cookjosh@users.noreply.github.com> Date: Thu, 6 Mar 2025 16:31:25 -0800 Subject: [PATCH] add boilerplate methods to device class similar to synapse-python --- include/science/synapse/device.h | 36 ++++++++++++++ src/science/synapse/device.cpp | 81 ++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/include/science/synapse/device.h b/include/science/synapse/device.h index 676fb96..426dff4 100644 --- a/include/science/synapse/device.h +++ b/include/science/synapse/device.h @@ -23,6 +23,14 @@ class IDevice { virtual auto stop(std::optional timeout = std::nullopt) -> science::Status = 0; virtual auto sockets() const -> const std::vector& = 0; virtual auto uri() const -> const std::string& = 0; + virtual auto get_logs( + const std::string& log_level = "INFO", + std::optional since_ms = std::nullopt, + std::optional start_time_ns = std::nullopt, + std::optional end_time_ns = std::nullopt) -> std::vector = 0; + virtual auto tail_logs( + const std::string& log_level = "INFO", + std::optional timeout = std::nullopt) -> std::vector = 0; }; /** @@ -66,6 +74,32 @@ class Device : public IDevice { */ [[nodiscard]] auto uri() const -> const std::string&; + /** + * Get the logs from the device. + * + * @param log_level Minimum log level to retrieve (default: INFO) + * @param since_ms Get logs from this many milliseconds ago (optional) + * @param start_time_ns Start time in nanoseconds since epoch (optional) + * @param end_time_ns End time in nanoseconds since epoch (optional) + * @return std::vector containing log entries + */ + [[nodiscard]] auto get_logs( + const std::string& log_level = "INFO", + std::optional since_ms = std::nullopt, + std::optional start_time_ns = std::nullopt, + std::optional end_time_ns = std::nullopt) -> std::vector; + + /** + * Tail the logs from the device. + * + * @param log_level Minimum log level to retrieve (default: INFO) + * @param timeout Timeout for the request (optional) + * @return std::vector containing the most recent log entries + */ + [[nodiscard]] auto tail_logs( + const std::string& log_level = "INFO", + std::optional timeout = std::nullopt) -> std::vector; + private: std::string uri_; std::shared_ptr channel_; @@ -74,6 +108,8 @@ class Device : public IDevice { std::vector sockets_; [[nodiscard]] auto handle_status_response(const synapse::Status& status) -> science::Status; + + [[nodiscard]] auto log_level_to_pb(const std::string& level) -> synapse::LogLevel; }; } // namespace synapse diff --git a/src/science/synapse/device.cpp b/src/science/synapse/device.cpp index 310bb4d..c739c4b 100644 --- a/src/science/synapse/device.cpp +++ b/src/science/synapse/device.cpp @@ -159,6 +159,78 @@ auto Device::uri() const -> const std::string& { return uri_; } +auto Device::get_logs( + const std::string& log_level, + std::optional since_ms, + std::optional start_time_ns, + std::optional end_time_ns, + std::optional timeout) -> std::vector { + + synapse::LogQueryRequest request; + request.set_min_level(log_level_to_pb(log_level)); + + if (since_ms.has_value()) { + request.set_since_ms(since_ms.value()); + } else { + if (start_time_ns.has_value()) { + request.set_start_time_ns(start_time_ns.value()); + } + if (end_time_ns.has_value()) { + request.set_end_time_ns(end_time_ns.value()); + } + } + + grpc::ClientContext context; + if (timeout.has_value()) { + context.set_deadline(std::chrono::system_clock::now() + timeout.value()); + } + + synapse::LogQueryResponse response; + std::vector logs; + + grpc::Status status = rpc_->GetLogs(&context, request, &response); + + if (status.ok()) { + for (const auto& entry : response.entries()) { + logs.push_back(entry.message()); + } + } else { + std::cerr << "Error getting logs: " << status.error_message() << std::endl; + } + + return logs; +} + +auto Device::tail_logs( + const std::string& log_level, + std::optional timeout) -> std::vector { + + synapse::TailLogsRequest request; + request.set_min_level(log_level_to_pb(log_level)); + + grpc::ClientContext context; + if (timeout.has_value()) { + context.set_deadline(std::chrono::system_clock::now() + timeout.value()); + } + + std::vector logs; + + std::unique_ptr> reader( + rpc_->TailLogs(&context, request)); + + synapse::LogEntry entry; + while (reader->Read(&entry)) { + logs.push_back(entry.message()); + } + + grpc::Status status = reader->Finish(); + if (!status.ok()) { + std::cerr << "Error tailing logs: " << status.error_message() << std::endl; + } + + return logs; +} + auto Device::handle_status_response(const synapse::Status& status) -> science::Status { if (status.code() != synapse::StatusCode::kOk) { return { @@ -177,4 +249,13 @@ auto Device::handle_status_response(const synapse::Status& status) -> science::S return {}; } +auto Device::log_level_to_pb(const std::string& level) -> synapse::LogLevel { + if (level == "DEBUG") return synapse::LogLevel::LOG_LEVEL_DEBUG; + if (level == "INFO") return synapse::LogLevel::LOG_LEVEL_INFO; + if (level == "WARNING") return synapse::LogLevel::LOG_LEVEL_WARNING; + if (level == "ERROR") return synapse::LogLevel::LOG_LEVEL_ERROR; + if (level == "CRITICAL") return synapse::LogLevel::LOG_LEVEL_CRITICAL; + return synapse::LogLevel::LOG_LEVEL_UNKNOWN; +} + } // namespace synapse