diff --git a/include/maxscale/json_api.h b/include/maxscale/json_api.h index ade092302..8ba70d333 100644 --- a/include/maxscale/json_api.h +++ b/include/maxscale/json_api.h @@ -34,6 +34,7 @@ MXS_BEGIN_DECLS #define MXS_JSON_API_LOGS "/maxscale/logs/" #define MXS_JSON_API_TASKS "/maxscale/tasks/" #define MXS_JSON_API_MODULES "/maxscale/modules/" +#define MXS_JSON_API_QC_STATS "/maxscale/qc_stats/" #define MXS_JSON_API_USERS "/users/" /** diff --git a/server/core/internal/routingworker.hh b/server/core/internal/routingworker.hh index 143f2964c..36e376b39 100644 --- a/server/core/internal/routingworker.hh +++ b/server/core/internal/routingworker.hh @@ -355,12 +355,37 @@ public: } } + /** + * Provides QC statistics of one workers + * + * @param id[in] Id of worker. + * @param pStats[out] The QC statistics of that worker. + * + * return True, if @c id referred to a worker, false otherwise. + */ + static bool get_qc_stats(int id, QC_CACHE_STATS* pStats); + /** * Provides QC statistics of all workers * * @param all_stats Vector that on return will contain the statistics of all workers. */ - static void get_all_qc_stats(std::vector& all_stats); + static void get_qc_stats(std::vector& all_stats); + + /** + * Provides QC statistics of all workers as a Json object for use in the REST-API. + */ + static std::unique_ptr get_qc_stats_as_json(const char* zHost); + + /** + * Provides QC statistics of one worker as a Json object for use in the REST-API. + * + * @param zHost The name of the MaxScale host. + * @param id An id of a worker. + * + * @return A json object if @c id refers to a worker, NULL otherwise. + */ + static std::unique_ptr get_qc_stats_as_json(const char* zHost, int id); private: const int m_id; /*< The id of the worker. */ diff --git a/server/core/routingworker.cc b/server/core/routingworker.cc index 37c70719d..ed4722cfd 100644 --- a/server/core/routingworker.cc +++ b/server/core/routingworker.cc @@ -869,7 +869,40 @@ int64_t RoutingWorker::get_one_statistic(POLL_STAT what) } //static -void RoutingWorker::get_all_qc_stats(std::vector& all_stats) +bool RoutingWorker::get_qc_stats(int id, QC_CACHE_STATS* pStats) +{ + class Task : public mxs::Worker::Task + { + public: + Task(QC_CACHE_STATS* pStats) + : m_stats(*pStats) + { + } + + void execute(mxs::Worker&) + { + qc_get_cache_stats(&m_stats); + } + + private: + QC_CACHE_STATS& m_stats; + }; + + RoutingWorker* pWorker = RoutingWorker::get(id); + + if (pWorker) + { + Semaphore sem; + Task task(pStats); + pWorker->post(&task, &sem); + sem.wait(); + } + + return pWorker != nullptr; +} + +//static +void RoutingWorker::get_qc_stats(std::vector& all_stats) { class Task : public mxs::Worker::Task { @@ -898,6 +931,75 @@ void RoutingWorker::get_all_qc_stats(std::vector& all_stats) mxs::RoutingWorker::execute_concurrently(task); } +namespace +{ + +json_t* qc_stats_to_json(const char* zHost, int id, const QC_CACHE_STATS& stats) +{ + json_t* pStats = json_object(); + json_object_set_new(pStats, "size", json_integer(stats.size)); + json_object_set_new(pStats, "inserts", json_integer(stats.inserts)); + json_object_set_new(pStats, "hits", json_integer(stats.hits)); + json_object_set_new(pStats, "misses", json_integer(stats.misses)); + json_object_set_new(pStats, "evictions", json_integer(stats.evictions)); + + json_t* pAttributes = json_object(); + json_object_set_new(pAttributes, "stats", pStats); + + json_t* pSelf = mxs_json_self_link(zHost, "qc_stats", std::to_string(id).c_str()); + + json_t* pJson = json_object(); + json_object_set_new(pJson, CN_ID, json_string(std::to_string(id).c_str())); + json_object_set_new(pJson, CN_TYPE, json_string("qc_stats")); + json_object_set_new(pJson, CN_ATTRIBUTES, pAttributes); + json_object_set_new(pJson, CN_LINKS, pSelf); + + return pJson; +} + +} + +//static +std::unique_ptr RoutingWorker::get_qc_stats_as_json(const char* zHost, int id) +{ + std::unique_ptr sStats; + + QC_CACHE_STATS stats; + + if (get_qc_stats(id, &stats)) + { + json_t* pJson = qc_stats_to_json(zHost, id, stats); + + stringstream self; + self << MXS_JSON_API_QC_STATS << id; + + sStats = std::unique_ptr(mxs_json_resource(zHost, self.str().c_str(), pJson)); + } + + return sStats; +} + +//static +std::unique_ptr RoutingWorker::get_qc_stats_as_json(const char* zHost) +{ + vector all_stats; + + get_qc_stats(all_stats); + + std::unique_ptr sAll_stats(json_array()); + + int id = 0; + for (const auto& stats : all_stats) + { + json_t* pJson = qc_stats_to_json(zHost, id, stats); + + json_array_append_new(sAll_stats.get(), pJson); + ++id; + } + + return std::unique_ptr(mxs_json_resource(zHost, MXS_JSON_API_QC_STATS, sAll_stats.release())); +} + } size_t mxs_rworker_broadcast_message(uint32_t msg_id, intptr_t arg1, intptr_t arg2) diff --git a/server/modules/routing/debugcli/debugcmd.cc b/server/modules/routing/debugcli/debugcmd.cc index 7d3fd10e5..237429a4b 100644 --- a/server/modules/routing/debugcli/debugcmd.cc +++ b/server/modules/routing/debugcli/debugcmd.cc @@ -2436,7 +2436,7 @@ show_qc_all(DCB* dcb) { std::vector all_stats; - mxs::RoutingWorker::get_all_qc_stats(all_stats); + mxs::RoutingWorker::get_qc_stats(all_stats); dcb_printf(dcb, " ID | Size | Inserts | Hits | Misses | Evictions |\n"); dcb_printf(dcb, "----+------------+------------+------------+------------+------------+\n");