Merge "Adding the collectd API" from Amnon

"V2 Change how the information is gothered from the CPUs.  As a result of the
change, each function call in the parallel_for_each holds its own copy of the
ID, following that the get_collectd_value method was changed to get a const
reference, to prevent the redundant creation of a shared_ptr from the local
copy.

This series adds an API for the collectd. After applying the series the
collectd will be available from the API."
This commit is contained in:
Avi Kivity
2015-06-29 11:21:40 +03:00
7 changed files with 218 additions and 5 deletions

118
api/api-doc/collectd.json Normal file
View File

@@ -0,0 +1,118 @@
{
"apiVersion":"0.0.1",
"swaggerVersion":"1.2",
"basePath":"{{Protocol}}://{{Host}}",
"resourcePath":"/collectd",
"produces":[
"application/json"
],
"apis":[
{
"path":"/collectd/{pluginid}",
"operations":[
{
"method":"GET",
"summary":"Get a collectd value",
"type":"array",
"items":{
"type":"collectd_value"
},
"nickname":"get_collectd",
"produces":[
"application/json"
],
"parameters":[
{
"name":"pluginid",
"description":"The plugin ID",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"path"
},
{
"name":"instance",
"description":"The plugin instance",
"required":false,
"allowMultiple":false,
"type":"string",
"paramType":"query"
},
{
"name":"type",
"description":"The plugin type",
"required":true,
"allowMultiple":false,
"type":"string",
"paramType":"query"
},
{
"name":"type_instance",
"description":"The plugin type instance",
"required":false,
"allowMultiple":false,
"type":"string",
"paramType":"query"
}
]
}
]
},
{
"path":"/collectd/",
"operations":[
{
"method":"GET",
"summary":"Get a collectd value",
"type":"array",
"items":{
"type":"type_instance_id"
},
"nickname":"get_collectd_items",
"produces":[
"application/json"
],
"parameters":[
]
}
]
}
],
"models":{
"type_instance_id":{
"id":"type_instance_id",
"description":"A type instance ID",
"properties":{
"plugin":{
"type":"string",
"description":"The plugin ID"
},
"plugin_instance":{
"type":"string",
"description":"The plugin instance"
},
"type":{
"type":"string",
"description":"The plugin type"
},
"type_instance":{
"type":"string",
"description":"The plugin type instance"
}
}
},
"collectd_value":{
"id":"collectd_value",
"description":"Holds a collectd value",
"properties":{
"values":{
"description":"An array of values",
"type":"array",
"items":{
"type":"double"
}
}
}
}
}
}

View File

@@ -14,7 +14,7 @@
#include "messaging_service.hh"
#include "storage_proxy.hh"
#include "cache_service.hh"
#include "collectd.hh"
namespace api {
future<> set_server(http_context& ctx) {
@@ -52,7 +52,9 @@ future<> set_server(http_context& ctx) {
rb->register_function(r, "cache_service",
"The cache service API");
set_cache_service(ctx,r);
rb->register_function(r, "collectd",
"The collectd API");
set_collectd(ctx, r);
});
}

73
api/collectd.cc Normal file
View File

@@ -0,0 +1,73 @@
/*
* Copyright 2015 Cloudius Systems
*/
#include "collectd.hh"
#include "api/api-doc/collectd.json.hh"
#include "core/scollectd.hh"
#include "core/scollectd_api.hh"
#include "endian.h"
#include <boost/range/irange.hpp>
namespace api {
using namespace scollectd;
namespace cd = httpd::collectd_json;
static auto transformer(const std::vector<collectd_value>& values) {
cd::collectd_value collected_value;
for (auto v: values) {
switch (v._type) {
case scollectd::data_type::GAUGE:
collected_value.values.push(v.u._d);
break;
case scollectd::data_type::DERIVE:
collected_value.values.push(v.u._i);
break;
default:
collected_value.values.push(v.u._ui);
break;
}
}
return collected_value;
}
void set_collectd(http_context& ctx, routes& r) {
cd::get_collectd.set(r, [&ctx](std::unique_ptr<request> req) {
auto id = make_shared<scollectd::type_instance_id>(req->param["pluginid"],
req->get_query_param("instance"), req->get_query_param("type"),
req->get_query_param("type_instance"));
return do_with(std::vector<cd::collectd_value>(), [id] (auto& vec) {
vec.resize(smp::count);
return parallel_for_each(boost::irange(0u, smp::count), [&vec, id] (auto cpu) {
return smp::submit_to(cpu, [id = *id] {
return scollectd::get_collectd_value(id);
}).then([&vec, cpu] (auto res) {
vec[cpu] = transformer(res);
});
}).then([&vec] {
return make_ready_future<json::json_return_type>(vec);
});
});
});
cd::get_collectd_items.set(r, [](const_req req) {
std::vector<cd::type_instance_id> res;
auto ids = scollectd::get_collectd_ids();
for (auto i: ids) {
cd::type_instance_id id;
id.plugin = i.plugin();
id.plugin_instance = i.plugin_instance();
id.type = i.type();
id.type_instance = i.type_instance();
res.push_back(id);
}
return res;
});
}
}

18
api/collectd.hh Normal file
View File

@@ -0,0 +1,18 @@
/*
* Copyright 2015 Cloudius Systems
*/
#ifndef API_COLLECTD_HH_
#define API_COLLECTD_HH_
#include "api.hh"
namespace api {
void set_collectd(http_context& ctx, routes& r);
}
#endif /* API_COLLECTD_HH_ */

View File

@@ -335,6 +335,8 @@ api = ['api/api.cc',
'api/storage_proxy.cc',
'api/api-doc/cache_service.json',
'api/cache_service.cc',
'api/api-doc/collectd.json',
'api/collectd.cc',
]
boost_test_lib = [

View File

@@ -488,9 +488,9 @@ boost::program_options::options_description get_options_description() {
}
std::vector<collectd_value> get_collectd_value(
shared_ptr<scollectd::type_instance_id> id) {
const scollectd::type_instance_id& id) {
std::vector<collectd_value> res_values;
auto raw_types = get_impl().get_values(*id);
auto raw_types = get_impl().get_values(id);
if (raw_types == nullptr) {
return res_values;
}

View File

@@ -49,7 +49,7 @@ struct collectd_value {
};
std::vector<collectd_value> get_collectd_value(
shared_ptr<scollectd::type_instance_id> id);
const scollectd::type_instance_id& id);
std::vector<scollectd::type_instance_id> get_collectd_ids();