From cb778972d1a428a8ecbc4be163887a2d5359f94c Mon Sep 17 00:00:00 2001 From: Iain Anderson Date: Wed, 30 Sep 2020 17:59:57 +0100 Subject: [PATCH] feat: add v2 metrics endpoint update v2 ping and config endpoints to current spec Signed-off-by: Iain Anderson --- src/c/api.h | 1 + src/c/config.c | 19 +++++++++---------- src/c/device.c | 6 +++--- src/c/edgex-rest.c | 33 ++++++++++++++++++++++++++------- src/c/edgex-rest.h | 3 ++- src/c/edgex2.h | 14 +++++++++++++- src/c/metrics.c | 38 ++++++++++++++++++++++++++++++++++++++ src/c/metrics.h | 1 + src/c/rest-server.c | 1 + src/c/service.c | 8 ++++---- 10 files changed, 98 insertions(+), 26 deletions(-) diff --git a/src/c/api.h b/src/c/api.h index a474e07e2..b94183f33 100644 --- a/src/c/api.h +++ b/src/c/api.h @@ -23,6 +23,7 @@ #define EDGEX_DEV_API2_PING "/api/v2/ping" #define EDGEX_DEV_API2_CONFIG "/api/v2/config" +#define EDGEX_DEV_API2_METRICS "/api/v2/metrics" #define EDGEX_DEV_API2_DEVICE "/api/v2/device/{id}/{cmd}" #define EDGEX_DEV_API2_DEVICE_NAME "/api/v2/device/name/{name}/{cmd}" diff --git a/src/c/config.c b/src/c/config.c index 21e70d71f..74452b6ab 100644 --- a/src/c/config.c +++ b/src/c/config.c @@ -13,6 +13,7 @@ #include "service.h" #include "errorlist.h" #include "edgex-rest.h" +#include "correlation.h" #include "edgex-logging.h" #include "devutil.h" #include "autoevent.h" @@ -670,7 +671,7 @@ void edgex_device_freeConfig (devsdk_service_t *svc) edgex_map_deinit (&svc->config.watchers); } -static char *edgex_device_serialize_config (devsdk_service_t *svc) +static JSON_Value *edgex_device_config_toJson (devsdk_service_t *svc) { JSON_Value *val = json_value_init_object (); JSON_Object *obj = json_value_get_object (val); @@ -763,14 +764,15 @@ static char *edgex_device_serialize_config (devsdk_service_t *svc) json_object_set_value (obj, "Driver", dval); } - char *result = json_serialize_to_string (val); - json_value_free (val); - return result; + return val; } void edgex_device_handler_config (void *ctx, const devsdk_http_request *req, devsdk_http_reply *reply) { - char *json = edgex_device_serialize_config ((devsdk_service_t *)ctx); + JSON_Value *cval = edgex_device_config_toJson ((devsdk_service_t *)ctx); + + char *json = json_serialize_to_string (cval); + json_value_free (cval); reply->data.bytes = json; reply->data.size = strlen (json); reply->content_type = CONTENT_JSON; @@ -779,16 +781,13 @@ void edgex_device_handler_config (void *ctx, const devsdk_http_request *req, dev void edgex_device_handler_configv2 (void *ctx, const devsdk_http_request *req, devsdk_http_reply *reply) { - edgex_baserequest *br; edgex_configresponse *cr = malloc (sizeof (edgex_configresponse)); - br = edgex_baserequest_read (req->data); - edgex_baseresponse_populate ((edgex_baseresponse *)cr, br->requestId, MHD_HTTP_OK, NULL); - cr->config = edgex_device_serialize_config ((devsdk_service_t *)ctx); + edgex_baseresponse_populate ((edgex_baseresponse *)cr, "v2", edgex_device_get_crlid (), MHD_HTTP_OK, NULL); + cr->config = edgex_device_config_toJson ((devsdk_service_t *)ctx); edgex_configresponse_write (cr, reply); edgex_configresponse_free (cr); - edgex_baserequest_free (br); } void edgex_device_process_configured_devices diff --git a/src/c/device.c b/src/c/device.c index 63e89ae9e..4c3343a40 100644 --- a/src/c/device.c +++ b/src/c/device.c @@ -1063,7 +1063,7 @@ static void edgex_device_runput2 (devsdk_service_t *svc, edgex_device *dev, cons if (svc->userfns.puthandler (svc->userdata, dev->name, dev->protocols, cmdinfo->nreqs, cmdinfo->reqs, (const iot_data_t **)results, &e)) { edgex_baseresponse br; - edgex_baseresponse_populate (&br, "", MHD_HTTP_OK, "Data written successfully"); + edgex_baseresponse_populate (&br, "v2", "", MHD_HTTP_OK, "Data written successfully"); edgex_baseresponse_write (&br, reply); if (svc->config.device.updatelastconnected) { @@ -1186,7 +1186,7 @@ static void edgex_device_v2impl (devsdk_service_t *svc, edgex_device *dev, const else { edgex_data_client_add_event (svc, event); - edgex_baseresponse_populate (&br, "", MHD_HTTP_OK, "Event generated successfully"); + edgex_baseresponse_populate (&br, "v2", "", MHD_HTTP_OK, "Event generated successfully"); edgex_baseresponse_write (&br, reply); } } @@ -1199,7 +1199,7 @@ static void edgex_device_v2impl (devsdk_service_t *svc, edgex_device *dev, const else { edgex_event_cooked_free (event); - edgex_baseresponse_populate (&br, "", MHD_HTTP_OK, "Reading performed successfully"); + edgex_baseresponse_populate (&br, "v2", "", MHD_HTTP_OK, "Reading performed successfully"); edgex_baseresponse_write (&br, reply); } } diff --git a/src/c/edgex-rest.c b/src/c/edgex-rest.c index bab1d75c7..713ed1f4c 100644 --- a/src/c/edgex-rest.c +++ b/src/c/edgex-rest.c @@ -1827,8 +1827,9 @@ void edgex_baserequest_free (edgex_baserequest *e) } -void edgex_baseresponse_populate (edgex_baseresponse *e, const char *reqId, int code, const char *msg) +void edgex_baseresponse_populate (edgex_baseresponse *e, const char *version, const char *reqId, int code, const char *msg) { + e->apiVersion = version; e->requestId = reqId; e->statusCode = code; e->message = msg; @@ -1848,6 +1849,7 @@ static JSON_Value *baseresponse_write (const edgex_baseresponse *br) { JSON_Value *result = json_value_init_object (); JSON_Object *obj = json_value_get_object (result); + json_object_set_string (obj, "apiVersion", br->apiVersion); json_object_set_string (obj, "requestId", br->requestId); json_object_set_uint (obj, "statusCode", br->statusCode); if (br->message) @@ -1911,7 +1913,7 @@ static JSON_Value *configresponse_write (const edgex_configresponse *cr) { JSON_Value *result = baseresponse_write ((const edgex_baseresponse *)cr); JSON_Object *obj = json_value_get_object (result); - json_object_set_string (obj, "config", cr->config); + json_object_set_value (obj, "config", cr->config); return result; } @@ -1923,11 +1925,28 @@ void edgex_configresponse_write (const edgex_configresponse *cr, devsdk_http_rep void edgex_configresponse_free (edgex_configresponse *cr) { - if (cr) - { - free (cr->config); - free (cr); - } + free (cr); +} + +static JSON_Value *metricsesponse_write (const edgex_metricsresponse *mr) +{ + JSON_Value *result = baseresponse_write ((const edgex_baseresponse *)mr); + JSON_Object *obj = json_value_get_object (result); +#ifdef __GNU_LIBRARY__ + json_object_set_uint (obj, "Alloc", mr->alloc); + json_object_set_uint (obj, "TotalAlloc", mr->totalloc); + json_object_set_number (obj, "CpuLoadAvg", mr->loadavg); +#endif + json_object_set_number (obj, "CpuTime", mr->cputime); + json_object_set_number (obj, "CpuAvgUsage", mr->cpuavg); + + return result; +} + +void edgex_metricsresponse_write (const edgex_metricsresponse *mr, devsdk_http_reply *reply) +{ + JSON_Value *val = metricsesponse_write (mr); + value_write (val, reply); } #ifdef EDGEX_DEBUG_DUMP diff --git a/src/c/edgex-rest.h b/src/c/edgex-rest.h index d9d277a69..1c78a2f62 100644 --- a/src/c/edgex-rest.h +++ b/src/c/edgex-rest.h @@ -57,7 +57,7 @@ void edgex_watcher_free (edgex_watcher *e); edgex_baserequest *edgex_baserequest_read (devsdk_http_data d); void edgex_baserequest_free (edgex_baserequest *e); -void edgex_baseresponse_populate (edgex_baseresponse *e, const char *reqId, int code, const char *msg); +void edgex_baseresponse_populate (edgex_baseresponse *e, const char *version, const char *reqId, int code, const char *msg); edgex_errorresponse *edgex_errorresponse_create (uint64_t code, char *msg); void edgex_errorresponse_write (const edgex_errorresponse *er, devsdk_http_reply *reply); @@ -67,6 +67,7 @@ void edgex_baseresponse_write (const edgex_baseresponse *br, devsdk_http_reply * void edgex_pingresponse_write (const edgex_pingresponse *pr, devsdk_http_reply *reply); void edgex_configresponse_write (const edgex_configresponse *cr, devsdk_http_reply *reply); void edgex_configresponse_free (edgex_configresponse *cr); +void edgex_metricsresponse_write (const edgex_metricsresponse *mr, devsdk_http_reply *reply); #ifdef EDGEX_DEBUG_DUMP diff --git a/src/c/edgex2.h b/src/c/edgex2.h index abdad15b0..779dc414a 100644 --- a/src/c/edgex2.h +++ b/src/c/edgex2.h @@ -10,6 +10,7 @@ #define _EDGEX_EDGEX2_H_ #include "edgex/edgex-base.h" +#include "parson.h" /* Definitions of Data Transfer Objects for v2 REST API */ @@ -20,6 +21,7 @@ typedef struct typedef struct { + const char *apiVersion; const char *requestId; uint64_t statusCode; const char *message; @@ -36,7 +38,17 @@ typedef struct typedef struct { edgex_baseresponse base; - char *config; + JSON_Value *config; } edgex_configresponse; +typedef struct +{ + edgex_baseresponse base; + int alloc; + int totalloc; + double loadavg; + double cputime; + double cpuavg; +} edgex_metricsresponse; + #endif diff --git a/src/c/metrics.c b/src/c/metrics.c index 3d5496180..f06fb24fe 100644 --- a/src/c/metrics.c +++ b/src/c/metrics.c @@ -7,9 +7,12 @@ */ #include "metrics.h" +#include "edgex2.h" +#include "edgex-rest.h" #include "parson.h" #include "service.h" #include "iot/time.h" +#include "correlation.h" #include #include @@ -64,3 +67,38 @@ void edgex_device_handler_metrics (void *ctx, const devsdk_http_request *req, de reply->content_type = CONTENT_JSON; reply->code = MHD_HTTP_OK; } + +static void edgex_metrics_populate (edgex_metricsresponse *m, uint64_t starttime) +{ + struct rusage rstats; +#ifdef __GNU_LIBRARY__ + double loads[1]; + struct mallinfo mi = mallinfo (); + m->alloc = mi.uordblks; + m->totalloc = mi.arena + mi.hblkhd; + if (getloadavg (loads, 1) == 1) + { + m->loadavg = loads[0] * 100.0 / get_nprocs(); + } +#endif + if (getrusage (RUSAGE_SELF, &rstats) == 0) + { + double walltime = (double)(iot_time_msecs() - starttime) / 1e3; + double cputime = rstats.ru_utime.tv_sec + rstats.ru_stime.tv_sec; + cputime += (double)(rstats.ru_utime.tv_usec + rstats.ru_stime.tv_usec) / 1e6; + m->cputime = cputime; + m->cpuavg = cputime / walltime; + } +} + +void edgex_device_handler_metricsv2 (void *ctx, const devsdk_http_request *req, devsdk_http_reply *reply) +{ + devsdk_service_t *svc = (devsdk_service_t *)ctx; + edgex_metricsresponse mr; + memset (&mr, 0, sizeof (mr)); + + edgex_baseresponse_populate ((edgex_baseresponse *)&mr, "v2", edgex_device_get_crlid (), MHD_HTTP_OK, NULL); + edgex_metrics_populate (&mr, svc->starttime); + + edgex_metricsresponse_write (&mr, reply); +} diff --git a/src/c/metrics.h b/src/c/metrics.h index a8ae76000..1416f9003 100644 --- a/src/c/metrics.h +++ b/src/c/metrics.h @@ -14,5 +14,6 @@ #include extern void edgex_device_handler_metrics (void *ctx, const devsdk_http_request *req, devsdk_http_reply *reply); +extern void edgex_device_handler_metricsv2 (void *ctx, const devsdk_http_request *req, devsdk_http_reply *reply); #endif diff --git a/src/c/rest-server.c b/src/c/rest-server.c index f3316fd7d..f6a3f5c3f 100644 --- a/src/c/rest-server.c +++ b/src/c/rest-server.c @@ -271,6 +271,7 @@ static int http_handler } response = MHD_create_response_from_buffer (reply_size, reply, MHD_RESPMEM_MUST_FREE); MHD_add_response_header (response, "Content-Type", reply_type); + MHD_add_response_header (response, "X-Correlation-ID", edgex_device_get_crlid ()); MHD_queue_response (conn, status, response); MHD_destroy_response (response); diff --git a/src/c/service.c b/src/c/service.c index 824ed1e47..0d257852e 100644 --- a/src/c/service.c +++ b/src/c/service.c @@ -13,6 +13,7 @@ #include "discovery.h" #include "callback.h" #include "metrics.h" +#include "correlation.h" #include "errorlist.h" #include "rest-server.h" #include "profiles.h" @@ -272,14 +273,11 @@ static void ping_handler (void *ctx, const devsdk_http_request *req, devsdk_http static void ping2_handler (void *ctx, const devsdk_http_request *req, devsdk_http_reply *reply) { - edgex_baserequest *br; edgex_pingresponse pr; - br = edgex_baserequest_read (req->data); - edgex_baseresponse_populate ((edgex_baseresponse *)&pr, br->requestId, MHD_HTTP_OK, NULL); + edgex_baseresponse_populate ((edgex_baseresponse *)&pr, "v2", edgex_device_get_crlid (), MHD_HTTP_OK, NULL); pr.timestamp = iot_time_secs (); edgex_pingresponse_write (&pr, reply); - edgex_baserequest_free (br); } static void version_handler (void *ctx, const devsdk_http_request *req, devsdk_http_reply *reply) @@ -559,6 +557,8 @@ static void startConfigured (devsdk_service_t *svc, toml_table_t *config, devsdk svc->daemon, EDGEX_DEV_API_METRICS, DevSDK_Get, svc, edgex_device_handler_metrics ); + edgex_rest_server_register_handler (svc->daemon, EDGEX_DEV_API2_METRICS, DevSDK_Get, svc, edgex_device_handler_metricsv2); + edgex_rest_server_register_handler ( svc->daemon, EDGEX_DEV_API_CONFIG, DevSDK_Get, svc, edgex_device_handler_config