From e69a05a5bf7de4bc19632a8b8d02237d720ce464 Mon Sep 17 00:00:00 2001 From: Zhang Lei Date: Wed, 14 Aug 2024 11:50:33 +0800 Subject: [PATCH] fix(interactive): Catch exceptions thrown by nlohmann json (#4127) Catch exceptions thrown by nlohmann json and add additional debug logging. --- .../http_server/actor/admin_actor.act.cc | 60 ++++++-- .../metadata/default_graph_meta_store.cc | 13 +- flex/storages/metadata/graph_meta_store.cc | 139 +++++++++++++----- 3 files changed, 156 insertions(+), 56 deletions(-) diff --git a/flex/engines/http_server/actor/admin_actor.act.cc b/flex/engines/http_server/actor/admin_actor.act.cc index 5dc94e44a0eb..6cdb2de1b0ae 100644 --- a/flex/engines/http_server/actor/admin_actor.act.cc +++ b/flex/engines/http_server/actor/admin_actor.act.cc @@ -96,7 +96,12 @@ std::string merge_graph_and_plugin_meta( nlohmann::json res; for (auto& graph_meta : res_graph_metas) { - res.push_back(nlohmann::json::parse(graph_meta.ToJson())); + try { + res.push_back(nlohmann::json::parse(graph_meta.ToJson())); + } catch (const std::exception& e) { + LOG(ERROR) << "Fail to parse graph meta: " << e.what() + << graph_meta.ToJson(); + } } return res.empty() ? "{}" : res.dump(); } @@ -348,20 +353,38 @@ gs::Status invoke_delete_plugin_meta( // util functions -std::string to_json_str(const std::vector& plugin_metas) { - nlohmann::json res; - for (auto& plugin_meta : plugin_metas) { - res.push_back(nlohmann::json::parse(plugin_meta.ToJson())); +gs::Result to_json_str( + const std::vector& plugin_metas) { + try { + nlohmann::json res; + for (auto& plugin_meta : plugin_metas) { + res.push_back(nlohmann::json::parse(plugin_meta.ToJson())); + } + return res.empty() ? gs::Result("{}") + : gs::Result(res.dump()); + } catch (const std::exception& e) { + LOG(ERROR) << "Fail to parse plugin meta from json string: " << e.what(); + return gs::Result( + gs::Status(gs::StatusCode::InternalError, + "Fail to parse plugin meta: " + std::string(e.what()))); } - return res.empty() ? "{}" : res.dump(); } -std::string to_json_str(const std::vector& job_metas) { - nlohmann::json res; - for (auto& job_meta : job_metas) { - res.push_back(nlohmann::json::parse(job_meta.ToJson(true))); +gs::Result to_json_str( + const std::vector& job_metas) { + try { + nlohmann::json res; + for (auto& job_meta : job_metas) { + res.push_back(nlohmann::json::parse(job_meta.ToJson())); + } + return res.empty() ? gs::Result("{}") + : gs::Result(res.dump()); + } catch (const std::exception& e) { + LOG(ERROR) << "Fail to parse job meta from json string: " << e.what(); + return gs::Result( + gs::Status(gs::StatusCode::InternalError, + "Fail to parse job meta: " + std::string(e.what()))); } - return res.empty() ? "{}" : res.dump(); } admin_actor::~admin_actor() { @@ -711,7 +734,7 @@ seastar::future admin_actor::get_procedures_by_graph_name( graph_meta_res.value().plugin_metas.begin(), graph_meta_res.value().plugin_metas.end()); return seastar::make_ready_future( - gs::Result(to_json_str(all_plugin_metas))); + to_json_str(all_plugin_metas)); } else { LOG(ERROR) << "Fail to get all procedures: " << get_all_procedure_res.status().error_message(); @@ -1146,7 +1169,15 @@ seastar::future admin_actor::service_status( graph_meta.plugin_metas.emplace_back(plugin_meta); } } - res["graph"] = nlohmann::json::parse(graph_meta.ToJson()); + try { + res["graph"] = nlohmann::json::parse(graph_meta.ToJson()); + } catch (std::exception& e) { + LOG(ERROR) << "Fail to parse graph meta: " << e.what(); + return seastar::make_exception_future( + gs::Status( + gs::StatusCode::InternalError, + "Fail to parse graph meta: " + std::string(e.what()))); + } } else { LOG(ERROR) << "Fail to get all procedures: " << get_all_procedure_res.status().error_message(); @@ -1222,9 +1253,8 @@ seastar::future admin_actor::list_jobs( auto list_res = metadata_store_->GetAllJobMeta(); if (list_res.ok()) { VLOG(10) << "Successfully list jobs"; - auto list_job_metas_str = to_json_str(list_res.value()); return seastar::make_ready_future( - gs::Result(std::move(list_job_metas_str))); + to_json_str(list_res.value())); } else { LOG(ERROR) << "Fail to list jobs: " << list_res.status().error_message(); return seastar::make_ready_future(list_res.status()); diff --git a/flex/storages/metadata/default_graph_meta_store.cc b/flex/storages/metadata/default_graph_meta_store.cc index b2e2397945e5..73a8c6bf886e 100644 --- a/flex/storages/metadata/default_graph_meta_store.cc +++ b/flex/storages/metadata/default_graph_meta_store.cc @@ -81,8 +81,9 @@ Result DefaultGraphMetaStore::UpdateGraphMeta( json = nlohmann::json::parse(old_meta); } catch (const std::exception& e) { LOG(ERROR) << "Fail to parse old graph meta:" << e.what(); - return Result(Status(StatusCode::InternalError, - "Fail to parse old graph meta")); + return Result( + Status(StatusCode::InternalError, + std::string("Fail to parse old graph meta: ") + e.what())); } auto graph_meta = GraphMeta::FromJson(json); if (request.graph_name.has_value()) { @@ -197,8 +198,9 @@ Result DefaultGraphMetaStore::UpdatePluginMeta( json = nlohmann::json::parse(old_meta); } catch (const std::exception& e) { LOG(ERROR) << "Fail to parse old plugin meta:" << e.what(); - return Result(Status(StatusCode::InternalError, - "Fail to parse old plugin meta")); + return Result(Status( + StatusCode::InternalError, + std::string("Fail to parse old plugin meta: ") + e.what())); } auto plugin_meta = PluginMeta::FromJson(json); if (plugin_meta.bound_graph != graph_id) { @@ -288,7 +290,8 @@ Result DefaultGraphMetaStore::UpdateJobMeta( } catch (const std::exception& e) { LOG(ERROR) << "Fail to parse old job meta:" << e.what(); return Result( - Status(StatusCode::InternalError, "Fail to parse old job meta")); + Status(StatusCode::InternalError, + std::string("Fail to parse old job meta: ") + e.what())); } auto job_meta = JobMeta::FromJson(json); if (update_request.status.has_value()) { diff --git a/flex/storages/metadata/graph_meta_store.cc b/flex/storages/metadata/graph_meta_store.cc index 44801276ab91..74b1e25ec92a 100644 --- a/flex/storages/metadata/graph_meta_store.cc +++ b/flex/storages/metadata/graph_meta_store.cc @@ -65,21 +65,40 @@ std::string GraphMeta::ToJson() const { json["creation_time"] = creation_time; json["data_update_time"] = data_update_time; if (!data_import_config.empty()) { - json["data_import_config"] = nlohmann::json::parse(data_import_config); + try { + json["data_import_config"] = nlohmann::json::parse(data_import_config); + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid data_import_config: " << data_import_config << " " + << e.what(); + } + } + try { + json["schema"] = nlohmann::json::parse(schema); + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid schema: " << schema << " " << e.what(); } - json["schema"] = nlohmann::json::parse(schema); json["stored_procedures"] = nlohmann::json::array(); for (auto& plugin_meta : plugin_metas) { - json["stored_procedures"].push_back( - nlohmann::json::parse(plugin_meta.ToJson())); + try { + json["stored_procedures"].push_back( + nlohmann::json::parse(plugin_meta.ToJson())); + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid plugin_meta: " << plugin_meta.ToJson() << " " + << e.what(); + } } json["store_type"] = store_type; return json.dump(); } GraphMeta GraphMeta::FromJson(const std::string& json_str) { - auto j = nlohmann::json::parse(json_str); - return GraphMeta::FromJson(j); + try { + auto j = nlohmann::json::parse(json_str); + return GraphMeta::FromJson(j); + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid json string: " << json_str << " " << e.what(); + return GraphMeta(); + } } GraphMeta GraphMeta::FromJson(const nlohmann::json& json) { @@ -119,8 +138,13 @@ GraphMeta GraphMeta::FromJson(const nlohmann::json& json) { } PluginMeta PluginMeta::FromJson(const std::string& json_str) { - auto j = nlohmann::json::parse(json_str); - return PluginMeta::FromJson(j); + try { + auto j = nlohmann::json::parse(json_str); + return PluginMeta::FromJson(j); + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid json string: " << json_str << " " << e.what(); + return PluginMeta(); + } } PluginMeta PluginMeta::FromJson(const nlohmann::json& json) { @@ -217,33 +241,46 @@ void PluginMeta::setParamsFromJsonString(const std::string& json_str) { json_str == "nu") { return; } - auto j = nlohmann::json::parse(json_str); - if (j.is_array()) { - for (auto& param : j) { - Parameter p; - p.name = param["name"].get(); - p.type = param["type"].get(); - params.push_back(p); + try { + auto j = nlohmann::json::parse(json_str); + if (j.is_array()) { + for (auto& param : j) { + Parameter p; + p.name = param["name"].get(); + p.type = param["type"].get(); + params.push_back(p); + } + } else { + LOG(ERROR) << "Invalid params string: " << json_str; } - } else { - LOG(ERROR) << "Invalid params string: " << json_str; + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid params string: " << json_str << " " << e.what(); } } void PluginMeta::setReturnsFromJsonString(const std::string& json_str) { - auto j = nlohmann::json::parse(json_str); - for (auto& ret : j) { - Parameter p; - p.name = ret["name"].get(); - p.type = ret["type"].get(); - returns.push_back(p); + try { + auto j = nlohmann::json::parse(json_str); + for (auto& ret : j) { + Parameter p; + p.name = ret["name"].get(); + p.type = ret["type"].get(); + returns.push_back(p); + } + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid returns string: " << json_str << " " << e.what(); } } void PluginMeta::setOptionFromJsonString(const std::string& json_str) { - auto j = nlohmann::json::parse(json_str); - for (auto& opt : j.items()) { - option[opt.key()] = opt.value().get(); + try { + auto j = nlohmann::json::parse(json_str); + for (auto& opt : j.items()) { + option[opt.key()] = opt.value().get(); + } + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid option string: " << json_str; + return; } } @@ -265,8 +302,14 @@ std::string JobMeta::ToJson(bool print_log) const { } JobMeta JobMeta::FromJson(const std::string& json_str) { - auto j = nlohmann::json::parse(json_str); - return JobMeta::FromJson(j); + try { + auto j = nlohmann::json::parse(json_str); + return JobMeta::FromJson(j); + } catch (const std::exception& e) { + LOG(ERROR) << "Fail to parse JobMeta from json: " << json_str << " " + << e.what(); + return JobMeta(); + } } JobMeta JobMeta::FromJson(const nlohmann::json& json) { @@ -354,7 +397,11 @@ std::string CreateGraphMetaRequest::ToString() const { nlohmann::json json; json["name"] = name; json["description"] = description; - json["schema"] = nlohmann::json::parse(schema); + try { + json["schema"] = nlohmann::json::parse(schema); + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid schema: " << schema << " " << e.what(); + } if (data_update_time.has_value()) { json["data_update_time"] = data_update_time.value(); } else { @@ -363,8 +410,13 @@ std::string CreateGraphMetaRequest::ToString() const { json["creation_time"] = creation_time; json["stored_procedures"] = nlohmann::json::array(); for (auto& plugin_meta : plugin_metas) { - json["stored_procedures"].push_back( - nlohmann::json::parse(plugin_meta.ToJson())); + try { + json["stored_procedures"].push_back( + nlohmann::json::parse(plugin_meta.ToJson())); + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid plugin_meta: " << plugin_meta.ToJson() << " " + << e.what(); + } } return json.dump(); } @@ -438,8 +490,14 @@ std::string CreatePluginMetaRequest::ToString() const { CreatePluginMetaRequest CreatePluginMetaRequest::FromJson( const std::string& json) { - auto j = nlohmann::json::parse(json); - return CreatePluginMetaRequest::FromJson(j); + try { + auto j = nlohmann::json::parse(json); + return CreatePluginMetaRequest::FromJson(j); + } catch (const std::exception& e) { + LOG(ERROR) << "CreatePluginMetaRequest::FromJson error: " << json << ", " + << e.what(); + return CreatePluginMetaRequest(); + } } CreatePluginMetaRequest CreatePluginMetaRequest::FromJson( @@ -561,7 +619,8 @@ UpdatePluginMetaRequest UpdatePluginMetaRequest::FromJson( request.enable = j["enable"].get(); } } catch (const std::exception& e) { - LOG(ERROR) << "UpdatePluginMetaRequest::FromJson error: " << e.what(); + LOG(ERROR) << "UpdatePluginMetaRequest::FromJson error: " << e.what() << " " + << json; } return request; } @@ -741,8 +800,16 @@ std::string GraphStatistics::ToJson() const { } Result GraphStatistics::FromJson(const std::string& json_str) { - auto j = nlohmann::json::parse(json_str); - return GraphStatistics::FromJson(j); + try { + auto j = nlohmann::json::parse(json_str); + return GraphStatistics::FromJson(j); + } catch (const std::exception& e) { + LOG(ERROR) << "Invalid json string: " << json_str << " " << e.what(); + return Result(Status( + StatusCode::InternalError, + "Invalid json string when parsing graph statistics : " + json_str + + " " + e.what())); + } } Result GraphStatistics::FromJson(const nlohmann::json& json) {