Initial OpenECOMP Demo commit
[demo.git] / vnfs / VES / code / evel_library / evel_scaling_measurement.c
1 /**************************************************************************//**
2  * @file
3  * Implementation of EVEL functions relating to the Measurement.
4  *
5  * License
6  * -------
7  *
8  * Copyright(c) <2016>, AT&T Intellectual Property.  All other rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  *    this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  *    this list of conditions and the following disclaimer in the documentation
17  *    and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:  This product includes
20  *    software developed by the AT&T.
21  * 4. Neither the name of AT&T nor the names of its contributors may be used to
22  *    endorse or promote products derived from this software without specific
23  *    prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
26  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28  * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
29  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *****************************************************************************/
36
37 #include <string.h>
38 #include <assert.h>
39 #include <stdlib.h>
40
41 #include "evel.h"
42 #include "evel_internal.h"
43 #include "evel_throttle.h"
44
45 /**************************************************************************//**
46  * Create a new Measurement event.
47  *
48  * @note    The mandatory fields on the Measurement must be supplied to this
49  *          factory function and are immutable once set.  Optional fields have
50  *          explicit setter functions, but again values may only be set once so
51  *          that the Measurement has immutable properties.
52  *
53  * @param   measurement_interval
54  *
55  * @returns pointer to the newly manufactured ::EVENT_MEASUREMENT.  If the
56  *          event is not used (i.e. posted) it must be released using
57  *          ::evel_free_event.
58  * @retval  NULL  Failed to create the event.
59  *****************************************************************************/
60 EVENT_MEASUREMENT * evel_new_measurement(double measurement_interval)
61 {
62   EVENT_MEASUREMENT * measurement = NULL;
63
64   EVEL_ENTER();
65
66   /***************************************************************************/
67   /* Check preconditions.                                                    */
68   /***************************************************************************/
69   assert(measurement_interval >= 0.0);
70
71   /***************************************************************************/
72   /* Allocate the measurement.                                               */
73   /***************************************************************************/
74   measurement = malloc(sizeof(EVENT_MEASUREMENT));
75   if (measurement == NULL)
76   {
77     log_error_state("Out of memory for Measurement");
78     goto exit_label;
79   }
80   memset(measurement, 0, sizeof(EVENT_MEASUREMENT));
81   EVEL_DEBUG("New measurement is at %lp", measurement);
82
83   /***************************************************************************/
84   /* Initialize the header & the measurement fields.                         */
85   /***************************************************************************/
86   evel_init_header(&measurement->header);
87   measurement->header.event_domain = EVEL_DOMAIN_MEASUREMENT;
88   measurement->measurement_interval = measurement_interval;
89   dlist_initialize(&measurement->cpu_usage);
90   dlist_initialize(&measurement->filesystem_usage);
91   dlist_initialize(&measurement->latency_distribution);
92   dlist_initialize(&measurement->vnic_usage);
93   dlist_initialize(&measurement->codec_usage);
94   dlist_initialize(&measurement->feature_usage);
95   dlist_initialize(&measurement->additional_measurements);
96   evel_init_option_double(&measurement->aggregate_cpu_usage);
97   evel_init_option_double(&measurement->mean_request_latency);
98   evel_init_option_double(&measurement->memory_configured);
99   evel_init_option_double(&measurement->memory_used);
100   evel_init_option_double(&measurement->vnfc_scaling_metric);
101   evel_init_option_int(&measurement->concurrent_sessions);
102   evel_init_option_int(&measurement->configured_entities);
103   evel_init_option_int(&measurement->media_ports_in_use);
104   evel_init_option_int(&measurement->request_rate);
105   measurement->major_version = EVEL_MEASUREMENT_MAJOR_VERSION;
106   measurement->minor_version = EVEL_MEASUREMENT_MINOR_VERSION;
107
108 exit_label:
109   EVEL_EXIT();
110   return measurement;
111 }
112
113 /**************************************************************************//**
114  * Set the Event Type property of the Measurement.
115  *
116  * @note  The property is treated as immutable: it is only valid to call
117  *        the setter once.  However, we don't assert if the caller tries to
118  *        overwrite, just ignoring the update instead.
119  *
120  * @param measurement Pointer to the Measurement.
121  * @param type        The Event Type to be set. ASCIIZ string. The caller
122  *                    does not need to preserve the value once the function
123  *                    returns.
124  *****************************************************************************/
125 void evel_measurement_type_set(EVENT_MEASUREMENT * measurement,
126                                const char * const type)
127 {
128   EVEL_ENTER();
129
130   /***************************************************************************/
131   /* Check preconditions and call evel_header_type_set.                      */
132   /***************************************************************************/
133   assert(measurement != NULL);
134   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
135   evel_header_type_set(&measurement->header, type);
136
137   EVEL_EXIT();
138 }
139
140 /**************************************************************************//**
141  * Set the Concurrent Sessions property of the Measurement.
142  *
143  * @note  The property is treated as immutable: it is only valid to call
144  *        the setter once.  However, we don't assert if the caller tries to
145  *        overwrite, just ignoring the update instead.
146  *
147  * @param measurement         Pointer to the Measurement.
148  * @param concurrent_sessions The Concurrent Sessions to be set.
149  *****************************************************************************/
150 void evel_measurement_conc_sess_set(EVENT_MEASUREMENT * measurement,
151                                     int concurrent_sessions)
152 {
153   EVEL_ENTER();
154
155   /***************************************************************************/
156   /* Check preconditions.                                                    */
157   /***************************************************************************/
158   assert(measurement != NULL);
159   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
160   assert(concurrent_sessions >= 0);
161
162   evel_set_option_int(&measurement->concurrent_sessions,
163                       concurrent_sessions,
164                       "Concurrent Sessions");
165   EVEL_EXIT();
166 }
167
168 /**************************************************************************//**
169  * Set the Configured Entities property of the Measurement.
170  *
171  * @note  The property is treated as immutable: it is only valid to call
172  *        the setter once.  However, we don't assert if the caller tries to
173  *        overwrite, just ignoring the update instead.
174  *
175  * @param measurement         Pointer to the Measurement.
176  * @param configured_entities The Configured Entities to be set.
177  *****************************************************************************/
178 void evel_measurement_cfg_ents_set(EVENT_MEASUREMENT * measurement,
179                                    int configured_entities)
180 {
181   EVEL_ENTER();
182
183   /***************************************************************************/
184   /* Check preconditions.                                                    */
185   /***************************************************************************/
186   assert(measurement != NULL);
187   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
188   assert(configured_entities >= 0);
189
190   evel_set_option_int(&measurement->configured_entities,
191                       configured_entities,
192                       "Configured Entities");
193   EVEL_EXIT();
194 }
195
196 /**************************************************************************//**
197  * Add an additional set of Errors to the Measurement.
198  *
199  * @note  The property is treated as immutable: it is only valid to call
200  *        the setter once.  However, we don't assert if the caller tries to
201  *        overwrite, just ignoring the update instead.
202  *
203  * @param measurement       Pointer to the measurement.
204  * @param receive_discards  The number of receive discards.
205  * @param receive_errors    The number of receive errors.
206  * @param transmit_discards The number of transmit discards.
207  * @param transmit_errors   The number of transmit errors.
208  *****************************************************************************/
209 void evel_measurement_errors_set(EVENT_MEASUREMENT * measurement,
210                                  int receive_discards,
211                                  int receive_errors,
212                                  int transmit_discards,
213                                  int transmit_errors)
214 {
215   MEASUREMENT_ERRORS * errors = NULL;
216   EVEL_ENTER();
217
218   /***************************************************************************/
219   /* Check preconditions.                                                      */
220   /***************************************************************************/
221   assert(measurement != NULL);
222   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
223   assert(receive_discards >= 0);
224   assert(receive_errors >= 0);
225   assert(transmit_discards >= 0);
226   assert(transmit_errors >= 0);
227
228   if (measurement->errors == NULL)
229   {
230     EVEL_DEBUG("Adding Errors: %d, %d; %d, %d",
231                receive_discards,
232                receive_errors,
233                transmit_discards,
234                transmit_errors);
235     errors = malloc(sizeof(MEASUREMENT_ERRORS));
236     assert(errors != NULL);
237     memset(errors, 0, sizeof(MEASUREMENT_ERRORS));
238     errors->receive_discards = receive_discards;
239     errors->receive_errors = receive_errors;
240     errors->transmit_discards = transmit_discards;
241     errors->transmit_errors = transmit_errors;
242     measurement->errors = errors;
243   }
244   else
245   {
246     errors = measurement->errors;
247     EVEL_DEBUG("Ignoring attempt to add Errors: %d, %d; %d, %d\n"
248                "Errors already set: %d, %d; %d, %d",
249                receive_discards,
250                receive_errors,
251                transmit_discards,
252                transmit_errors,
253                errors->receive_discards,
254                errors->receive_errors,
255                errors->transmit_discards,
256                errors->transmit_errors);
257   }
258
259   EVEL_EXIT();
260 }
261
262 /**************************************************************************//**
263  * Set the Mean Request Latency property of the Measurement.
264  *
265  * @note  The property is treated as immutable: it is only valid to call
266  *        the setter once.  However, we don't assert if the caller tries to
267  *        overwrite, just ignoring the update instead.
268  *
269  * @param measurement          Pointer to the Measurement.
270  * @param mean_request_latency The Mean Request Latency to be set.
271  *****************************************************************************/
272 void evel_measurement_mean_req_lat_set(EVENT_MEASUREMENT * measurement,
273                                        double mean_request_latency)
274 {
275   EVEL_ENTER();
276
277   /***************************************************************************/
278   /* Check preconditions.                                                    */
279   /***************************************************************************/
280   assert(measurement != NULL);
281   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
282   assert(mean_request_latency >= 0.0);
283
284   evel_set_option_double(&measurement->mean_request_latency,
285                          mean_request_latency,
286                          "Mean Request Latency");
287   EVEL_EXIT();
288 }
289
290 /**************************************************************************//**
291  * Set the Memory Configured property of the Measurement.
292  *
293  * @note  The property is treated as immutable: it is only valid to call
294  *        the setter once.  However, we don't assert if the caller tries to
295  *        overwrite, just ignoring the update instead.
296  *
297  * @param measurement       Pointer to the Measurement.
298  * @param memory_configured The Memory Configured to be set.
299  *****************************************************************************/
300 void evel_measurement_mem_cfg_set(EVENT_MEASUREMENT * measurement,
301                                   double memory_configured)
302 {
303   EVEL_ENTER();
304
305   /***************************************************************************/
306   /* Check preconditions.                                                    */
307   /***************************************************************************/
308   assert(measurement != NULL);
309   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
310   assert(memory_configured >= 0.0);
311
312   evel_set_option_double(&measurement->memory_configured,
313                          memory_configured,
314                          "Memory Configured");
315   EVEL_EXIT();
316 }
317
318 /**************************************************************************//**
319  * Set the Memory Used property of the Measurement.
320  *
321  * @note  The property is treated as immutable: it is only valid to call
322  *        the setter once.  However, we don't assert if the caller tries to
323  *        overwrite, just ignoring the update instead.
324  *
325  * @param measurement Pointer to the Measurement.
326  * @param memory_used The Memory Used to be set.
327  *****************************************************************************/
328 void evel_measurement_mem_used_set(EVENT_MEASUREMENT * measurement,
329                                    double memory_used)
330 {
331   EVEL_ENTER();
332
333   /***************************************************************************/
334   /* Check preconditions.                                                    */
335   /***************************************************************************/
336   assert(measurement != NULL);
337   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
338   assert(memory_used >= 0.0);
339
340   evel_set_option_double(&measurement->memory_used,
341                          memory_used,
342                          "Memory Used");
343   EVEL_EXIT();
344 }
345
346 /**************************************************************************//**
347  * Set the Request Rate property of the Measurement.
348  *
349  * @note  The property is treated as immutable: it is only valid to call
350  *        the setter once.  However, we don't assert if the caller tries to
351  *        overwrite, just ignoring the update instead.
352  *
353  * @param measurement  Pointer to the Measurement.
354  * @param request_rate The Request Rate to be set.
355  *****************************************************************************/
356 void evel_measurement_request_rate_set(EVENT_MEASUREMENT * measurement,
357                                        int request_rate)
358 {
359   EVEL_ENTER();
360
361   /***************************************************************************/
362   /* Check preconditions.                                                    */
363   /***************************************************************************/
364   assert(measurement != NULL);
365   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
366   assert(request_rate >= 0);
367
368   evel_set_option_int(&measurement->request_rate,
369                       request_rate,
370                       "Request Rate");
371   EVEL_EXIT();
372 }
373
374 /**************************************************************************//**
375  * Add an additional CPU usage value name/value pair to the Measurement.
376  *
377  * The name and value are null delimited ASCII strings.  The library takes
378  * a copy so the caller does not have to preserve values after the function
379  * returns.
380  *
381  * @param measurement   Pointer to the measurement.
382  * @param id            ASCIIZ string with the CPU's identifier.
383  * @param usage         CPU utilization.
384  *****************************************************************************/
385 void evel_measurement_cpu_use_add(EVENT_MEASUREMENT * measurement,
386                                  char * id, double usage)
387 {
388   MEASUREMENT_CPU_USE * cpu_use = NULL;
389   EVEL_ENTER();
390
391   /***************************************************************************/
392   /* Check assumptions.                                                      */
393   /***************************************************************************/
394   assert(measurement != NULL);
395   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
396   assert(id != NULL);
397   assert(usage >= 0.0);
398
399   /***************************************************************************/
400   /* Allocate a container for the value and push onto the list.              */
401   /***************************************************************************/
402   EVEL_DEBUG("Adding id=%s usage=%lf", id, usage);
403   cpu_use = malloc(sizeof(MEASUREMENT_CPU_USE));
404   assert(cpu_use != NULL);
405   memset(cpu_use, 0, sizeof(MEASUREMENT_CPU_USE));
406   cpu_use->id = strdup(id);
407   cpu_use->usage = usage;
408   assert(cpu_use->id != NULL);
409
410   dlist_push_last(&measurement->cpu_usage, cpu_use);
411
412   EVEL_EXIT();
413 }
414
415 /**************************************************************************//**
416  * Add an additional File System usage value name/value pair to the
417  * Measurement.
418  *
419  * The filesystem_name is null delimited ASCII string.  The library takes a
420  * copy so the caller does not have to preserve values after the function
421  * returns.
422  *
423  * @param measurement     Pointer to the measurement.
424  * @param filesystem_name   ASCIIZ string with the file-system's UUID.
425  * @param block_configured  Block storage configured.
426  * @param block_used        Block storage in use.
427  * @param block_iops        Block storage IOPS.
428  * @param ephemeral_configured  Ephemeral storage configured.
429  * @param ephemeral_used        Ephemeral storage in use.
430  * @param ephemeral_iops        Ephemeral storage IOPS.
431  *****************************************************************************/
432 void evel_measurement_fsys_use_add(EVENT_MEASUREMENT * measurement,
433                                    char * filesystem_name,
434                                    double block_configured,
435                                    double block_used,
436                                    int block_iops,
437                                    double ephemeral_configured,
438                                    double ephemeral_used,
439                                    int ephemeral_iops)
440 {
441   MEASUREMENT_FSYS_USE * fsys_use = NULL;
442   EVEL_ENTER();
443
444   /***************************************************************************/
445   /* Check assumptions.                                                      */
446   /***************************************************************************/
447   assert(measurement != NULL);
448   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
449   assert(filesystem_name != NULL);
450   assert(block_configured >= 0.0);
451   assert(block_used >= 0.0);
452   assert(block_iops >= 0);
453   assert(ephemeral_configured >= 0.0);
454   assert(ephemeral_used >= 0.0);
455   assert(ephemeral_iops >= 0);
456
457   /***************************************************************************/
458   /* Allocate a container for the value and push onto the list.              */
459   /***************************************************************************/
460   EVEL_DEBUG("Adding filesystem_name=%s", filesystem_name);
461   fsys_use = malloc(sizeof(MEASUREMENT_FSYS_USE));
462   assert(fsys_use != NULL);
463   memset(fsys_use, 0, sizeof(MEASUREMENT_FSYS_USE));
464   fsys_use->filesystem_name = strdup(filesystem_name);
465   fsys_use->block_configured = block_configured;
466   fsys_use->block_used = block_used;
467   fsys_use->block_iops = block_iops;
468   fsys_use->ephemeral_configured = block_configured;
469   fsys_use->ephemeral_used = ephemeral_used;
470   fsys_use->ephemeral_iops = ephemeral_iops;
471
472   dlist_push_last(&measurement->filesystem_usage, fsys_use);
473
474   EVEL_EXIT();
475 }
476
477 /**************************************************************************//**
478  * Add a Feature usage value name/value pair to the Measurement.
479  *
480  * The name is null delimited ASCII string.  The library takes
481  * a copy so the caller does not have to preserve values after the function
482  * returns.
483  *
484  * @param measurement     Pointer to the measurement.
485  * @param feature         ASCIIZ string with the feature's name.
486  * @param utilization     Utilization of the feature.
487  *****************************************************************************/
488 void evel_measurement_feature_use_add(EVENT_MEASUREMENT * measurement,
489                                       char * feature,
490                                       int utilization)
491 {
492   MEASUREMENT_FEATURE_USE * feature_use = NULL;
493   EVEL_ENTER();
494
495   /***************************************************************************/
496   /* Check assumptions.                                                      */
497   /***************************************************************************/
498   assert(measurement != NULL);
499   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
500   assert(feature != NULL);
501   assert(utilization >= 0);
502
503   /***************************************************************************/
504   /* Allocate a container for the value and push onto the list.              */
505   /***************************************************************************/
506   EVEL_DEBUG("Adding Feature=%s Use=%d", feature, utilization);
507   feature_use = malloc(sizeof(MEASUREMENT_FEATURE_USE));
508   assert(feature_use != NULL);
509   memset(feature_use, 0, sizeof(MEASUREMENT_FEATURE_USE));
510   feature_use->feature_id = strdup(feature);
511   assert(feature_use->feature_id != NULL);
512   feature_use->feature_utilization = utilization;
513
514   dlist_push_last(&measurement->feature_usage, feature_use);
515
516   EVEL_EXIT();
517 }
518
519 /**************************************************************************//**
520  * Add a Additional Measurement value name/value pair to the Report.
521  *
522  * The name is null delimited ASCII string.  The library takes
523  * a copy so the caller does not have to preserve values after the function
524  * returns.
525  *
526  * @param measurement   Pointer to the Measaurement.
527  * @param group    ASCIIZ string with the measurement group's name.
528  * @param name     ASCIIZ string containing the measurement's name.
529  * @param value    ASCIIZ string containing the measurement's value.
530  *****************************************************************************/
531 void evel_measurement_custom_measurement_add(EVENT_MEASUREMENT * measurement,
532                                              const char * const group,
533                                              const char * const name,
534                                              const char * const value)
535 {
536   MEASUREMENT_GROUP * measurement_group = NULL;
537   CUSTOM_MEASUREMENT * custom_measurement = NULL;
538   DLIST_ITEM * item = NULL;
539   EVEL_ENTER();
540
541   /***************************************************************************/
542   /* Check assumptions.                                                      */
543   /***************************************************************************/
544   assert(measurement != NULL);
545   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
546   assert(group != NULL);
547   assert(name != NULL);
548   assert(value != NULL);
549
550   /***************************************************************************/
551   /* Allocate a container for the name/value pair.                           */
552   /***************************************************************************/
553   EVEL_DEBUG("Adding Measurement Group=%s Name=%s Value=%s",
554               group, name, value);
555   custom_measurement = malloc(sizeof(CUSTOM_MEASUREMENT));
556   assert(custom_measurement != NULL);
557   memset(custom_measurement, 0, sizeof(CUSTOM_MEASUREMENT));
558   custom_measurement->name = strdup(name);
559   assert(custom_measurement->name != NULL);
560   custom_measurement->value = strdup(value);
561   assert(custom_measurement->value != NULL);
562
563   /***************************************************************************/
564   /* See if we have that group already.                                      */
565   /***************************************************************************/
566   item = dlist_get_first(&measurement->additional_measurements);
567   while (item != NULL)
568   {
569     measurement_group = (MEASUREMENT_GROUP *) item->item;
570     assert(measurement_group != NULL);
571
572     EVEL_DEBUG("Got measurement group %s", measurement_group->name);
573     if (strcmp(group, measurement_group->name) == 0)
574     {
575       EVEL_DEBUG("Found existing Measurement Group");
576       break;
577     }
578     item = dlist_get_next(item);
579   }
580
581   /***************************************************************************/
582   /* If we didn't have the group already, create it.                         */
583   /***************************************************************************/
584   if (item == NULL)
585   {
586     EVEL_DEBUG("Creating new Measurement Group");
587     measurement_group = malloc(sizeof(MEASUREMENT_GROUP));
588     assert(measurement_group != NULL);
589     memset(measurement_group, 0, sizeof(MEASUREMENT_GROUP));
590     measurement_group->name = strdup(group);
591     assert(measurement_group->name != NULL);
592     dlist_initialize(&measurement_group->measurements);
593     dlist_push_last(&measurement->additional_measurements, measurement_group);
594   }
595
596   /***************************************************************************/
597   /* If we didn't have the group already, create it.                         */
598   /***************************************************************************/
599   dlist_push_last(&measurement_group->measurements, custom_measurement);
600
601   EVEL_EXIT();
602 }
603
604 /**************************************************************************//**
605  * Add a Codec usage value name/value pair to the Measurement.
606  *
607  * The name is null delimited ASCII string.  The library takes
608  * a copy so the caller does not have to preserve values after the function
609  * returns.
610  *
611  * @param measurement     Pointer to the measurement.
612  * @param codec           ASCIIZ string with the codec's name.
613  * @param utilization     Number of codecs in use.
614  *****************************************************************************/
615 void evel_measurement_codec_use_add(EVENT_MEASUREMENT * measurement,
616                                     char * codec,
617                                     int utilization)
618 {
619   MEASUREMENT_CODEC_USE * codec_use = NULL;
620   EVEL_ENTER();
621
622   /***************************************************************************/
623   /* Check assumptions.                                                      */
624   /***************************************************************************/
625   assert(measurement != NULL);
626   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
627   assert(codec != NULL);
628   assert(utilization >= 0.0);
629
630   /***************************************************************************/
631   /* Allocate a container for the value and push onto the list.              */
632   /***************************************************************************/
633   EVEL_DEBUG("Adding Codec=%s Use=%d", codec, utilization);
634   codec_use = malloc(sizeof(MEASUREMENT_CODEC_USE));
635   assert(codec_use != NULL);
636   memset(codec_use, 0, sizeof(MEASUREMENT_CODEC_USE));
637   codec_use->codec_id = strdup(codec);
638   assert(codec_use->codec_id != NULL);
639   codec_use->number_in_use = utilization;
640
641   dlist_push_last(&measurement->codec_usage, codec_use);
642
643   EVEL_EXIT();
644 }
645
646 /**************************************************************************//**
647  * Set the Aggregate CPU Use property of the Measurement.
648  *
649  * @note  The property is treated as immutable: it is only valid to call
650  *        the setter once.  However, we don't assert if the caller tries to
651  *        overwrite, just ignoring the update instead.
652  *
653  * @param measurement   Pointer to the measurement.
654  * @param cpu_use       The CPU use to set.
655  *****************************************************************************/
656 void evel_measurement_agg_cpu_use_set(EVENT_MEASUREMENT * measurement,
657                                       double cpu_use)
658 {
659   EVEL_ENTER();
660
661   /***************************************************************************/
662   /* Check preconditions.                                                    */
663   /***************************************************************************/
664   assert(measurement != NULL);
665   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
666   assert(cpu_use >= 0.0);
667
668   evel_set_option_double(&measurement->aggregate_cpu_usage,
669                          cpu_use,
670                          "CPU Use");
671   EVEL_EXIT();
672 }
673
674 /**************************************************************************//**
675  * Set the Media Ports in Use property of the Measurement.
676  *
677  * @note  The property is treated as immutable: it is only valid to call
678  *        the setter once.  However, we don't assert if the caller tries to
679  *        overwrite, just ignoring the update instead.
680  *
681  * @param measurement         Pointer to the measurement.
682  * @param media_ports_in_use  The media port usage to set.
683  *****************************************************************************/
684 void evel_measurement_media_port_use_set(EVENT_MEASUREMENT * measurement,
685                                          int media_ports_in_use)
686 {
687   EVEL_ENTER();
688
689   /***************************************************************************/
690   /* Check preconditions.                                                    */
691   /***************************************************************************/
692   assert(measurement != NULL);
693   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
694   assert(media_ports_in_use >= 0);
695
696   evel_set_option_int(&measurement->media_ports_in_use,
697                       media_ports_in_use,
698                       "Media Ports In Use");
699   EVEL_EXIT();
700 }
701
702 /**************************************************************************//**
703  * Set the VNFC Scaling Metric property of the Measurement.
704  *
705  * @note  The property is treated as immutable: it is only valid to call
706  *        the setter once.  However, we don't assert if the caller tries to
707  *        overwrite, just ignoring the update instead.
708  *
709  * @param measurement     Pointer to the measurement.
710  * @param scaling_metric  The scaling metric to set.
711  *****************************************************************************/
712 void evel_measurement_vnfc_scaling_metric_set(EVENT_MEASUREMENT * measurement,
713                                               double scaling_metric)
714 {
715   EVEL_ENTER();
716
717   /***************************************************************************/
718   /* Check preconditions.                                                    */
719   /***************************************************************************/
720   assert(measurement != NULL);
721   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
722   assert(scaling_metric >= 0.0);
723
724   evel_set_option_double(&measurement->vnfc_scaling_metric,
725                          scaling_metric,
726                          "VNFC Scaling Metric");
727   EVEL_EXIT();
728 }
729
730 /**************************************************************************//**
731  * Create a new Latency Bucket to be added to a Measurement event.
732  *
733  * @note    The mandatory fields on the ::MEASUREMENT_LATENCY_BUCKET must be
734  *          supplied to this factory function and are immutable once set.
735  *          Optional fields have explicit setter functions, but again values
736  *          may only be set once so that the ::MEASUREMENT_LATENCY_BUCKET has
737  *          immutable properties.
738  *
739  * @param count         Count of events in this bucket.
740  *
741  * @returns pointer to the newly manufactured ::MEASUREMENT_LATENCY_BUCKET.
742  *          If the structure is not used it must be released using free.
743  * @retval  NULL  Failed to create the Latency Bucket.
744  *****************************************************************************/
745 MEASUREMENT_LATENCY_BUCKET * evel_new_meas_latency_bucket(const int count)
746 {
747   MEASUREMENT_LATENCY_BUCKET * bucket;
748
749   EVEL_ENTER();
750
751   /***************************************************************************/
752   /* Check preconditions.                                                    */
753   /***************************************************************************/
754   assert(count >= 0);
755
756   /***************************************************************************/
757   /* Allocate, then set Mandatory Parameters.                                */
758   /***************************************************************************/
759   EVEL_DEBUG("Creating bucket, count = %d", count);
760   bucket = malloc(sizeof(MEASUREMENT_LATENCY_BUCKET));
761   assert(bucket != NULL);
762
763   /***************************************************************************/
764   /* Set Mandatory Parameters.                                               */
765   /***************************************************************************/
766   bucket->count = count;
767
768   /***************************************************************************/
769   /* Initialize Optional Parameters.                                         */
770   /***************************************************************************/
771   evel_init_option_double(&bucket->high_end);
772   evel_init_option_double(&bucket->low_end);
773
774   EVEL_EXIT();
775
776   return bucket;
777 }
778
779 /**************************************************************************//**
780  * Set the High End property of the Measurement Latency Bucket.
781  *
782  * @note  The property is treated as immutable: it is only valid to call
783  *        the setter once.  However, we don't assert if the caller tries to
784  *        overwrite, just ignoring the update instead.
785  *
786  * @param bucket        Pointer to the Measurement Latency Bucket.
787  * @param high_end      High end of the bucket's range.
788  *****************************************************************************/
789 void evel_meas_latency_bucket_high_end_set(
790                                      MEASUREMENT_LATENCY_BUCKET * const bucket,
791                                      const double high_end)
792 {
793   EVEL_ENTER();
794
795   /***************************************************************************/
796   /* Check preconditions.                                                    */
797   /***************************************************************************/
798   assert(high_end >= 0.0);
799   evel_set_option_double(&bucket->high_end, high_end, "High End");
800
801   EVEL_EXIT();
802 }
803
804 /**************************************************************************//**
805  * Set the Low End property of the Measurement Latency Bucket.
806  *
807  * @note  The property is treated as immutable: it is only valid to call
808  *        the setter once.  However, we don't assert if the caller tries to
809  *        overwrite, just ignoring the update instead.
810  *
811  * @param bucket        Pointer to the Measurement Latency Bucket.
812  * @param low_end       Low end of the bucket's range.
813  *****************************************************************************/
814 void evel_meas_latency_bucket_low_end_set(
815                                      MEASUREMENT_LATENCY_BUCKET * const bucket,
816                                      const double low_end)
817 {
818   EVEL_ENTER();
819
820   /***************************************************************************/
821   /* Check preconditions.                                                    */
822   /***************************************************************************/
823   assert(low_end >= 0.0);
824   evel_set_option_double(&bucket->low_end, low_end, "Low End");
825   EVEL_EXIT();
826 }
827
828 /**************************************************************************//**
829  * Add an additional Measurement Latency Bucket to the specified event.
830  *
831  * @param measurement   Pointer to the Measurement event.
832  * @param bucket        Pointer to the Measurement Latency Bucket to add.
833  *****************************************************************************/
834 void evel_meas_latency_bucket_add(EVENT_MEASUREMENT * const measurement,
835                                   MEASUREMENT_LATENCY_BUCKET * const bucket)
836 {
837   EVEL_ENTER();
838
839   /***************************************************************************/
840   /* Check preconditions.                                                    */
841   /***************************************************************************/
842   assert(measurement != NULL);
843   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
844   assert(bucket != NULL);
845   dlist_push_last(&measurement->latency_distribution, bucket);
846
847   EVEL_EXIT();
848 }
849
850 /**************************************************************************//**
851  * Add an additional Latency Distribution bucket to the Measurement.
852  *
853  * This function implements the previous API, purely for convenience.
854  *
855  * @param measurement   Pointer to the measurement.
856  * @param low_end       Low end of the bucket's range.
857  * @param high_end      High end of the bucket's range.
858  * @param count         Count of events in this bucket.
859  *****************************************************************************/
860 void evel_measurement_latency_add(EVENT_MEASUREMENT * const measurement,
861                                   const double low_end,
862                                   const double high_end,
863                                   const int count)
864 {
865   MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
866
867   EVEL_ENTER();
868
869   /***************************************************************************/
870   /* Trust the assertions in the underlying methods.                         */
871   /***************************************************************************/
872   bucket = evel_new_meas_latency_bucket(count);
873   evel_meas_latency_bucket_low_end_set(bucket, low_end);
874   evel_meas_latency_bucket_high_end_set(bucket, high_end);
875   evel_meas_latency_bucket_add(measurement, bucket);
876
877   EVEL_EXIT();
878 }
879
880 /**************************************************************************//**
881  * Create a new vNIC Use to be added to a Measurement event.
882  *
883  * @note    The mandatory fields on the ::MEASUREMENT_VNIC_USE must be supplied
884  *          to this factory function and are immutable once set. Optional
885  *          fields have explicit setter functions, but again values may only be
886  *          set once so that the ::MEASUREMENT_VNIC_USE has immutable
887  *          properties.
888  *
889  * @param vnic_id               ASCIIZ string with the vNIC's ID.
890  * @param packets_in            Total packets received.
891  * @param packets_out           Total packets transmitted.
892  * @param bytes_in              Total bytes received.
893  * @param bytes_out             Total bytes transmitted.
894  *
895  * @returns pointer to the newly manufactured ::MEASUREMENT_VNIC_USE.
896  *          If the structure is not used it must be released using
897  *          ::evel_free_measurement_vnic_use.
898  * @retval  NULL  Failed to create the vNIC Use.
899  *****************************************************************************/
900 MEASUREMENT_VNIC_USE * evel_new_measurement_vnic_use(char * const vnic_id,
901                                                      const int packets_in,
902                                                      const int packets_out,
903                                                      const int bytes_in,
904                                                      const int bytes_out)
905 {
906   MEASUREMENT_VNIC_USE * vnic_use;
907
908   EVEL_ENTER();
909
910   /***************************************************************************/
911   /* Check preconditions.                                                    */
912   /***************************************************************************/
913   assert(vnic_id != NULL);
914   assert(packets_in >= 0);
915   assert(packets_out >= 0);
916   assert(bytes_in >= 0);
917   assert(bytes_out >= 0);
918
919   /***************************************************************************/
920   /* Allocate, then set Mandatory Parameters.                                */
921   /***************************************************************************/
922   EVEL_DEBUG("Adding VNIC ID=%s", vnic_id);
923   vnic_use = malloc(sizeof(MEASUREMENT_VNIC_USE));
924   assert(vnic_use != NULL);
925   vnic_use->vnic_id = strdup(vnic_id);
926   vnic_use->packets_in = packets_in;
927   vnic_use->packets_out = packets_out;
928   vnic_use->bytes_in = bytes_in;
929   vnic_use->bytes_out = bytes_out;
930
931   /***************************************************************************/
932   /* Initialize Optional Parameters.                                         */
933   /***************************************************************************/
934   evel_init_option_int(&vnic_use->broadcast_packets_in);
935   evel_init_option_int(&vnic_use->broadcast_packets_out);
936   evel_init_option_int(&vnic_use->multicast_packets_in);
937   evel_init_option_int(&vnic_use->multicast_packets_out);
938   evel_init_option_int(&vnic_use->unicast_packets_in);
939   evel_init_option_int(&vnic_use->unicast_packets_out);
940
941   EVEL_EXIT();
942
943   return vnic_use;
944 }
945
946 /**************************************************************************//**
947  * Free a vNIC Use.
948  *
949  * Free off the ::MEASUREMENT_VNIC_USE supplied.  Will free all the contained
950  * allocated memory.
951  *
952  * @note It does not free the vNIC Use itself, since that may be part of a
953  * larger structure.
954  *****************************************************************************/
955 void evel_free_measurement_vnic_use(MEASUREMENT_VNIC_USE * const vnic_use)
956 {
957   EVEL_ENTER();
958
959   /***************************************************************************/
960   /* Check preconditions.                                                    */
961   /***************************************************************************/
962   assert(vnic_use != NULL);
963   assert(vnic_use->vnic_id != NULL);
964
965   /***************************************************************************/
966   /* Free the duplicated string.                                             */
967   /***************************************************************************/
968   free(vnic_use->vnic_id);
969   vnic_use->vnic_id = NULL;
970
971   EVEL_EXIT();
972 }
973
974 /**************************************************************************//**
975  * Set the Broadcast Packets Received property of the vNIC Use.
976  *
977  * @note  The property is treated as immutable: it is only valid to call
978  *        the setter once.  However, we don't assert if the caller tries to
979  *        overwrite, just ignoring the update instead.
980  *
981  * @param vnic_use      Pointer to the vNIC Use.
982  * @param broadcast_packets_in
983  *                      Broadcast packets received.
984  *****************************************************************************/
985 void evel_vnic_use_bcast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
986                                     const int broadcast_packets_in)
987 {
988   EVEL_ENTER();
989
990   /***************************************************************************/
991   /* Check preconditions.                                                    */
992   /***************************************************************************/
993   assert(broadcast_packets_in >= 0);
994
995   evel_set_option_int(&vnic_use->broadcast_packets_in,
996                       broadcast_packets_in,
997                       "Broadcast Packets Received");
998
999   EVEL_EXIT();
1000 }
1001
1002 /**************************************************************************//**
1003  * Set the Broadcast Packets Transmitted property of the vNIC Use.
1004  *
1005  * @note  The property is treated as immutable: it is only valid to call
1006  *        the setter once.  However, we don't assert if the caller tries to
1007  *        overwrite, just ignoring the update instead.
1008  *
1009  * @param vnic_use      Pointer to the vNIC Use.
1010  * @param broadcast_packets_out
1011  *                      Broadcast packets transmitted.
1012  *****************************************************************************/
1013 void evel_vnic_use_bcast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
1014                                      const int broadcast_packets_out)
1015 {
1016   EVEL_ENTER();
1017
1018   /***************************************************************************/
1019   /* Check preconditions.                                                    */
1020   /***************************************************************************/
1021   assert(broadcast_packets_out >= 0);
1022
1023   evel_set_option_int(&vnic_use->broadcast_packets_out,
1024                       broadcast_packets_out,
1025                       "Broadcast Packets Transmitted");
1026
1027   EVEL_EXIT();
1028 }
1029
1030 /**************************************************************************//**
1031  * Set the Multicast Packets Received property of the vNIC Use.
1032  *
1033  * @note  The property is treated as immutable: it is only valid to call
1034  *        the setter once.  However, we don't assert if the caller tries to
1035  *        overwrite, just ignoring the update instead.
1036  *
1037  * @param vnic_use      Pointer to the vNIC Use.
1038  * @param multicast_packets_in
1039  *                      Multicast packets received.
1040  *****************************************************************************/
1041 void evel_vnic_use_mcast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
1042                                     const int multicast_packets_in)
1043 {
1044   EVEL_ENTER();
1045
1046   /***************************************************************************/
1047   /* Check preconditions.                                                    */
1048   /***************************************************************************/
1049   assert(multicast_packets_in >= 0);
1050
1051   evel_set_option_int(&vnic_use->multicast_packets_in,
1052                       multicast_packets_in,
1053                       "Multicast Packets Received");
1054
1055   EVEL_EXIT();
1056 }
1057
1058 /**************************************************************************//**
1059  * Set the Multicast Packets Transmitted property of the vNIC Use.
1060  *
1061  * @note  The property is treated as immutable: it is only valid to call
1062  *        the setter once.  However, we don't assert if the caller tries to
1063  *        overwrite, just ignoring the update instead.
1064  *
1065  * @param vnic_use      Pointer to the vNIC Use.
1066  * @param multicast_packets_out
1067  *                      Multicast packets transmitted.
1068  *****************************************************************************/
1069 void evel_vnic_use_mcast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
1070                                      const int multicast_packets_out)
1071 {
1072   EVEL_ENTER();
1073
1074   /***************************************************************************/
1075   /* Check preconditions.                                                    */
1076   /***************************************************************************/
1077   assert(multicast_packets_out >= 0);
1078
1079   evel_set_option_int(&vnic_use->multicast_packets_out,
1080                       multicast_packets_out,
1081                       "Multicast Packets Transmitted");
1082
1083   EVEL_EXIT();
1084 }
1085
1086 /**************************************************************************//**
1087  * Set the Unicast Packets Received property of the vNIC Use.
1088  *
1089  * @note  The property is treated as immutable: it is only valid to call
1090  *        the setter once.  However, we don't assert if the caller tries to
1091  *        overwrite, just ignoring the update instead.
1092  *
1093  * @param vnic_use      Pointer to the vNIC Use.
1094  * @param unicast_packets_in
1095  *                      Unicast packets received.
1096  *****************************************************************************/
1097 void evel_vnic_use_ucast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
1098                                     const int unicast_packets_in)
1099 {
1100   EVEL_ENTER();
1101
1102   /***************************************************************************/
1103   /* Check preconditions.                                                    */
1104   /***************************************************************************/
1105   assert(unicast_packets_in >= 0);
1106
1107   evel_set_option_int(&vnic_use->unicast_packets_in,
1108                       unicast_packets_in,
1109                       "Unicast Packets Received");
1110
1111   EVEL_EXIT();
1112 }
1113
1114 /**************************************************************************//**
1115  * Set the Unicast Packets Transmitted property of the vNIC Use.
1116  *
1117  * @note  The property is treated as immutable: it is only valid to call
1118  *        the setter once.  However, we don't assert if the caller tries to
1119  *        overwrite, just ignoring the update instead.
1120  *
1121  * @param vnic_use      Pointer to the vNIC Use.
1122  * @param unicast_packets_out
1123  *                      Unicast packets transmitted.
1124  *****************************************************************************/
1125 void evel_vnic_use_ucast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
1126                                      const int unicast_packets_out)
1127 {
1128   EVEL_ENTER();
1129
1130   /***************************************************************************/
1131   /* Check preconditions.                                                    */
1132   /***************************************************************************/
1133   assert(unicast_packets_out >= 0);
1134
1135   evel_set_option_int(&vnic_use->unicast_packets_out,
1136                       unicast_packets_out,
1137                       "Unicast Packets Transmitted");
1138
1139   EVEL_EXIT();
1140 }
1141
1142 /**************************************************************************//**
1143  * Add an additional vNIC Use to the specified Measurement event.
1144  *
1145  * @param measurement   Pointer to the measurement.
1146  * @param vnic_use      Pointer to the vNIC Use to add.
1147  *****************************************************************************/
1148 void evel_meas_vnic_use_add(EVENT_MEASUREMENT * const measurement,
1149                             MEASUREMENT_VNIC_USE * const vnic_use)
1150 {
1151   EVEL_ENTER();
1152
1153   /***************************************************************************/
1154   /* Check preconditions.                                                    */
1155   /***************************************************************************/
1156   assert(measurement != NULL);
1157   assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
1158   assert(vnic_use != NULL);
1159
1160   dlist_push_last(&measurement->vnic_usage, vnic_use);
1161
1162   EVEL_EXIT();
1163 }
1164
1165 /**************************************************************************//**
1166  * Add an additional vNIC usage record Measurement.
1167  *
1168  * This function implements the previous API, purely for convenience.
1169  *
1170  * The ID is null delimited ASCII string.  The library takes a copy so the
1171  * caller does not have to preserve values after the function returns.
1172  *
1173  * @param measurement           Pointer to the measurement.
1174  * @param vnic_id               ASCIIZ string with the vNIC's ID.
1175  * @param packets_in            Total packets received.
1176  * @param packets_out           Total packets transmitted.
1177  * @param broadcast_packets_in  Broadcast packets received.
1178  * @param broadcast_packets_out Broadcast packets transmitted.
1179  * @param bytes_in              Total bytes received.
1180  * @param bytes_out             Total bytes transmitted.
1181  * @param multicast_packets_in  Multicast packets received.
1182  * @param multicast_packets_out Multicast packets transmitted.
1183  * @param unicast_packets_in    Unicast packets received.
1184  * @param unicast_packets_out   Unicast packets transmitted.
1185  *****************************************************************************/
1186 void evel_measurement_vnic_use_add(EVENT_MEASUREMENT * const measurement,
1187                                    char * const vnic_id,
1188                                    const int packets_in,
1189                                    const int packets_out,
1190                                    const int broadcast_packets_in,
1191                                    const int broadcast_packets_out,
1192                                    const int bytes_in,
1193                                    const int bytes_out,
1194                                    const int multicast_packets_in,
1195                                    const int multicast_packets_out,
1196                                    const int unicast_packets_in,
1197                                    const int unicast_packets_out)
1198 {
1199   MEASUREMENT_VNIC_USE * vnic_use = NULL;
1200   EVEL_ENTER();
1201
1202   /***************************************************************************/
1203   /* Trust the assertions in the underlying methods.                         */
1204   /***************************************************************************/
1205   vnic_use = evel_new_measurement_vnic_use(vnic_id,
1206                                            packets_in,
1207                                            packets_out,
1208                                            bytes_in,
1209                                            bytes_out);
1210   evel_vnic_use_bcast_pkt_in_set(vnic_use, broadcast_packets_in);
1211   evel_vnic_use_bcast_pkt_out_set(vnic_use, broadcast_packets_out);
1212   evel_vnic_use_mcast_pkt_in_set(vnic_use, multicast_packets_in);
1213   evel_vnic_use_mcast_pkt_out_set(vnic_use, multicast_packets_out);
1214   evel_vnic_use_ucast_pkt_in_set(vnic_use, unicast_packets_in);
1215   evel_vnic_use_ucast_pkt_out_set(vnic_use, unicast_packets_out);
1216   evel_meas_vnic_use_add(measurement, vnic_use);
1217 }
1218
1219 /**************************************************************************//**
1220  * Encode the measurement as a JSON measurement.
1221  *
1222  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
1223  * @param event         Pointer to the ::EVENT_HEADER to encode.
1224  *****************************************************************************/
1225 void evel_json_encode_measurement(EVEL_JSON_BUFFER * jbuf,
1226                                   EVENT_MEASUREMENT * event)
1227 {
1228   MEASUREMENT_CPU_USE * cpu_use = NULL;
1229   MEASUREMENT_FSYS_USE * fsys_use = NULL;
1230   MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
1231   MEASUREMENT_VNIC_USE * vnic_use = NULL;
1232   MEASUREMENT_ERRORS * errors = NULL;
1233   MEASUREMENT_FEATURE_USE * feature_use = NULL;
1234   MEASUREMENT_CODEC_USE * codec_use = NULL;
1235   MEASUREMENT_GROUP * measurement_group = NULL;
1236   CUSTOM_MEASUREMENT * custom_measurement = NULL;
1237   DLIST_ITEM * item = NULL;
1238   DLIST_ITEM * nested_item = NULL;
1239
1240   EVEL_ENTER();
1241
1242   /***************************************************************************/
1243   /* Check preconditions.                                                    */
1244   /***************************************************************************/
1245   assert(event != NULL);
1246   assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
1247
1248   evel_json_encode_header(jbuf, &event->header);
1249   evel_json_open_named_object(jbuf, "measurementsForVfScalingFields");
1250
1251   /***************************************************************************/
1252   /* Mandatory fields.                                                       */
1253   /***************************************************************************/
1254   evel_enc_kv_double(jbuf, "measurementInterval", event->measurement_interval);
1255
1256   /***************************************************************************/
1257   /* Optional fields.                                                        */
1258   /***************************************************************************/
1259   evel_enc_kv_opt_int(jbuf, "concurrentSessions", &event->concurrent_sessions);
1260   evel_enc_kv_opt_int(jbuf, "configuredEntities", &event->configured_entities);
1261
1262   /***************************************************************************/
1263   /* CPU Use list.                                                           */
1264   /***************************************************************************/
1265   evel_json_checkpoint(jbuf);
1266   if (evel_json_open_opt_named_list(jbuf, "cpuUsageArray"))
1267   {
1268     bool item_added = false;
1269
1270     item = dlist_get_first(&event->cpu_usage);
1271     while (item != NULL)
1272     {
1273       cpu_use = (MEASUREMENT_CPU_USE*) item->item;
1274       assert(cpu_use != NULL);
1275
1276       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
1277                                           "cpuUsageArray",
1278                                           cpu_use->id))
1279       {
1280         evel_json_open_object(jbuf);
1281         evel_enc_kv_string(jbuf, "cpuIdentifier", cpu_use->id);
1282         evel_enc_kv_double(jbuf, "percentUsage", cpu_use->usage);
1283         evel_json_close_object(jbuf);
1284         item_added = true;
1285       }
1286       item = dlist_get_next(item);
1287     }
1288     evel_json_close_list(jbuf);
1289
1290     /*************************************************************************/
1291     /* If we've not written anything, rewind to before we opened the list.   */
1292     /*************************************************************************/
1293     if (!item_added)
1294     {
1295       evel_json_rewind(jbuf);
1296     }
1297   }
1298
1299   /***************************************************************************/
1300   /* Filesystem Usage list.                                                  */
1301   /***************************************************************************/
1302   evel_json_checkpoint(jbuf);
1303   if (evel_json_open_opt_named_list(jbuf, "filesystemUsageArray"))
1304   {
1305     bool item_added = false;
1306
1307     item = dlist_get_first(&event->filesystem_usage);
1308     while (item != NULL)
1309     {
1310       fsys_use = (MEASUREMENT_FSYS_USE *) item->item;
1311       assert(fsys_use != NULL);
1312
1313       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
1314                                           "filesystemUsageArray",
1315                                           fsys_use->filesystem_name))
1316       {
1317         evel_json_open_object(jbuf);
1318         evel_enc_kv_double(
1319           jbuf, "blockConfigured", fsys_use->block_configured);
1320         evel_enc_kv_int(jbuf, "blockIops", fsys_use->block_iops);
1321         evel_enc_kv_double(jbuf, "blockUsed", fsys_use->block_used);
1322         evel_enc_kv_double(
1323           jbuf, "ephemeralConfigured", fsys_use->ephemeral_configured);
1324         evel_enc_kv_int(jbuf, "ephemeralIops", fsys_use->ephemeral_iops);
1325         evel_enc_kv_double(jbuf, "ephemeralUsed", fsys_use->ephemeral_used);
1326         evel_enc_kv_string(jbuf, "filesystemName", fsys_use->filesystem_name);
1327         evel_json_close_object(jbuf);
1328         item_added = true;
1329       }
1330       item = dlist_get_next(item);
1331     }
1332     evel_json_close_list(jbuf);
1333
1334     /*************************************************************************/
1335     /* If we've not written anything, rewind to before we opened the list.   */
1336     /*************************************************************************/
1337     if (!item_added)
1338     {
1339       evel_json_rewind(jbuf);
1340     }
1341   }
1342
1343   /***************************************************************************/
1344   /* Latency distribution.                                                   */
1345   /***************************************************************************/
1346   item = dlist_get_first(&event->latency_distribution);
1347   if ((item != NULL) &&
1348       evel_json_open_opt_named_list(jbuf, "latencyDistribution"))
1349   {
1350     while (item != NULL)
1351     {
1352       bucket = (MEASUREMENT_LATENCY_BUCKET*) item->item;
1353       assert(bucket != NULL);
1354
1355       evel_json_open_object(jbuf);
1356       evel_enc_kv_opt_double(
1357         jbuf, "lowEndOfLatencyBucket", &bucket->low_end);
1358       evel_enc_kv_opt_double(
1359         jbuf, "highEndOfLatencyBucket", &bucket->high_end);
1360       evel_enc_kv_int(jbuf, "countsInTheBucket", bucket->count);
1361       evel_json_close_object(jbuf);
1362       item = dlist_get_next(item);
1363     }
1364     evel_json_close_list(jbuf);
1365   }
1366
1367   evel_enc_kv_opt_double(
1368     jbuf, "meanRequestLatency", &event->mean_request_latency);
1369   evel_enc_kv_opt_double(jbuf, "memoryConfigured", &event->memory_configured);
1370   evel_enc_kv_opt_double(jbuf, "memoryUsed", &event->memory_used);
1371   evel_enc_kv_opt_int(jbuf, "requestRate", &event->request_rate);
1372
1373   /***************************************************************************/
1374   /* vNIC Usage                                                              */
1375   /***************************************************************************/
1376   evel_json_checkpoint(jbuf);
1377   if (evel_json_open_opt_named_list(jbuf, "vNicUsageArray"))
1378   {
1379     bool item_added = false;
1380
1381     item = dlist_get_first(&event->vnic_usage);
1382     while (item != NULL)
1383     {
1384       vnic_use = (MEASUREMENT_VNIC_USE *) item->item;
1385       assert(vnic_use != NULL);
1386
1387       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
1388                                           "vNicUsageArray",
1389                                           vnic_use->vnic_id))
1390       {
1391         evel_json_open_object(jbuf);
1392
1393         /*********************************************************************/
1394         /* Mandatory fields.                                                 */
1395         /*********************************************************************/
1396         evel_enc_kv_int(jbuf, "bytesIn", vnic_use->bytes_in);
1397         evel_enc_kv_int(jbuf, "bytesOut", vnic_use->bytes_out);
1398         evel_enc_kv_int(jbuf, "packetsIn", vnic_use->packets_in);
1399         evel_enc_kv_int(jbuf, "packetsOut", vnic_use->packets_out);
1400         evel_enc_kv_string(jbuf, "vNicIdentifier", vnic_use->vnic_id);
1401
1402         /*********************************************************************/
1403         /* Optional fields.                                                  */
1404         /*********************************************************************/
1405         evel_enc_kv_opt_int(
1406           jbuf, "broadcastPacketsIn", &vnic_use->broadcast_packets_in);
1407         evel_enc_kv_opt_int(
1408           jbuf, "broadcastPacketsOut", &vnic_use->broadcast_packets_out);
1409         evel_enc_kv_opt_int(
1410           jbuf, "multicastPacketsIn", &vnic_use->multicast_packets_in);
1411         evel_enc_kv_opt_int(
1412           jbuf, "multicastPacketsOut", &vnic_use->multicast_packets_out);
1413         evel_enc_kv_opt_int(
1414           jbuf, "unicastPacketsIn", &vnic_use->unicast_packets_in);
1415         evel_enc_kv_opt_int(
1416           jbuf, "unicastPacketsOut", &vnic_use->unicast_packets_out);
1417
1418         evel_json_close_object(jbuf);
1419         item_added = true;
1420       }
1421       item = dlist_get_next(item);
1422     }
1423
1424     evel_json_close_list(jbuf);
1425
1426     /*************************************************************************/
1427     /* If we've not written anything, rewind to before we opened the list.   */
1428     /*************************************************************************/
1429     if (!item_added)
1430     {
1431       evel_json_rewind(jbuf);
1432     }
1433   }
1434
1435   evel_enc_kv_opt_double(
1436     jbuf, "aggregateCpuUsage", &event->aggregate_cpu_usage);
1437   evel_enc_kv_opt_int(
1438     jbuf, "numberOfMediaPortsInUse", &event->media_ports_in_use);
1439   evel_enc_kv_opt_double(
1440     jbuf, "vnfcScalingMetric", &event->vnfc_scaling_metric);
1441
1442   /***************************************************************************/
1443   /* Errors list.                                                            */
1444   /***************************************************************************/
1445   if ((event->errors != NULL) &&
1446       evel_json_open_opt_named_object(jbuf, "errors"))
1447   {
1448     errors = event->errors;
1449     evel_enc_kv_int(jbuf, "receiveDiscards", errors->receive_discards);
1450     evel_enc_kv_int(jbuf, "receiveErrors", errors->receive_errors);
1451     evel_enc_kv_int(jbuf, "transmitDiscards", errors->transmit_discards);
1452     evel_enc_kv_int(jbuf, "transmitErrors", errors->transmit_errors);
1453     evel_json_close_object(jbuf);
1454   }
1455
1456   /***************************************************************************/
1457   /* Feature Utilization list.                                               */
1458   /***************************************************************************/
1459   evel_json_checkpoint(jbuf);
1460   if (evel_json_open_opt_named_list(jbuf, "featureUsageArray"))
1461   {
1462     bool item_added = false;
1463
1464     item = dlist_get_first(&event->feature_usage);
1465     while (item != NULL)
1466     {
1467       feature_use = (MEASUREMENT_FEATURE_USE*) item->item;
1468       assert(feature_use != NULL);
1469
1470       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
1471                                           "featureUsageArray",
1472                                           feature_use->feature_id))
1473       {
1474         evel_json_open_object(jbuf);
1475         evel_enc_kv_string(jbuf, "featureIdentifier", feature_use->feature_id);
1476         evel_enc_kv_int(
1477           jbuf, "featureUtilization", feature_use->feature_utilization);
1478         evel_json_close_object(jbuf);
1479         item_added = true;
1480       }
1481       item = dlist_get_next(item);
1482     }
1483     evel_json_close_list(jbuf);
1484
1485     /*************************************************************************/
1486     /* If we've not written anything, rewind to before we opened the list.   */
1487     /*************************************************************************/
1488     if (!item_added)
1489     {
1490       evel_json_rewind(jbuf);
1491     }
1492   }
1493
1494   /***************************************************************************/
1495   /* Codec Utilization list.                                                 */
1496   /***************************************************************************/
1497   evel_json_checkpoint(jbuf);
1498   if (evel_json_open_opt_named_list(jbuf, "codecUsageArray"))
1499   {
1500     bool item_added = false;
1501
1502     item = dlist_get_first(&event->codec_usage);
1503     while (item != NULL)
1504     {
1505       codec_use = (MEASUREMENT_CODEC_USE*) item->item;
1506       assert(codec_use != NULL);
1507
1508       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
1509                                           "codecUsageArray",
1510                                           codec_use->codec_id))
1511       {
1512         evel_json_open_object(jbuf);
1513         evel_enc_kv_string(jbuf, "codecIdentifier", codec_use->codec_id);
1514         evel_enc_kv_int(jbuf, "numberInUse", codec_use->number_in_use);
1515         evel_json_close_object(jbuf);
1516         item_added = true;
1517       }
1518       item = dlist_get_next(item);
1519     }
1520     evel_json_close_list(jbuf);
1521
1522     /*************************************************************************/
1523     /* If we've not written anything, rewind to before we opened the list.   */
1524     /*************************************************************************/
1525     if (!item_added)
1526     {
1527       evel_json_rewind(jbuf);
1528     }
1529   }
1530
1531   /***************************************************************************/
1532   /* Additional Measurement Groups list.                                     */
1533   /***************************************************************************/
1534   evel_json_checkpoint(jbuf);
1535   if (evel_json_open_opt_named_list(jbuf, "additionalMeasurements"))
1536   {
1537     bool item_added = false;
1538
1539     item = dlist_get_first(&event->additional_measurements);
1540     while (item != NULL)
1541     {
1542       measurement_group = (MEASUREMENT_GROUP *) item->item;
1543       assert(measurement_group != NULL);
1544
1545       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
1546                                           "additionalMeasurements",
1547                                           measurement_group->name))
1548       {
1549         evel_json_open_object(jbuf);
1550         evel_enc_kv_string(jbuf, "name", measurement_group->name);
1551         evel_json_open_opt_named_list(jbuf, "measurements");
1552
1553         /*********************************************************************/
1554         /* Measurements list.                                                */
1555         /*********************************************************************/
1556         nested_item = dlist_get_first(&measurement_group->measurements);
1557         while (nested_item != NULL)
1558         {
1559           custom_measurement = (CUSTOM_MEASUREMENT *) nested_item->item;
1560           assert(custom_measurement != NULL);
1561
1562           evel_json_open_object(jbuf);
1563           evel_enc_kv_string(jbuf, "name", custom_measurement->name);
1564           evel_enc_kv_string(jbuf, "value", custom_measurement->value);
1565           evel_json_close_object(jbuf);
1566           nested_item = dlist_get_next(nested_item);
1567         }
1568         evel_json_close_list(jbuf);
1569         evel_json_close_object(jbuf);
1570         item_added = true;
1571       }
1572       item = dlist_get_next(item);
1573     }
1574     evel_json_close_list(jbuf);
1575
1576     /*************************************************************************/
1577     /* If we've not written anything, rewind to before we opened the list.   */
1578     /*************************************************************************/
1579     if (!item_added)
1580     {
1581       evel_json_rewind(jbuf);
1582     }
1583   }
1584
1585   /***************************************************************************/
1586   /* Although optional, we always generate the version.  Note that this      */
1587   /* closes the object, too.                                                 */
1588   /***************************************************************************/
1589   evel_enc_version(jbuf,
1590                    "measurementsForVfScalingVersion",
1591                    event->major_version,
1592                    event->major_version);
1593   evel_json_close_object(jbuf);
1594
1595   EVEL_EXIT();
1596 }
1597
1598 /**************************************************************************//**
1599  * Free a Measurement.
1600  *
1601  * Free off the Measurement supplied.  Will free all the contained allocated
1602  * memory.
1603  *
1604  * @note It does not free the Measurement itself, since that may be part of a
1605  * larger structure.
1606  *****************************************************************************/
1607 void evel_free_measurement(EVENT_MEASUREMENT * event)
1608 {
1609   MEASUREMENT_CPU_USE * cpu_use = NULL;
1610   MEASUREMENT_FSYS_USE * fsys_use = NULL;
1611   MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
1612   MEASUREMENT_VNIC_USE * vnic_use = NULL;
1613   MEASUREMENT_FEATURE_USE * feature_use = NULL;
1614   MEASUREMENT_CODEC_USE * codec_use = NULL;
1615   MEASUREMENT_GROUP * measurement_group = NULL;
1616   CUSTOM_MEASUREMENT * measurement = NULL;
1617
1618   EVEL_ENTER();
1619
1620   /***************************************************************************/
1621   /* Check preconditions.  As an internal API we don't allow freeing NULL    */
1622   /* events as we do on the public API.                                      */
1623   /***************************************************************************/
1624   assert(event != NULL);
1625   assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
1626
1627   /***************************************************************************/
1628   /* Free all internal strings then the header itself.                       */
1629   /***************************************************************************/
1630   cpu_use = dlist_pop_last(&event->cpu_usage);
1631   while (cpu_use != NULL)
1632   {
1633     EVEL_DEBUG("Freeing CPU use Info (%s)", cpu_use->id);
1634     free(cpu_use->id);
1635     free(cpu_use);
1636     cpu_use = dlist_pop_last(&event->cpu_usage);
1637   }
1638
1639   fsys_use = dlist_pop_last(&event->filesystem_usage);
1640   while (fsys_use != NULL)
1641   {
1642     EVEL_DEBUG("Freeing Filesystem Use info (%s)", fsys_use->filesystem_name);
1643     free(fsys_use->filesystem_name);
1644     free(fsys_use);
1645     fsys_use = dlist_pop_last(&event->filesystem_usage);
1646   }
1647
1648   bucket = dlist_pop_last(&event->latency_distribution);
1649   while (bucket != NULL)
1650   {
1651     EVEL_DEBUG("Freeing Latency Bucket");
1652     free(bucket);
1653     bucket = dlist_pop_last(&event->latency_distribution);
1654   }
1655
1656   vnic_use = dlist_pop_last(&event->vnic_usage);
1657   while (vnic_use != NULL)
1658   {
1659     EVEL_DEBUG("Freeing vNIC use Info (%s)", vnic_use->vnic_id);
1660     evel_free_measurement_vnic_use(vnic_use);
1661     free(vnic_use);
1662     vnic_use = dlist_pop_last(&event->vnic_usage);
1663   }
1664
1665   codec_use = dlist_pop_last(&event->codec_usage);
1666   while (codec_use != NULL)
1667   {
1668     EVEL_DEBUG("Freeing Codec use Info (%s)", codec_use->codec_id);
1669     free(codec_use->codec_id);
1670     free(codec_use);
1671     codec_use = dlist_pop_last(&event->codec_usage);
1672   }
1673
1674   if (event->errors != NULL)
1675   {
1676     EVEL_DEBUG("Freeing Errors");
1677     free(event->errors);
1678   }
1679
1680   feature_use = dlist_pop_last(&event->feature_usage);
1681   while (feature_use != NULL)
1682   {
1683     EVEL_DEBUG("Freeing Feature use Info (%s)", feature_use->feature_id);
1684     free(feature_use->feature_id);
1685     free(feature_use);
1686     feature_use = dlist_pop_last(&event->feature_usage);
1687   }
1688
1689   measurement_group = dlist_pop_last(&event->additional_measurements);
1690   while (measurement_group != NULL)
1691   {
1692     EVEL_DEBUG("Freeing Measurement Group (%s)", measurement_group->name);
1693
1694     measurement = dlist_pop_last(&measurement_group->measurements);
1695     while (measurement != NULL)
1696     {
1697       EVEL_DEBUG("Freeing Measurement (%s)", measurement->name);
1698       free(measurement->name);
1699       free(measurement->value);
1700       free(measurement);
1701       measurement = dlist_pop_last(&measurement_group->measurements);
1702     }
1703     free(measurement_group->name);
1704     free(measurement_group);
1705     measurement_group = dlist_pop_last(&event->additional_measurements);
1706   }
1707
1708   evel_free_header(&event->header);
1709
1710   EVEL_EXIT();
1711 }