9fbf3926617f799345bef3a1942d07c58fe974f5
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / evel_library / evel_event.c
1 /**************************************************************************//**
2  * @file
3  * Implementation of EVEL functions relating to Event Headers - since
4  * Heartbeats only contain the Event Header, the Heartbeat factory function is
5  * here too.
6  *
7  * License
8  * -------
9  *
10  * Copyright(c) <2016>, AT&T Intellectual Property.  All other rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright notice,
18  *    this list of conditions and the following disclaimer in the documentation
19  *    and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:  This product includes
22  *    software developed by the AT&T.
23  * 4. Neither the name of AT&T nor the names of its contributors may be used to
24  *    endorse or promote products derived from this software without specific
25  *    prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
28  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30  * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
31  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *****************************************************************************/
38
39 #include <string.h>
40 #include <assert.h>
41 #include <stdlib.h>
42 #include <sys/time.h>
43
44 #include "evel.h"
45 #include "evel_internal.h"
46 #include "evel_throttle.h"
47 #include "metadata.h"
48
49 /**************************************************************************//**
50  * Unique sequence number for events from this VNF.
51  *****************************************************************************/
52 static int event_sequence = 1;
53
54 /**************************************************************************//**
55  * Set the next event_sequence to use.
56  *
57  * @param sequence      The next sequence number to use.
58  *****************************************************************************/
59 void evel_set_next_event_sequence(const int sequence)
60 {
61   EVEL_ENTER();
62
63   EVEL_INFO("Setting event sequence to %d, was %d ", sequence, event_sequence);
64   event_sequence = sequence;
65
66   EVEL_EXIT();
67 }
68
69 /**************************************************************************//**
70  * Create a new heartbeat event.
71  *
72  * @note that the heartbeat is just a "naked" commonEventHeader!
73  *
74  * @returns pointer to the newly manufactured ::EVENT_HEADER.  If the event is
75  *          not used it must be released using ::evel_free_event
76  * @retval  NULL  Failed to create the event.
77  *****************************************************************************/
78 EVENT_HEADER * evel_new_heartbeat()
79 {
80   EVENT_HEADER * heartbeat = NULL;
81   EVEL_ENTER();
82
83   /***************************************************************************/
84   /* Allocate the header.                                                    */
85   /***************************************************************************/
86   heartbeat = malloc(sizeof(EVENT_HEADER));
87   if (heartbeat == NULL)
88   {
89     log_error_state("Out of memory");
90     goto exit_label;
91   }
92   memset(heartbeat, 0, sizeof(EVENT_HEADER));
93
94   /***************************************************************************/
95   /* Initialize the header.  Get a new event sequence number.  Note that if  */
96   /* any memory allocation fails in here we will fail gracefully because     */
97   /* everything downstream can cope with NULLs.                              */
98   /***************************************************************************/
99   evel_init_header(heartbeat,"Heartbeat");
100   evel_force_option_string(&heartbeat->event_type, "Autonomous heartbeat");
101
102 exit_label:
103   EVEL_EXIT();
104   return heartbeat;
105 }
106
107 /**************************************************************************//**
108  * Initialize a newly created event header.
109  *
110  * @param header  Pointer to the header being initialized.
111  *****************************************************************************/
112 void evel_init_header(EVENT_HEADER * const header,const char *const eventname)
113 {
114   char scratchpad[EVEL_MAX_STRING_LEN + 1] = {0};
115   struct timeval tv;
116
117   EVEL_ENTER();
118
119   assert(header != NULL);
120
121   gettimeofday(&tv, NULL);
122
123   /***************************************************************************/
124   /* Initialize the header.  Get a new event sequence number.  Note that if  */
125   /* any memory allocation fails in here we will fail gracefully because     */
126   /* everything downstream can cope with NULLs.                              */
127   /***************************************************************************/
128   header->event_domain = EVEL_DOMAIN_HEARTBEAT;
129   snprintf(scratchpad, EVEL_MAX_STRING_LEN, "%d", event_sequence);
130   header->event_id = strdup(scratchpad);
131   if( eventname == NULL )
132      header->event_name = strdup(functional_role);
133   else
134      header->event_name = strdup(eventname);
135   header->last_epoch_microsec = tv.tv_usec + 1000000 * tv.tv_sec;
136   header->priority = EVEL_PRIORITY_NORMAL;
137   header->reporting_entity_name = strdup(openstack_vm_name());
138   header->source_name = strdup(openstack_vm_name());
139   header->sequence = event_sequence;
140   header->start_epoch_microsec = header->last_epoch_microsec;
141   header->major_version = EVEL_HEADER_MAJOR_VERSION;
142   header->minor_version = EVEL_HEADER_MINOR_VERSION;
143   event_sequence++;
144
145   /***************************************************************************/
146   /* Optional parameters.                                                    */
147   /***************************************************************************/
148   evel_init_option_string(&header->event_type);
149   evel_init_option_string(&header->nfcnaming_code);
150   evel_init_option_string(&header->nfnaming_code);
151   evel_force_option_string(&header->reporting_entity_id, openstack_vm_uuid());
152   evel_force_option_string(&header->source_id, openstack_vm_uuid());
153   evel_init_option_intheader(&header->internal_field);
154
155   EVEL_EXIT();
156 }
157
158 /**************************************************************************//**
159  * Set the Event Type property of the event header.
160  *
161  * @note  The property is treated as immutable: it is only valid to call
162  *        the setter once.  However, we don't assert if the caller tries to
163  *        overwrite, just ignoring the update instead.
164  *
165  * @param header        Pointer to the ::EVENT_HEADER.
166  * @param type          The Event Type to be set. ASCIIZ string. The caller
167  *                      does not need to preserve the value once the function
168  *                      returns.
169  *****************************************************************************/
170 void evel_header_type_set(EVENT_HEADER * const header,
171                           const char * const type)
172 {
173   EVEL_ENTER();
174
175   /***************************************************************************/
176   /* Check preconditions.                                                    */
177   /***************************************************************************/
178   assert(header != NULL);
179   assert(type != NULL);
180
181   evel_set_option_string(&header->event_type, type, "Event Type");
182
183   EVEL_EXIT();
184 }
185
186 /**************************************************************************//**
187  * Set the Start Epoch property of the event header.
188  *
189  * @note The Start Epoch defaults to the time of event creation.
190  *
191  * @param header        Pointer to the ::EVENT_HEADER.
192  * @param start_epoch_microsec
193  *                      The start epoch to set, in microseconds.
194  *****************************************************************************/
195 void evel_start_epoch_set(EVENT_HEADER * const header,
196                           const unsigned long long start_epoch_microsec)
197 {
198   EVEL_ENTER();
199
200   /***************************************************************************/
201   /* Check preconditions and assign the new value.                           */
202   /***************************************************************************/
203   assert(header != NULL);
204   header->start_epoch_microsec = start_epoch_microsec;
205
206   EVEL_EXIT();
207 }
208
209 /**************************************************************************//**
210  * Set the Last Epoch property of the event header.
211  *
212  * @note The Last Epoch defaults to the time of event creation.
213  *
214  * @param header        Pointer to the ::EVENT_HEADER.
215  * @param last_epoch_microsec
216  *                      The last epoch to set, in microseconds.
217  *****************************************************************************/
218 void evel_last_epoch_set(EVENT_HEADER * const header,
219                          const unsigned long long last_epoch_microsec)
220 {
221   EVEL_ENTER();
222
223   /***************************************************************************/
224   /* Check preconditions and assign the new value.                           */
225   /***************************************************************************/
226   assert(header != NULL);
227   header->last_epoch_microsec = last_epoch_microsec;
228
229   EVEL_EXIT();
230 }
231
232 /**************************************************************************//**
233  * Set the NFC Naming code property of the event header.
234  *
235  * @param header        Pointer to the ::EVENT_HEADER.
236  * @param nfcnamingcode String
237  *****************************************************************************/
238 void evel_nfcnamingcode_set(EVENT_HEADER * const header,
239                          const char * const nfcnam)
240 {
241   EVEL_ENTER();
242
243   /***************************************************************************/
244   /* Check preconditions and assign the new value.                           */
245   /***************************************************************************/
246   assert(header != NULL);
247   assert(nfcnam != NULL);
248   evel_set_option_string(&header->nfcnaming_code, nfcnam, "NFC Naming Code");
249
250   EVEL_EXIT();
251 }
252
253 /**************************************************************************//**
254  * Set the NF Naming code property of the event header.
255  *
256  * @param header        Pointer to the ::EVENT_HEADER.
257  * @param nfnamingcode String
258  *****************************************************************************/
259 void evel_nfnamingcode_set(EVENT_HEADER * const header,
260                          const char * const nfnam)
261 {
262   EVEL_ENTER();
263
264   /***************************************************************************/
265   /* Check preconditions and assign the new value.                           */
266   /***************************************************************************/
267   assert(header != NULL);
268   assert(nfnam != NULL);
269   evel_set_option_string(&header->nfnaming_code, nfnam, "NF Naming Code");
270
271   EVEL_EXIT();
272 }
273
274
275 /**************************************************************************//**
276  * Set the Reporting Entity Name property of the event header.
277  *
278  * @note The Reporting Entity Name defaults to the OpenStack VM Name.
279  *
280  * @param header        Pointer to the ::EVENT_HEADER.
281  * @param entity_name   The entity name to set.
282  *****************************************************************************/
283 void evel_reporting_entity_name_set(EVENT_HEADER * const header,
284                                     const char * const entity_name)
285 {
286   EVEL_ENTER();
287
288   /***************************************************************************/
289   /* Check preconditions and assign the new value.                           */
290   /***************************************************************************/
291   assert(header != NULL);
292   assert(entity_name != NULL);
293   assert(header->reporting_entity_name != NULL);
294
295   /***************************************************************************/
296   /* Free the previously allocated memory and replace it with a copy of the  */
297   /* provided one.                                                           */
298   /***************************************************************************/
299   free(header->reporting_entity_name);
300   header->reporting_entity_name = strdup(entity_name);
301
302   EVEL_EXIT();
303 }
304
305 /**************************************************************************//**
306  * Set the Reporting Entity Id property of the event header.
307  *
308  * @note The Reporting Entity Id defaults to the OpenStack VM UUID.
309  *
310  * @param header        Pointer to the ::EVENT_HEADER.
311  * @param entity_id     The entity id to set.
312  *****************************************************************************/
313 void evel_reporting_entity_id_set(EVENT_HEADER * const header,
314                                   const char * const entity_id)
315 {
316   EVEL_ENTER();
317
318   /***************************************************************************/
319   /* Check preconditions and assign the new value.                           */
320   /***************************************************************************/
321   assert(header != NULL);
322   assert(entity_id != NULL);
323
324   /***************************************************************************/
325   /* Free the previously allocated memory and replace it with a copy of the  */
326   /* provided one.  Note that evel_force_option_string strdups entity_id.    */
327   /***************************************************************************/
328   evel_free_option_string(&header->reporting_entity_id);
329   evel_force_option_string(&header->reporting_entity_id, entity_id);
330
331   EVEL_EXIT();
332 }
333
334 /**************************************************************************//**
335  * Encode the event as a JSON event object according to AT&T's schema.
336  *
337  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
338  * @param event         Pointer to the ::EVENT_HEADER to encode.
339  *****************************************************************************/
340 void evel_json_encode_header(EVEL_JSON_BUFFER * jbuf,
341                              EVENT_HEADER * event)
342 {
343   char * domain;
344   char * priority;
345
346   EVEL_ENTER();
347
348   /***************************************************************************/
349   /* Check preconditions.                                                    */
350   /***************************************************************************/
351   assert(jbuf != NULL);
352   assert(jbuf->json != NULL);
353   assert(jbuf->max_size > 0);
354   assert(event != NULL);
355
356   domain = evel_event_domain(event->event_domain);
357   priority = evel_event_priority(event->priority);
358   evel_json_open_named_object(jbuf, "commonEventHeader");
359
360   /***************************************************************************/
361   /* Mandatory fields.                                                       */
362   /***************************************************************************/
363   evel_enc_kv_string(jbuf, "domain", domain);
364   evel_enc_kv_string(jbuf, "eventId", event->event_id);
365   evel_enc_kv_string(jbuf, "eventName", event->event_name);
366   evel_enc_kv_ull(jbuf, "lastEpochMicrosec", event->last_epoch_microsec);
367   evel_enc_kv_string(jbuf, "priority", priority);
368   evel_enc_kv_string(
369     jbuf, "reportingEntityName", event->reporting_entity_name);
370   evel_enc_kv_int(jbuf, "sequence", event->sequence);
371   evel_enc_kv_string(jbuf, "sourceName", event->source_name);
372   evel_enc_kv_ull(jbuf, "startEpochMicrosec", event->start_epoch_microsec);
373   evel_enc_version(
374     jbuf, "version", event->major_version, event->minor_version);
375
376   /***************************************************************************/
377   /* Optional fields.                                                        */
378   /***************************************************************************/
379   evel_enc_kv_opt_string(jbuf, "eventType", &event->event_type);
380   evel_enc_kv_opt_string(
381     jbuf, "reportingEntityId", &event->reporting_entity_id);
382   evel_enc_kv_opt_string(jbuf, "sourceId", &event->source_id);
383   evel_enc_kv_opt_string(jbuf, "nfcNamingCode", &event->nfcnaming_code);
384   evel_enc_kv_opt_string(jbuf, "nfNamingCode", &event->nfnaming_code);
385
386   evel_json_close_object(jbuf);
387
388   EVEL_EXIT();
389 }
390
391 /**************************************************************************//**
392  * Free an event header.
393  *
394  * Free off the event header supplied.  Will free all the contained allocated
395  * memory.
396  *
397  * @note It does not free the header itself, since that may be part of a
398  * larger structure.
399  *****************************************************************************/
400 void evel_free_header(EVENT_HEADER * const event)
401 {
402   EVEL_ENTER();
403
404   /***************************************************************************/
405   /* Check preconditions.  As an internal API we don't allow freeing NULL    */
406   /* events as we do on the public API.                                      */
407   /***************************************************************************/
408   assert(event != NULL);
409
410   /***************************************************************************/
411   /* Free all internal strings.                                              */
412   /***************************************************************************/
413   free(event->event_id);
414   evel_free_option_string(&event->event_type);
415   free(event->event_name);
416   evel_free_option_string(&event->reporting_entity_id);
417   free(event->reporting_entity_name);
418   evel_free_option_string(&event->source_id);
419   evel_free_option_string(&event->nfcnaming_code);
420   evel_free_option_string(&event->nfnaming_code);
421   evel_free_option_intheader(&event->internal_field);
422   free(event->source_name);
423
424   EVEL_EXIT();
425 }
426
427 /**************************************************************************//**
428  * Encode the event as a JSON event object according to AT&T's schema.
429  *
430  * @param json      Pointer to where to store the JSON encoded data.
431  * @param max_size  Size of storage available in json_body.
432  * @param event     Pointer to the ::EVENT_HEADER to encode.
433  * @returns Number of bytes actually written.
434  *****************************************************************************/
435 int evel_json_encode_event(char * json,
436                            int max_size,
437                            EVENT_HEADER * event)
438 {
439   EVEL_JSON_BUFFER json_buffer;
440   EVEL_JSON_BUFFER * jbuf = &json_buffer;
441   EVEL_THROTTLE_SPEC * throttle_spec;
442
443   EVEL_ENTER();
444
445   /***************************************************************************/
446   /* Get the latest throttle specification for the domain.                   */
447   /***************************************************************************/
448   throttle_spec = evel_get_throttle_spec(event->event_domain);
449
450   /***************************************************************************/
451   /* Initialize the JSON_BUFFER and open the top-level objects.              */
452   /***************************************************************************/
453   evel_json_buffer_init(jbuf, json, max_size, throttle_spec);
454   evel_json_open_object(jbuf);
455   evel_json_open_named_object(jbuf, "event");
456
457   switch (event->event_domain)
458   {
459     case EVEL_DOMAIN_HEARTBEAT:
460       evel_json_encode_header(jbuf, event);
461       break;
462
463     case EVEL_DOMAIN_FAULT:
464       evel_json_encode_fault(jbuf, (EVENT_FAULT *)event);
465       break;
466
467     case EVEL_DOMAIN_MEASUREMENT:
468       evel_json_encode_measurement(jbuf, (EVENT_MEASUREMENT *)event);
469       break;
470
471     case EVEL_DOMAIN_MOBILE_FLOW:
472       evel_json_encode_mobile_flow(jbuf, (EVENT_MOBILE_FLOW *)event);
473       break;
474
475     case EVEL_DOMAIN_REPORT:
476       evel_json_encode_report(jbuf, (EVENT_REPORT *)event);
477       break;
478
479     case EVEL_DOMAIN_HEARTBEAT_FIELD:
480       evel_json_encode_hrtbt_field(jbuf, (EVENT_HEARTBEAT_FIELD *)event);
481       break;
482
483     case EVEL_DOMAIN_SIPSIGNALING:
484       evel_json_encode_signaling(jbuf, (EVENT_SIGNALING *)event);
485       break;
486
487     case EVEL_DOMAIN_STATE_CHANGE:
488       evel_json_encode_state_change(jbuf, (EVENT_STATE_CHANGE *)event);
489       break;
490
491     case EVEL_DOMAIN_SYSLOG:
492       evel_json_encode_syslog(jbuf, (EVENT_SYSLOG *)event);
493       break;
494
495     case EVEL_DOMAIN_OTHER:
496       evel_json_encode_other(jbuf, (EVENT_OTHER *)event);
497       break;
498
499     case EVEL_DOMAIN_VOICE_QUALITY:
500       evel_json_encode_other(jbuf, (EVENT_VOICE_QUALITY *)event);
501       break;
502
503     case EVEL_DOMAIN_INTERNAL:
504     default:
505       EVEL_ERROR("Unexpected domain %d", event->event_domain);
506       assert(0);
507   }
508
509   evel_json_close_object(jbuf);
510   evel_json_close_object(jbuf);
511
512   /***************************************************************************/
513   /* Sanity check.                                                           */
514   /***************************************************************************/
515   assert(jbuf->depth == 0);
516
517   EVEL_EXIT();
518
519   return jbuf->offset;
520 }
521
522
523 /**************************************************************************//**
524  * Initialize an event instance id.
525  *
526  * @param vfield        Pointer to the event vnfname field being initialized.
527  * @param vendor_id     The vendor id to encode in the event instance id.
528  * @param event_id      The event id to encode in the event instance id.
529  *****************************************************************************/
530 void evel_init_vendor_field(VENDOR_VNFNAME_FIELD * const vfield,
531                                  const char * const vendor_name)
532 {
533   EVEL_ENTER();
534
535   /***************************************************************************/
536   /* Check preconditions.                                                    */
537   /***************************************************************************/
538   assert(vfield != NULL);
539   assert(vendor_name != NULL);
540
541   /***************************************************************************/
542   /* Store the mandatory parts.                                              */
543   /***************************************************************************/
544   vfield->vendorname = strdup(vendor_name);
545   evel_init_option_string(&vfield->vfmodule);
546   evel_init_option_string(&vfield->vnfname);
547
548   /***************************************************************************/
549   /* Initialize the optional parts.                                          */
550   /***************************************************************************/
551
552   EVEL_EXIT();
553 }
554
555 /**************************************************************************//**
556  * Set the Vendor module property of the Vendor.
557  *
558  * @note  The property is treated as immutable: it is only valid to call
559  *        the setter once.  However, we don't assert if the caller tries to
560  *        overwrite, just ignoring the update instead.
561  *
562  * @param vfield        Pointer to the Vendor field.
563  * @param module_name   The module name to be set. ASCIIZ string. The caller
564  *                      does not need to preserve the value once the function
565  *                      returns.
566  *****************************************************************************/
567 void evel_vendor_field_module_set(VENDOR_VNFNAME_FIELD * const vfield,
568                                     const char * const module_name)
569 {
570   EVEL_ENTER();
571
572   /***************************************************************************/
573   /* Check preconditions.                                                    */
574   /***************************************************************************/
575   assert(vfield != NULL);
576   assert(module_name != NULL);
577
578   evel_set_option_string(&vfield->vfmodule, module_name, "Module name set");
579
580   EVEL_EXIT();
581 }
582
583 /**************************************************************************//**
584  * Set the Vendor module property of the Vendor.
585  *
586  * @note  The property is treated as immutable: it is only valid to call
587  *        the setter once.  However, we don't assert if the caller tries to
588  *        overwrite, just ignoring the update instead.
589  *
590  * @param vfield        Pointer to the Vendor field.
591  * @param module_name   The module name to be set. ASCIIZ string. The caller
592  *                      does not need to preserve the value once the function
593  *                      returns.
594  *****************************************************************************/
595 void evel_vendor_field_vnfname_set(VENDOR_VNFNAME_FIELD * const vfield,
596                                     const char * const vnfname)
597 {
598   EVEL_ENTER();
599
600   /***************************************************************************/
601   /* Check preconditions.                                                    */
602   /***************************************************************************/
603   assert(vfield != NULL);
604   assert(vnfname != NULL);
605
606   evel_set_option_string(&vfield->vnfname, vnfname, "Virtual Network Function name set");
607
608   EVEL_EXIT();
609 }
610
611 /**************************************************************************//**
612  * Free an event instance id.
613  *
614  * @param vfield   Pointer to the event vnfname_field being freed.
615  *****************************************************************************/
616 void evel_free_event_vendor_field(VENDOR_VNFNAME_FIELD * const vfield)
617 {
618   EVEL_ENTER();
619
620   /***************************************************************************/
621   /* Check preconditions.                                                    */
622   /***************************************************************************/
623   assert(vfield->vendorname != NULL);
624
625   /***************************************************************************/
626   /* Free everything.                                                        */
627   /***************************************************************************/
628   evel_free_option_string(&vfield->vfmodule);
629   evel_free_option_string(&vfield->vnfname);
630   free(vfield->vendorname);
631
632   EVEL_EXIT();
633 }
634
635 /**************************************************************************//**
636  * Encode the instance id as a JSON object according to AT&T's schema.
637  *
638  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
639  * @param vfield        Pointer to the ::VENDOR_VNFNAME_FIELD to encode.
640  *****************************************************************************/
641 void evel_json_encode_vendor_field(EVEL_JSON_BUFFER * jbuf,
642                                   VENDOR_VNFNAME_FIELD * vfield)
643 {
644   EVEL_ENTER();
645
646   /***************************************************************************/
647   /* Check preconditions.                                                    */
648   /***************************************************************************/
649   assert(jbuf != NULL);
650   assert(jbuf->json != NULL);
651   assert(jbuf->max_size > 0);
652   assert(vfield != NULL);
653   assert(vfield->vendorname != NULL);
654
655   evel_json_open_named_object(jbuf, "vendorVnfNamedFields");
656
657   /***************************************************************************/
658   /* Mandatory fields.                                                       */
659   /***************************************************************************/
660   evel_enc_kv_string(jbuf, "vendorName", vfield->vendorname);
661   evel_enc_kv_opt_string(jbuf, "vfModuleName", &vfield->vfmodule);
662   evel_enc_kv_opt_string(jbuf, "vnfName", &vfield->vnfname);
663
664   /***************************************************************************/
665   /* Optional fields.                                                        */
666   /***************************************************************************/
667
668   evel_json_close_object(jbuf);
669
670   EVEL_EXIT();
671 }