aboutsummaryrefslogtreecommitdiffstats
path: root/vnfs/VES/code/evel_library/evel_scaling_measurement.c
diff options
context:
space:
mode:
Diffstat (limited to 'vnfs/VES/code/evel_library/evel_scaling_measurement.c')
-rw-r--r--vnfs/VES/code/evel_library/evel_scaling_measurement.c1711
1 files changed, 1711 insertions, 0 deletions
diff --git a/vnfs/VES/code/evel_library/evel_scaling_measurement.c b/vnfs/VES/code/evel_library/evel_scaling_measurement.c
new file mode 100644
index 00000000..ec8f32a4
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_scaling_measurement.c
@@ -0,0 +1,1711 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Measurement.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Measurement event.
+ *
+ * @note The mandatory fields on the Measurement must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Measurement has immutable properties.
+ *
+ * @param measurement_interval
+ *
+ * @returns pointer to the newly manufactured ::EVENT_MEASUREMENT. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MEASUREMENT * evel_new_measurement(double measurement_interval)
+{
+ EVENT_MEASUREMENT * measurement = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement_interval >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate the measurement. */
+ /***************************************************************************/
+ measurement = malloc(sizeof(EVENT_MEASUREMENT));
+ if (measurement == NULL)
+ {
+ log_error_state("Out of memory for Measurement");
+ goto exit_label;
+ }
+ memset(measurement, 0, sizeof(EVENT_MEASUREMENT));
+ EVEL_DEBUG("New measurement is at %lp", measurement);
+
+ /***************************************************************************/
+ /* Initialize the header & the measurement fields. */
+ /***************************************************************************/
+ evel_init_header(&measurement->header);
+ measurement->header.event_domain = EVEL_DOMAIN_MEASUREMENT;
+ measurement->measurement_interval = measurement_interval;
+ dlist_initialize(&measurement->cpu_usage);
+ dlist_initialize(&measurement->filesystem_usage);
+ dlist_initialize(&measurement->latency_distribution);
+ dlist_initialize(&measurement->vnic_usage);
+ dlist_initialize(&measurement->codec_usage);
+ dlist_initialize(&measurement->feature_usage);
+ dlist_initialize(&measurement->additional_measurements);
+ evel_init_option_double(&measurement->aggregate_cpu_usage);
+ evel_init_option_double(&measurement->mean_request_latency);
+ evel_init_option_double(&measurement->memory_configured);
+ evel_init_option_double(&measurement->memory_used);
+ evel_init_option_double(&measurement->vnfc_scaling_metric);
+ evel_init_option_int(&measurement->concurrent_sessions);
+ evel_init_option_int(&measurement->configured_entities);
+ evel_init_option_int(&measurement->media_ports_in_use);
+ evel_init_option_int(&measurement->request_rate);
+ measurement->major_version = EVEL_MEASUREMENT_MAJOR_VERSION;
+ measurement->minor_version = EVEL_MEASUREMENT_MINOR_VERSION;
+
+exit_label:
+ EVEL_EXIT();
+ return measurement;
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_measurement_type_set(EVENT_MEASUREMENT * measurement,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ evel_header_type_set(&measurement->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Concurrent Sessions property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param concurrent_sessions The Concurrent Sessions to be set.
+ *****************************************************************************/
+void evel_measurement_conc_sess_set(EVENT_MEASUREMENT * measurement,
+ int concurrent_sessions)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(concurrent_sessions >= 0);
+
+ evel_set_option_int(&measurement->concurrent_sessions,
+ concurrent_sessions,
+ "Concurrent Sessions");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Configured Entities property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param configured_entities The Configured Entities to be set.
+ *****************************************************************************/
+void evel_measurement_cfg_ents_set(EVENT_MEASUREMENT * measurement,
+ int configured_entities)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(configured_entities >= 0);
+
+ evel_set_option_int(&measurement->configured_entities,
+ configured_entities,
+ "Configured Entities");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional set of Errors to the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param receive_discards The number of receive discards.
+ * @param receive_errors The number of receive errors.
+ * @param transmit_discards The number of transmit discards.
+ * @param transmit_errors The number of transmit errors.
+ *****************************************************************************/
+void evel_measurement_errors_set(EVENT_MEASUREMENT * measurement,
+ int receive_discards,
+ int receive_errors,
+ int transmit_discards,
+ int transmit_errors)
+{
+ MEASUREMENT_ERRORS * errors = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(receive_discards >= 0);
+ assert(receive_errors >= 0);
+ assert(transmit_discards >= 0);
+ assert(transmit_errors >= 0);
+
+ if (measurement->errors == NULL)
+ {
+ EVEL_DEBUG("Adding Errors: %d, %d; %d, %d",
+ receive_discards,
+ receive_errors,
+ transmit_discards,
+ transmit_errors);
+ errors = malloc(sizeof(MEASUREMENT_ERRORS));
+ assert(errors != NULL);
+ memset(errors, 0, sizeof(MEASUREMENT_ERRORS));
+ errors->receive_discards = receive_discards;
+ errors->receive_errors = receive_errors;
+ errors->transmit_discards = transmit_discards;
+ errors->transmit_errors = transmit_errors;
+ measurement->errors = errors;
+ }
+ else
+ {
+ errors = measurement->errors;
+ EVEL_DEBUG("Ignoring attempt to add Errors: %d, %d; %d, %d\n"
+ "Errors already set: %d, %d; %d, %d",
+ receive_discards,
+ receive_errors,
+ transmit_discards,
+ transmit_errors,
+ errors->receive_discards,
+ errors->receive_errors,
+ errors->transmit_discards,
+ errors->transmit_errors);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Mean Request Latency property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param mean_request_latency The Mean Request Latency to be set.
+ *****************************************************************************/
+void evel_measurement_mean_req_lat_set(EVENT_MEASUREMENT * measurement,
+ double mean_request_latency)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(mean_request_latency >= 0.0);
+
+ evel_set_option_double(&measurement->mean_request_latency,
+ mean_request_latency,
+ "Mean Request Latency");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Memory Configured property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param memory_configured The Memory Configured to be set.
+ *****************************************************************************/
+void evel_measurement_mem_cfg_set(EVENT_MEASUREMENT * measurement,
+ double memory_configured)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(memory_configured >= 0.0);
+
+ evel_set_option_double(&measurement->memory_configured,
+ memory_configured,
+ "Memory Configured");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Memory Used property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param memory_used The Memory Used to be set.
+ *****************************************************************************/
+void evel_measurement_mem_used_set(EVENT_MEASUREMENT * measurement,
+ double memory_used)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(memory_used >= 0.0);
+
+ evel_set_option_double(&measurement->memory_used,
+ memory_used,
+ "Memory Used");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Request Rate property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param request_rate The Request Rate to be set.
+ *****************************************************************************/
+void evel_measurement_request_rate_set(EVENT_MEASUREMENT * measurement,
+ int request_rate)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(request_rate >= 0);
+
+ evel_set_option_int(&measurement->request_rate,
+ request_rate,
+ "Request Rate");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional CPU usage value name/value pair to the Measurement.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param id ASCIIZ string with the CPU's identifier.
+ * @param usage CPU utilization.
+ *****************************************************************************/
+void evel_measurement_cpu_use_add(EVENT_MEASUREMENT * measurement,
+ char * id, double usage)
+{
+ MEASUREMENT_CPU_USE * cpu_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(id != NULL);
+ assert(usage >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding id=%s usage=%lf", id, usage);
+ cpu_use = malloc(sizeof(MEASUREMENT_CPU_USE));
+ assert(cpu_use != NULL);
+ memset(cpu_use, 0, sizeof(MEASUREMENT_CPU_USE));
+ cpu_use->id = strdup(id);
+ cpu_use->usage = usage;
+ assert(cpu_use->id != NULL);
+
+ dlist_push_last(&measurement->cpu_usage, cpu_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional File System usage value name/value pair to the
+ * Measurement.
+ *
+ * The filesystem_name is null delimited ASCII string. The library takes a
+ * copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param filesystem_name ASCIIZ string with the file-system's UUID.
+ * @param block_configured Block storage configured.
+ * @param block_used Block storage in use.
+ * @param block_iops Block storage IOPS.
+ * @param ephemeral_configured Ephemeral storage configured.
+ * @param ephemeral_used Ephemeral storage in use.
+ * @param ephemeral_iops Ephemeral storage IOPS.
+ *****************************************************************************/
+void evel_measurement_fsys_use_add(EVENT_MEASUREMENT * measurement,
+ char * filesystem_name,
+ double block_configured,
+ double block_used,
+ int block_iops,
+ double ephemeral_configured,
+ double ephemeral_used,
+ int ephemeral_iops)
+{
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(filesystem_name != NULL);
+ assert(block_configured >= 0.0);
+ assert(block_used >= 0.0);
+ assert(block_iops >= 0);
+ assert(ephemeral_configured >= 0.0);
+ assert(ephemeral_used >= 0.0);
+ assert(ephemeral_iops >= 0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding filesystem_name=%s", filesystem_name);
+ fsys_use = malloc(sizeof(MEASUREMENT_FSYS_USE));
+ assert(fsys_use != NULL);
+ memset(fsys_use, 0, sizeof(MEASUREMENT_FSYS_USE));
+ fsys_use->filesystem_name = strdup(filesystem_name);
+ fsys_use->block_configured = block_configured;
+ fsys_use->block_used = block_used;
+ fsys_use->block_iops = block_iops;
+ fsys_use->ephemeral_configured = block_configured;
+ fsys_use->ephemeral_used = ephemeral_used;
+ fsys_use->ephemeral_iops = ephemeral_iops;
+
+ dlist_push_last(&measurement->filesystem_usage, fsys_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Feature usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param feature ASCIIZ string with the feature's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_measurement_feature_use_add(EVENT_MEASUREMENT * measurement,
+ char * feature,
+ int utilization)
+{
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(feature != NULL);
+ assert(utilization >= 0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Feature=%s Use=%d", feature, utilization);
+ feature_use = malloc(sizeof(MEASUREMENT_FEATURE_USE));
+ assert(feature_use != NULL);
+ memset(feature_use, 0, sizeof(MEASUREMENT_FEATURE_USE));
+ feature_use->feature_id = strdup(feature);
+ assert(feature_use->feature_id != NULL);
+ feature_use->feature_utilization = utilization;
+
+ dlist_push_last(&measurement->feature_usage, feature_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Additional Measurement value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the Measaurement.
+ * @param group ASCIIZ string with the measurement group's name.
+ * @param name ASCIIZ string containing the measurement's name.
+ * @param value ASCIIZ string containing the measurement's value.
+ *****************************************************************************/
+void evel_measurement_custom_measurement_add(EVENT_MEASUREMENT * measurement,
+ const char * const group,
+ const char * const name,
+ const char * const value)
+{
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * custom_measurement = NULL;
+ DLIST_ITEM * item = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(group != NULL);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ /***************************************************************************/
+ /* Allocate a container for the name/value pair. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Measurement Group=%s Name=%s Value=%s",
+ group, name, value);
+ custom_measurement = malloc(sizeof(CUSTOM_MEASUREMENT));
+ assert(custom_measurement != NULL);
+ memset(custom_measurement, 0, sizeof(CUSTOM_MEASUREMENT));
+ custom_measurement->name = strdup(name);
+ assert(custom_measurement->name != NULL);
+ custom_measurement->value = strdup(value);
+ assert(custom_measurement->value != NULL);
+
+ /***************************************************************************/
+ /* See if we have that group already. */
+ /***************************************************************************/
+ item = dlist_get_first(&measurement->additional_measurements);
+ while (item != NULL)
+ {
+ measurement_group = (MEASUREMENT_GROUP *) item->item;
+ assert(measurement_group != NULL);
+
+ EVEL_DEBUG("Got measurement group %s", measurement_group->name);
+ if (strcmp(group, measurement_group->name) == 0)
+ {
+ EVEL_DEBUG("Found existing Measurement Group");
+ break;
+ }
+ item = dlist_get_next(item);
+ }
+
+ /***************************************************************************/
+ /* If we didn't have the group already, create it. */
+ /***************************************************************************/
+ if (item == NULL)
+ {
+ EVEL_DEBUG("Creating new Measurement Group");
+ measurement_group = malloc(sizeof(MEASUREMENT_GROUP));
+ assert(measurement_group != NULL);
+ memset(measurement_group, 0, sizeof(MEASUREMENT_GROUP));
+ measurement_group->name = strdup(group);
+ assert(measurement_group->name != NULL);
+ dlist_initialize(&measurement_group->measurements);
+ dlist_push_last(&measurement->additional_measurements, measurement_group);
+ }
+
+ /***************************************************************************/
+ /* If we didn't have the group already, create it. */
+ /***************************************************************************/
+ dlist_push_last(&measurement_group->measurements, custom_measurement);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Codec usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param codec ASCIIZ string with the codec's name.
+ * @param utilization Number of codecs in use.
+ *****************************************************************************/
+void evel_measurement_codec_use_add(EVENT_MEASUREMENT * measurement,
+ char * codec,
+ int utilization)
+{
+ MEASUREMENT_CODEC_USE * codec_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(codec != NULL);
+ assert(utilization >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Codec=%s Use=%d", codec, utilization);
+ codec_use = malloc(sizeof(MEASUREMENT_CODEC_USE));
+ assert(codec_use != NULL);
+ memset(codec_use, 0, sizeof(MEASUREMENT_CODEC_USE));
+ codec_use->codec_id = strdup(codec);
+ assert(codec_use->codec_id != NULL);
+ codec_use->number_in_use = utilization;
+
+ dlist_push_last(&measurement->codec_usage, codec_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Aggregate CPU Use property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param cpu_use The CPU use to set.
+ *****************************************************************************/
+void evel_measurement_agg_cpu_use_set(EVENT_MEASUREMENT * measurement,
+ double cpu_use)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(cpu_use >= 0.0);
+
+ evel_set_option_double(&measurement->aggregate_cpu_usage,
+ cpu_use,
+ "CPU Use");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Media Ports in Use property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param media_ports_in_use The media port usage to set.
+ *****************************************************************************/
+void evel_measurement_media_port_use_set(EVENT_MEASUREMENT * measurement,
+ int media_ports_in_use)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(media_ports_in_use >= 0);
+
+ evel_set_option_int(&measurement->media_ports_in_use,
+ media_ports_in_use,
+ "Media Ports In Use");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the VNFC Scaling Metric property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param scaling_metric The scaling metric to set.
+ *****************************************************************************/
+void evel_measurement_vnfc_scaling_metric_set(EVENT_MEASUREMENT * measurement,
+ double scaling_metric)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(scaling_metric >= 0.0);
+
+ evel_set_option_double(&measurement->vnfc_scaling_metric,
+ scaling_metric,
+ "VNFC Scaling Metric");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Create a new Latency Bucket to be added to a Measurement event.
+ *
+ * @note The mandatory fields on the ::MEASUREMENT_LATENCY_BUCKET must be
+ * supplied to this factory function and are immutable once set.
+ * Optional fields have explicit setter functions, but again values
+ * may only be set once so that the ::MEASUREMENT_LATENCY_BUCKET has
+ * immutable properties.
+ *
+ * @param count Count of events in this bucket.
+ *
+ * @returns pointer to the newly manufactured ::MEASUREMENT_LATENCY_BUCKET.
+ * If the structure is not used it must be released using free.
+ * @retval NULL Failed to create the Latency Bucket.
+ *****************************************************************************/
+MEASUREMENT_LATENCY_BUCKET * evel_new_meas_latency_bucket(const int count)
+{
+ MEASUREMENT_LATENCY_BUCKET * bucket;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(count >= 0);
+
+ /***************************************************************************/
+ /* Allocate, then set Mandatory Parameters. */
+ /***************************************************************************/
+ EVEL_DEBUG("Creating bucket, count = %d", count);
+ bucket = malloc(sizeof(MEASUREMENT_LATENCY_BUCKET));
+ assert(bucket != NULL);
+
+ /***************************************************************************/
+ /* Set Mandatory Parameters. */
+ /***************************************************************************/
+ bucket->count = count;
+
+ /***************************************************************************/
+ /* Initialize Optional Parameters. */
+ /***************************************************************************/
+ evel_init_option_double(&bucket->high_end);
+ evel_init_option_double(&bucket->low_end);
+
+ EVEL_EXIT();
+
+ return bucket;
+}
+
+/**************************************************************************//**
+ * Set the High End property of the Measurement Latency Bucket.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param bucket Pointer to the Measurement Latency Bucket.
+ * @param high_end High end of the bucket's range.
+ *****************************************************************************/
+void evel_meas_latency_bucket_high_end_set(
+ MEASUREMENT_LATENCY_BUCKET * const bucket,
+ const double high_end)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(high_end >= 0.0);
+ evel_set_option_double(&bucket->high_end, high_end, "High End");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Low End property of the Measurement Latency Bucket.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param bucket Pointer to the Measurement Latency Bucket.
+ * @param low_end Low end of the bucket's range.
+ *****************************************************************************/
+void evel_meas_latency_bucket_low_end_set(
+ MEASUREMENT_LATENCY_BUCKET * const bucket,
+ const double low_end)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(low_end >= 0.0);
+ evel_set_option_double(&bucket->low_end, low_end, "Low End");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional Measurement Latency Bucket to the specified event.
+ *
+ * @param measurement Pointer to the Measurement event.
+ * @param bucket Pointer to the Measurement Latency Bucket to add.
+ *****************************************************************************/
+void evel_meas_latency_bucket_add(EVENT_MEASUREMENT * const measurement,
+ MEASUREMENT_LATENCY_BUCKET * const bucket)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(bucket != NULL);
+ dlist_push_last(&measurement->latency_distribution, bucket);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional Latency Distribution bucket to the Measurement.
+ *
+ * This function implements the previous API, purely for convenience.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param low_end Low end of the bucket's range.
+ * @param high_end High end of the bucket's range.
+ * @param count Count of events in this bucket.
+ *****************************************************************************/
+void evel_measurement_latency_add(EVENT_MEASUREMENT * const measurement,
+ const double low_end,
+ const double high_end,
+ const int count)
+{
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Trust the assertions in the underlying methods. */
+ /***************************************************************************/
+ bucket = evel_new_meas_latency_bucket(count);
+ evel_meas_latency_bucket_low_end_set(bucket, low_end);
+ evel_meas_latency_bucket_high_end_set(bucket, high_end);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Create a new vNIC Use to be added to a Measurement event.
+ *
+ * @note The mandatory fields on the ::MEASUREMENT_VNIC_USE must be supplied
+ * to this factory function and are immutable once set. Optional
+ * fields have explicit setter functions, but again values may only be
+ * set once so that the ::MEASUREMENT_VNIC_USE has immutable
+ * properties.
+ *
+ * @param vnic_id ASCIIZ string with the vNIC's ID.
+ * @param packets_in Total packets received.
+ * @param packets_out Total packets transmitted.
+ * @param bytes_in Total bytes received.
+ * @param bytes_out Total bytes transmitted.
+ *
+ * @returns pointer to the newly manufactured ::MEASUREMENT_VNIC_USE.
+ * If the structure is not used it must be released using
+ * ::evel_free_measurement_vnic_use.
+ * @retval NULL Failed to create the vNIC Use.
+ *****************************************************************************/
+MEASUREMENT_VNIC_USE * evel_new_measurement_vnic_use(char * const vnic_id,
+ const int packets_in,
+ const int packets_out,
+ const int bytes_in,
+ const int bytes_out)
+{
+ MEASUREMENT_VNIC_USE * vnic_use;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vnic_id != NULL);
+ assert(packets_in >= 0);
+ assert(packets_out >= 0);
+ assert(bytes_in >= 0);
+ assert(bytes_out >= 0);
+
+ /***************************************************************************/
+ /* Allocate, then set Mandatory Parameters. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding VNIC ID=%s", vnic_id);
+ vnic_use = malloc(sizeof(MEASUREMENT_VNIC_USE));
+ assert(vnic_use != NULL);
+ vnic_use->vnic_id = strdup(vnic_id);
+ vnic_use->packets_in = packets_in;
+ vnic_use->packets_out = packets_out;
+ vnic_use->bytes_in = bytes_in;
+ vnic_use->bytes_out = bytes_out;
+
+ /***************************************************************************/
+ /* Initialize Optional Parameters. */
+ /***************************************************************************/
+ evel_init_option_int(&vnic_use->broadcast_packets_in);
+ evel_init_option_int(&vnic_use->broadcast_packets_out);
+ evel_init_option_int(&vnic_use->multicast_packets_in);
+ evel_init_option_int(&vnic_use->multicast_packets_out);
+ evel_init_option_int(&vnic_use->unicast_packets_in);
+ evel_init_option_int(&vnic_use->unicast_packets_out);
+
+ EVEL_EXIT();
+
+ return vnic_use;
+}
+
+/**************************************************************************//**
+ * Free a vNIC Use.
+ *
+ * Free off the ::MEASUREMENT_VNIC_USE supplied. Will free all the contained
+ * allocated memory.
+ *
+ * @note It does not free the vNIC Use itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_measurement_vnic_use(MEASUREMENT_VNIC_USE * const vnic_use)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vnic_use != NULL);
+ assert(vnic_use->vnic_id != NULL);
+
+ /***************************************************************************/
+ /* Free the duplicated string. */
+ /***************************************************************************/
+ free(vnic_use->vnic_id);
+ vnic_use->vnic_id = NULL;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Broadcast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param broadcast_packets_in
+ * Broadcast packets received.
+ *****************************************************************************/
+void evel_vnic_use_bcast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int broadcast_packets_in)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(broadcast_packets_in >= 0);
+
+ evel_set_option_int(&vnic_use->broadcast_packets_in,
+ broadcast_packets_in,
+ "Broadcast Packets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Broadcast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param broadcast_packets_out
+ * Broadcast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_bcast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int broadcast_packets_out)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(broadcast_packets_out >= 0);
+
+ evel_set_option_int(&vnic_use->broadcast_packets_out,
+ broadcast_packets_out,
+ "Broadcast Packets Transmitted");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Multicast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param multicast_packets_in
+ * Multicast packets received.
+ *****************************************************************************/
+void evel_vnic_use_mcast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int multicast_packets_in)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(multicast_packets_in >= 0);
+
+ evel_set_option_int(&vnic_use->multicast_packets_in,
+ multicast_packets_in,
+ "Multicast Packets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Multicast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param multicast_packets_out
+ * Multicast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_mcast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int multicast_packets_out)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(multicast_packets_out >= 0);
+
+ evel_set_option_int(&vnic_use->multicast_packets_out,
+ multicast_packets_out,
+ "Multicast Packets Transmitted");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Unicast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param unicast_packets_in
+ * Unicast packets received.
+ *****************************************************************************/
+void evel_vnic_use_ucast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int unicast_packets_in)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(unicast_packets_in >= 0);
+
+ evel_set_option_int(&vnic_use->unicast_packets_in,
+ unicast_packets_in,
+ "Unicast Packets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Unicast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param unicast_packets_out
+ * Unicast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_ucast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int unicast_packets_out)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(unicast_packets_out >= 0);
+
+ evel_set_option_int(&vnic_use->unicast_packets_out,
+ unicast_packets_out,
+ "Unicast Packets Transmitted");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional vNIC Use to the specified Measurement event.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param vnic_use Pointer to the vNIC Use to add.
+ *****************************************************************************/
+void evel_meas_vnic_use_add(EVENT_MEASUREMENT * const measurement,
+ MEASUREMENT_VNIC_USE * const vnic_use)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(vnic_use != NULL);
+
+ dlist_push_last(&measurement->vnic_usage, vnic_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional vNIC usage record Measurement.
+ *
+ * This function implements the previous API, purely for convenience.
+ *
+ * The ID is null delimited ASCII string. The library takes a copy so the
+ * caller does not have to preserve values after the function returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param vnic_id ASCIIZ string with the vNIC's ID.
+ * @param packets_in Total packets received.
+ * @param packets_out Total packets transmitted.
+ * @param broadcast_packets_in Broadcast packets received.
+ * @param broadcast_packets_out Broadcast packets transmitted.
+ * @param bytes_in Total bytes received.
+ * @param bytes_out Total bytes transmitted.
+ * @param multicast_packets_in Multicast packets received.
+ * @param multicast_packets_out Multicast packets transmitted.
+ * @param unicast_packets_in Unicast packets received.
+ * @param unicast_packets_out Unicast packets transmitted.
+ *****************************************************************************/
+void evel_measurement_vnic_use_add(EVENT_MEASUREMENT * const measurement,
+ char * const vnic_id,
+ const int packets_in,
+ const int packets_out,
+ const int broadcast_packets_in,
+ const int broadcast_packets_out,
+ const int bytes_in,
+ const int bytes_out,
+ const int multicast_packets_in,
+ const int multicast_packets_out,
+ const int unicast_packets_in,
+ const int unicast_packets_out)
+{
+ MEASUREMENT_VNIC_USE * vnic_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Trust the assertions in the underlying methods. */
+ /***************************************************************************/
+ vnic_use = evel_new_measurement_vnic_use(vnic_id,
+ packets_in,
+ packets_out,
+ bytes_in,
+ bytes_out);
+ evel_vnic_use_bcast_pkt_in_set(vnic_use, broadcast_packets_in);
+ evel_vnic_use_bcast_pkt_out_set(vnic_use, broadcast_packets_out);
+ evel_vnic_use_mcast_pkt_in_set(vnic_use, multicast_packets_in);
+ evel_vnic_use_mcast_pkt_out_set(vnic_use, multicast_packets_out);
+ evel_vnic_use_ucast_pkt_in_set(vnic_use, unicast_packets_in);
+ evel_vnic_use_ucast_pkt_out_set(vnic_use, unicast_packets_out);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+}
+
+/**************************************************************************//**
+ * Encode the measurement as a JSON measurement.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_measurement(EVEL_JSON_BUFFER * jbuf,
+ EVENT_MEASUREMENT * event)
+{
+ MEASUREMENT_CPU_USE * cpu_use = NULL;
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_USE * vnic_use = NULL;
+ MEASUREMENT_ERRORS * errors = NULL;
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ MEASUREMENT_CODEC_USE * codec_use = NULL;
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * custom_measurement = NULL;
+ DLIST_ITEM * item = NULL;
+ DLIST_ITEM * nested_item = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "measurementsForVfScalingFields");
+
+ /***************************************************************************/
+ /* Mandatory fields. */
+ /***************************************************************************/
+ evel_enc_kv_double(jbuf, "measurementInterval", event->measurement_interval);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+ evel_enc_kv_opt_int(jbuf, "concurrentSessions", &event->concurrent_sessions);
+ evel_enc_kv_opt_int(jbuf, "configuredEntities", &event->configured_entities);
+
+ /***************************************************************************/
+ /* CPU Use list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "cpuUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->cpu_usage);
+ while (item != NULL)
+ {
+ cpu_use = (MEASUREMENT_CPU_USE*) item->item;
+ assert(cpu_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "cpuUsageArray",
+ cpu_use->id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "cpuIdentifier", cpu_use->id);
+ evel_enc_kv_double(jbuf, "percentUsage", cpu_use->usage);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Filesystem Usage list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "filesystemUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->filesystem_usage);
+ while (item != NULL)
+ {
+ fsys_use = (MEASUREMENT_FSYS_USE *) item->item;
+ assert(fsys_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "filesystemUsageArray",
+ fsys_use->filesystem_name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_double(
+ jbuf, "blockConfigured", fsys_use->block_configured);
+ evel_enc_kv_int(jbuf, "blockIops", fsys_use->block_iops);
+ evel_enc_kv_double(jbuf, "blockUsed", fsys_use->block_used);
+ evel_enc_kv_double(
+ jbuf, "ephemeralConfigured", fsys_use->ephemeral_configured);
+ evel_enc_kv_int(jbuf, "ephemeralIops", fsys_use->ephemeral_iops);
+ evel_enc_kv_double(jbuf, "ephemeralUsed", fsys_use->ephemeral_used);
+ evel_enc_kv_string(jbuf, "filesystemName", fsys_use->filesystem_name);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Latency distribution. */
+ /***************************************************************************/
+ item = dlist_get_first(&event->latency_distribution);
+ if ((item != NULL) &&
+ evel_json_open_opt_named_list(jbuf, "latencyDistribution"))
+ {
+ while (item != NULL)
+ {
+ bucket = (MEASUREMENT_LATENCY_BUCKET*) item->item;
+ assert(bucket != NULL);
+
+ evel_json_open_object(jbuf);
+ evel_enc_kv_opt_double(
+ jbuf, "lowEndOfLatencyBucket", &bucket->low_end);
+ evel_enc_kv_opt_double(
+ jbuf, "highEndOfLatencyBucket", &bucket->high_end);
+ evel_enc_kv_int(jbuf, "countsInTheBucket", bucket->count);
+ evel_json_close_object(jbuf);
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ evel_enc_kv_opt_double(
+ jbuf, "meanRequestLatency", &event->mean_request_latency);
+ evel_enc_kv_opt_double(jbuf, "memoryConfigured", &event->memory_configured);
+ evel_enc_kv_opt_double(jbuf, "memoryUsed", &event->memory_used);
+ evel_enc_kv_opt_int(jbuf, "requestRate", &event->request_rate);
+
+ /***************************************************************************/
+ /* vNIC Usage */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "vNicUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->vnic_usage);
+ while (item != NULL)
+ {
+ vnic_use = (MEASUREMENT_VNIC_USE *) item->item;
+ assert(vnic_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "vNicUsageArray",
+ vnic_use->vnic_id))
+ {
+ evel_json_open_object(jbuf);
+
+ /*********************************************************************/
+ /* Mandatory fields. */
+ /*********************************************************************/
+ evel_enc_kv_int(jbuf, "bytesIn", vnic_use->bytes_in);
+ evel_enc_kv_int(jbuf, "bytesOut", vnic_use->bytes_out);
+ evel_enc_kv_int(jbuf, "packetsIn", vnic_use->packets_in);
+ evel_enc_kv_int(jbuf, "packetsOut", vnic_use->packets_out);
+ evel_enc_kv_string(jbuf, "vNicIdentifier", vnic_use->vnic_id);
+
+ /*********************************************************************/
+ /* Optional fields. */
+ /*********************************************************************/
+ evel_enc_kv_opt_int(
+ jbuf, "broadcastPacketsIn", &vnic_use->broadcast_packets_in);
+ evel_enc_kv_opt_int(
+ jbuf, "broadcastPacketsOut", &vnic_use->broadcast_packets_out);
+ evel_enc_kv_opt_int(
+ jbuf, "multicastPacketsIn", &vnic_use->multicast_packets_in);
+ evel_enc_kv_opt_int(
+ jbuf, "multicastPacketsOut", &vnic_use->multicast_packets_out);
+ evel_enc_kv_opt_int(
+ jbuf, "unicastPacketsIn", &vnic_use->unicast_packets_in);
+ evel_enc_kv_opt_int(
+ jbuf, "unicastPacketsOut", &vnic_use->unicast_packets_out);
+
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ evel_enc_kv_opt_double(
+ jbuf, "aggregateCpuUsage", &event->aggregate_cpu_usage);
+ evel_enc_kv_opt_int(
+ jbuf, "numberOfMediaPortsInUse", &event->media_ports_in_use);
+ evel_enc_kv_opt_double(
+ jbuf, "vnfcScalingMetric", &event->vnfc_scaling_metric);
+
+ /***************************************************************************/
+ /* Errors list. */
+ /***************************************************************************/
+ if ((event->errors != NULL) &&
+ evel_json_open_opt_named_object(jbuf, "errors"))
+ {
+ errors = event->errors;
+ evel_enc_kv_int(jbuf, "receiveDiscards", errors->receive_discards);
+ evel_enc_kv_int(jbuf, "receiveErrors", errors->receive_errors);
+ evel_enc_kv_int(jbuf, "transmitDiscards", errors->transmit_discards);
+ evel_enc_kv_int(jbuf, "transmitErrors", errors->transmit_errors);
+ evel_json_close_object(jbuf);
+ }
+
+ /***************************************************************************/
+ /* Feature Utilization list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "featureUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->feature_usage);
+ while (item != NULL)
+ {
+ feature_use = (MEASUREMENT_FEATURE_USE*) item->item;
+ assert(feature_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "featureUsageArray",
+ feature_use->feature_id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "featureIdentifier", feature_use->feature_id);
+ evel_enc_kv_int(
+ jbuf, "featureUtilization", feature_use->feature_utilization);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Codec Utilization list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "codecUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->codec_usage);
+ while (item != NULL)
+ {
+ codec_use = (MEASUREMENT_CODEC_USE*) item->item;
+ assert(codec_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "codecUsageArray",
+ codec_use->codec_id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "codecIdentifier", codec_use->codec_id);
+ evel_enc_kv_int(jbuf, "numberInUse", codec_use->number_in_use);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Additional Measurement Groups list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalMeasurements"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->additional_measurements);
+ while (item != NULL)
+ {
+ measurement_group = (MEASUREMENT_GROUP *) item->item;
+ assert(measurement_group != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalMeasurements",
+ measurement_group->name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", measurement_group->name);
+ evel_json_open_opt_named_list(jbuf, "measurements");
+
+ /*********************************************************************/
+ /* Measurements list. */
+ /*********************************************************************/
+ nested_item = dlist_get_first(&measurement_group->measurements);
+ while (nested_item != NULL)
+ {
+ custom_measurement = (CUSTOM_MEASUREMENT *) nested_item->item;
+ assert(custom_measurement != NULL);
+
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", custom_measurement->name);
+ evel_enc_kv_string(jbuf, "value", custom_measurement->value);
+ evel_json_close_object(jbuf);
+ nested_item = dlist_get_next(nested_item);
+ }
+ evel_json_close_list(jbuf);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Although optional, we always generate the version. Note that this */
+ /* closes the object, too. */
+ /***************************************************************************/
+ evel_enc_version(jbuf,
+ "measurementsForVfScalingVersion",
+ event->major_version,
+ event->major_version);
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Measurement.
+ *
+ * Free off the Measurement supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Measurement itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_measurement(EVENT_MEASUREMENT * event)
+{
+ MEASUREMENT_CPU_USE * cpu_use = NULL;
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_USE * vnic_use = NULL;
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ MEASUREMENT_CODEC_USE * codec_use = NULL;
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * measurement = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ cpu_use = dlist_pop_last(&event->cpu_usage);
+ while (cpu_use != NULL)
+ {
+ EVEL_DEBUG("Freeing CPU use Info (%s)", cpu_use->id);
+ free(cpu_use->id);
+ free(cpu_use);
+ cpu_use = dlist_pop_last(&event->cpu_usage);
+ }
+
+ fsys_use = dlist_pop_last(&event->filesystem_usage);
+ while (fsys_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Filesystem Use info (%s)", fsys_use->filesystem_name);
+ free(fsys_use->filesystem_name);
+ free(fsys_use);
+ fsys_use = dlist_pop_last(&event->filesystem_usage);
+ }
+
+ bucket = dlist_pop_last(&event->latency_distribution);
+ while (bucket != NULL)
+ {
+ EVEL_DEBUG("Freeing Latency Bucket");
+ free(bucket);
+ bucket = dlist_pop_last(&event->latency_distribution);
+ }
+
+ vnic_use = dlist_pop_last(&event->vnic_usage);
+ while (vnic_use != NULL)
+ {
+ EVEL_DEBUG("Freeing vNIC use Info (%s)", vnic_use->vnic_id);
+ evel_free_measurement_vnic_use(vnic_use);
+ free(vnic_use);
+ vnic_use = dlist_pop_last(&event->vnic_usage);
+ }
+
+ codec_use = dlist_pop_last(&event->codec_usage);
+ while (codec_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Codec use Info (%s)", codec_use->codec_id);
+ free(codec_use->codec_id);
+ free(codec_use);
+ codec_use = dlist_pop_last(&event->codec_usage);
+ }
+
+ if (event->errors != NULL)
+ {
+ EVEL_DEBUG("Freeing Errors");
+ free(event->errors);
+ }
+
+ feature_use = dlist_pop_last(&event->feature_usage);
+ while (feature_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Feature use Info (%s)", feature_use->feature_id);
+ free(feature_use->feature_id);
+ free(feature_use);
+ feature_use = dlist_pop_last(&event->feature_usage);
+ }
+
+ measurement_group = dlist_pop_last(&event->additional_measurements);
+ while (measurement_group != NULL)
+ {
+ EVEL_DEBUG("Freeing Measurement Group (%s)", measurement_group->name);
+
+ measurement = dlist_pop_last(&measurement_group->measurements);
+ while (measurement != NULL)
+ {
+ EVEL_DEBUG("Freeing Measurement (%s)", measurement->name);
+ free(measurement->name);
+ free(measurement->value);
+ free(measurement);
+ measurement = dlist_pop_last(&measurement_group->measurements);
+ }
+ free(measurement_group->name);
+ free(measurement_group);
+ measurement_group = dlist_pop_last(&event->additional_measurements);
+ }
+
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}