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