Add License to VES library
[demo.git] / vnfs / VES / 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 © 2017 AT&T Intellectual Property. All rights reserved.
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *        http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *****************************************************************************/
23
24 #include <string.h>
25 #include <assert.h>
26 #include <stdlib.h>
27 #include <sys/time.h>
28
29 #include "evel.h"
30 #include "evel_internal.h"
31 #include "evel_throttle.h"
32 #include "metadata.h"
33
34 /**************************************************************************//**
35  * Unique sequence number for events from this VNF.
36  *****************************************************************************/
37 static int event_sequence = 1;
38
39 /**************************************************************************//**
40  * Set the next event_sequence to use.
41  *
42  * @param sequence      The next sequence number to use.
43  *****************************************************************************/
44 void evel_set_next_event_sequence(const int sequence)
45 {
46   EVEL_ENTER();
47
48   EVEL_INFO("Setting event sequence to %d, was %d ", sequence, event_sequence);
49   event_sequence = sequence;
50
51   EVEL_EXIT();
52 }
53
54 /**************************************************************************//**
55  * Create a new heartbeat event.
56  *
57  * @note that the heartbeat is just a "naked" commonEventHeader!
58  *
59  * @returns pointer to the newly manufactured ::EVENT_HEADER.  If the event is
60  *          not used it must be released using ::evel_free_event
61  * @retval  NULL  Failed to create the event.
62  *****************************************************************************/
63 EVENT_HEADER * evel_new_heartbeat()
64 {
65   EVENT_HEADER * heartbeat = NULL;
66   EVEL_ENTER();
67
68   /***************************************************************************/
69   /* Allocate the header.                                                    */
70   /***************************************************************************/
71   heartbeat = malloc(sizeof(EVENT_HEADER));
72   if (heartbeat == NULL)
73   {
74     log_error_state("Out of memory");
75     goto exit_label;
76   }
77   memset(heartbeat, 0, sizeof(EVENT_HEADER));
78
79   /***************************************************************************/
80   /* Initialize the header.  Get a new event sequence number.  Note that if  */
81   /* any memory allocation fails in here we will fail gracefully because     */
82   /* everything downstream can cope with NULLs.                              */
83   /***************************************************************************/
84   evel_init_header(heartbeat);
85   evel_force_option_string(&heartbeat->event_type, "Autonomous heartbeat");
86
87 exit_label:
88   EVEL_EXIT();
89   return heartbeat;
90 }
91
92 /**************************************************************************//**
93  * Initialize a newly created event header.
94  *
95  * @param header  Pointer to the header being initialized.
96  *****************************************************************************/
97 void evel_init_header(EVENT_HEADER * const header)
98 {
99   char scratchpad[EVEL_MAX_STRING_LEN + 1] = {0};
100   struct timeval tv;
101
102   EVEL_ENTER();
103
104   assert(header != NULL);
105
106   gettimeofday(&tv, NULL);
107
108   /***************************************************************************/
109   /* Initialize the header.  Get a new event sequence number.  Note that if  */
110   /* any memory allocation fails in here we will fail gracefully because     */
111   /* everything downstream can cope with NULLs.                              */
112   /***************************************************************************/
113   header->event_domain = EVEL_DOMAIN_HEARTBEAT;
114   snprintf(scratchpad, EVEL_MAX_STRING_LEN, "%d", event_sequence);
115   header->event_id = strdup(scratchpad);
116   header->functional_role = strdup(functional_role);
117   header->last_epoch_microsec = tv.tv_usec + 1000000 * tv.tv_sec;
118   header->priority = EVEL_PRIORITY_NORMAL;
119   header->reporting_entity_name = strdup(openstack_vm_name());
120   header->source_name = strdup(openstack_vm_name());
121   header->sequence = event_sequence;
122   header->start_epoch_microsec = header->last_epoch_microsec;
123   header->major_version = EVEL_HEADER_MAJOR_VERSION;
124   header->minor_version = EVEL_HEADER_MINOR_VERSION;
125   event_sequence++;
126
127   /***************************************************************************/
128   /* Optional parameters.                                                    */
129   /***************************************************************************/
130   evel_init_option_string(&header->event_type);
131   evel_force_option_string(&header->reporting_entity_id, openstack_vm_uuid());
132   evel_force_option_string(&header->source_id, openstack_vm_uuid());
133
134   EVEL_EXIT();
135 }
136
137 /**************************************************************************//**
138  * Set the Event Type property of the event header.
139  *
140  * @note  The property is treated as immutable: it is only valid to call
141  *        the setter once.  However, we don't assert if the caller tries to
142  *        overwrite, just ignoring the update instead.
143  *
144  * @param header        Pointer to the ::EVENT_HEADER.
145  * @param type          The Event Type to be set. ASCIIZ string. The caller
146  *                      does not need to preserve the value once the function
147  *                      returns.
148  *****************************************************************************/
149 void evel_header_type_set(EVENT_HEADER * const header,
150                           const char * const type)
151 {
152   EVEL_ENTER();
153
154   /***************************************************************************/
155   /* Check preconditions.                                                    */
156   /***************************************************************************/
157   assert(header != NULL);
158   assert(type != NULL);
159
160   evel_set_option_string(&header->event_type, type, "Event Type");
161
162   EVEL_EXIT();
163 }
164
165 /**************************************************************************//**
166  * Set the Start Epoch property of the event header.
167  *
168  * @note The Start Epoch defaults to the time of event creation.
169  *
170  * @param header        Pointer to the ::EVENT_HEADER.
171  * @param start_epoch_microsec
172  *                      The start epoch to set, in microseconds.
173  *****************************************************************************/
174 void evel_start_epoch_set(EVENT_HEADER * const header,
175                           const unsigned long long start_epoch_microsec)
176 {
177   EVEL_ENTER();
178
179   /***************************************************************************/
180   /* Check preconditions and assign the new value.                           */
181   /***************************************************************************/
182   assert(header != NULL);
183   header->start_epoch_microsec = start_epoch_microsec;
184
185   EVEL_EXIT();
186 }
187
188 /**************************************************************************//**
189  * Set the Last Epoch property of the event header.
190  *
191  * @note The Last Epoch defaults to the time of event creation.
192  *
193  * @param header        Pointer to the ::EVENT_HEADER.
194  * @param last_epoch_microsec
195  *                      The last epoch to set, in microseconds.
196  *****************************************************************************/
197 void evel_last_epoch_set(EVENT_HEADER * const header,
198                          const unsigned long long last_epoch_microsec)
199 {
200   EVEL_ENTER();
201
202   /***************************************************************************/
203   /* Check preconditions and assign the new value.                           */
204   /***************************************************************************/
205   assert(header != NULL);
206   header->last_epoch_microsec = last_epoch_microsec;
207
208   EVEL_EXIT();
209 }
210
211 /**************************************************************************//**
212  * Set the Reporting Entity Name property of the event header.
213  *
214  * @note The Reporting Entity Name defaults to the OpenStack VM Name.
215  *
216  * @param header        Pointer to the ::EVENT_HEADER.
217  * @param entity_name   The entity name to set.
218  *****************************************************************************/
219 void evel_reporting_entity_name_set(EVENT_HEADER * const header,
220                                     const char * const entity_name)
221 {
222   EVEL_ENTER();
223
224   /***************************************************************************/
225   /* Check preconditions and assign the new value.                           */
226   /***************************************************************************/
227   assert(header != NULL);
228   assert(entity_name != NULL);
229   assert(header->reporting_entity_name != NULL);
230
231   /***************************************************************************/
232   /* Free the previously allocated memory and replace it with a copy of the  */
233   /* provided one.                                                           */
234   /***************************************************************************/
235   free(header->reporting_entity_name);
236   header->reporting_entity_name = strdup(entity_name);
237
238   EVEL_EXIT();
239 }
240
241 /**************************************************************************//**
242  * Set the Reporting Entity Id property of the event header.
243  *
244  * @note The Reporting Entity Id defaults to the OpenStack VM UUID.
245  *
246  * @param header        Pointer to the ::EVENT_HEADER.
247  * @param entity_id     The entity id to set.
248  *****************************************************************************/
249 void evel_reporting_entity_id_set(EVENT_HEADER * const header,
250                                   const char * const entity_id)
251 {
252   EVEL_ENTER();
253
254   /***************************************************************************/
255   /* Check preconditions and assign the new value.                           */
256   /***************************************************************************/
257   assert(header != NULL);
258   assert(entity_id != NULL);
259
260   /***************************************************************************/
261   /* Free the previously allocated memory and replace it with a copy of the  */
262   /* provided one.  Note that evel_force_option_string strdups entity_id.    */
263   /***************************************************************************/
264   evel_free_option_string(&header->reporting_entity_id);
265   evel_force_option_string(&header->reporting_entity_id, entity_id);
266
267   EVEL_EXIT();
268 }
269
270 /**************************************************************************//**
271  * Encode the event as a JSON event object according to AT&T's schema.
272  *
273  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
274  * @param event         Pointer to the ::EVENT_HEADER to encode.
275  *****************************************************************************/
276 void evel_json_encode_header(EVEL_JSON_BUFFER * jbuf,
277                              EVENT_HEADER * event)
278 {
279   char * domain;
280   char * priority;
281
282   EVEL_ENTER();
283
284   /***************************************************************************/
285   /* Check preconditions.                                                    */
286   /***************************************************************************/
287   assert(jbuf != NULL);
288   assert(jbuf->json != NULL);
289   assert(jbuf->max_size > 0);
290   assert(event != NULL);
291
292   domain = evel_event_domain(event->event_domain);
293   priority = evel_event_priority(event->priority);
294   evel_json_open_named_object(jbuf, "commonEventHeader");
295
296   /***************************************************************************/
297   /* Mandatory fields.                                                       */
298   /***************************************************************************/
299   evel_enc_kv_string(jbuf, "domain", domain);
300   evel_enc_kv_string(jbuf, "eventId", event->event_id);
301   evel_enc_kv_string(jbuf, "functionalRole", event->functional_role);
302   evel_enc_kv_ull(jbuf, "lastEpochMicrosec", event->last_epoch_microsec);
303   evel_enc_kv_string(jbuf, "priority", priority);
304   evel_enc_kv_string(
305     jbuf, "reportingEntityName", event->reporting_entity_name);
306   evel_enc_kv_int(jbuf, "sequence", event->sequence);
307   evel_enc_kv_string(jbuf, "sourceName", event->source_name);
308   evel_enc_kv_ull(jbuf, "startEpochMicrosec", event->start_epoch_microsec);
309   evel_enc_version(
310     jbuf, "version", event->major_version, event->minor_version);
311
312   /***************************************************************************/
313   /* Optional fields.                                                        */
314   /***************************************************************************/
315   evel_enc_kv_opt_string(jbuf, "eventType", &event->event_type);
316   evel_enc_kv_opt_string(
317     jbuf, "reportingEntityId", &event->reporting_entity_id);
318   evel_enc_kv_opt_string(jbuf, "sourceId", &event->source_id);
319
320   evel_json_close_object(jbuf);
321
322   EVEL_EXIT();
323 }
324
325 /**************************************************************************//**
326  * Free an event header.
327  *
328  * Free off the event header supplied.  Will free all the contained allocated
329  * memory.
330  *
331  * @note It does not free the header itself, since that may be part of a
332  * larger structure.
333  *****************************************************************************/
334 void evel_free_header(EVENT_HEADER * const event)
335 {
336   EVEL_ENTER();
337
338   /***************************************************************************/
339   /* Check preconditions.  As an internal API we don't allow freeing NULL    */
340   /* events as we do on the public API.                                      */
341   /***************************************************************************/
342   assert(event != NULL);
343
344   /***************************************************************************/
345   /* Free all internal strings.                                              */
346   /***************************************************************************/
347   free(event->event_id);
348   evel_free_option_string(&event->event_type);
349   free(event->functional_role);
350   evel_free_option_string(&event->reporting_entity_id);
351   free(event->reporting_entity_name);
352   evel_free_option_string(&event->source_id);
353   free(event->source_name);
354
355   EVEL_EXIT();
356 }
357
358 /**************************************************************************//**
359  * Encode the event as a JSON event object according to AT&T's schema.
360  *
361  * @param json      Pointer to where to store the JSON encoded data.
362  * @param max_size  Size of storage available in json_body.
363  * @param event     Pointer to the ::EVENT_HEADER to encode.
364  * @returns Number of bytes actually written.
365  *****************************************************************************/
366 int evel_json_encode_event(char * json,
367                            int max_size,
368                            EVENT_HEADER * event)
369 {
370   EVEL_JSON_BUFFER json_buffer;
371   EVEL_JSON_BUFFER * jbuf = &json_buffer;
372   EVEL_THROTTLE_SPEC * throttle_spec;
373
374   EVEL_ENTER();
375
376   /***************************************************************************/
377   /* Get the latest throttle specification for the domain.                   */
378   /***************************************************************************/
379   throttle_spec = evel_get_throttle_spec(event->event_domain);
380
381   /***************************************************************************/
382   /* Initialize the JSON_BUFFER and open the top-level objects.              */
383   /***************************************************************************/
384   evel_json_buffer_init(jbuf, json, max_size, throttle_spec);
385   evel_json_open_object(jbuf);
386   evel_json_open_named_object(jbuf, "event");
387
388   switch (event->event_domain)
389   {
390     case EVEL_DOMAIN_HEARTBEAT:
391       evel_json_encode_header(jbuf, event);
392       break;
393
394     case EVEL_DOMAIN_FAULT:
395       evel_json_encode_fault(jbuf, (EVENT_FAULT *)event);
396       break;
397
398     case EVEL_DOMAIN_MEASUREMENT:
399       evel_json_encode_measurement(jbuf, (EVENT_MEASUREMENT *)event);
400       break;
401
402     case EVEL_DOMAIN_MOBILE_FLOW:
403       evel_json_encode_mobile_flow(jbuf, (EVENT_MOBILE_FLOW *)event);
404       break;
405
406     case EVEL_DOMAIN_REPORT:
407       evel_json_encode_report(jbuf, (EVENT_REPORT *)event);
408       break;
409
410     case EVEL_DOMAIN_SERVICE:
411       evel_json_encode_service(jbuf, (EVENT_SERVICE *)event);
412       break;
413
414     case EVEL_DOMAIN_SIGNALING:
415       evel_json_encode_signaling(jbuf, (EVENT_SIGNALING *)event);
416       break;
417
418     case EVEL_DOMAIN_STATE_CHANGE:
419       evel_json_encode_state_change(jbuf, (EVENT_STATE_CHANGE *)event);
420       break;
421
422     case EVEL_DOMAIN_SYSLOG:
423       evel_json_encode_syslog(jbuf, (EVENT_SYSLOG *)event);
424       break;
425
426     case EVEL_DOMAIN_OTHER:
427       evel_json_encode_other(jbuf, (EVENT_OTHER *)event);
428       break;
429
430     case EVEL_DOMAIN_INTERNAL:
431     default:
432       EVEL_ERROR("Unexpected domain %d", event->event_domain);
433       assert(0);
434   }
435
436   evel_json_close_object(jbuf);
437   evel_json_close_object(jbuf);
438
439   /***************************************************************************/
440   /* Sanity check.                                                           */
441   /***************************************************************************/
442   assert(jbuf->depth == 0);
443
444   EVEL_EXIT();
445
446   return jbuf->offset;
447 }
448
449 /**************************************************************************//**
450  * Initialize an event instance id.
451  *
452  * @param instance_id   Pointer to the event instance id being initialized.
453  * @param vendor_id     The vendor id to encode in the event instance id.
454  * @param event_id      The event id to encode in the event instance id.
455  *****************************************************************************/
456 void evel_init_event_instance_id(EVEL_EVENT_INSTANCE_ID * const instance_id,
457                                  const char * const vendor_id,
458                                  const char * const event_id)
459 {
460   EVEL_ENTER();
461
462   /***************************************************************************/
463   /* Check preconditions.                                                    */
464   /***************************************************************************/
465   assert(instance_id != NULL);
466   assert(vendor_id != NULL);
467   assert(event_id != NULL);
468
469   /***************************************************************************/
470   /* Store the mandatory parts.                                              */
471   /***************************************************************************/
472   instance_id->vendor_id = strdup(vendor_id);
473   instance_id->event_id = strdup(event_id);
474
475   /***************************************************************************/
476   /* Initialize the optional parts.                                          */
477   /***************************************************************************/
478   evel_init_option_string(&instance_id->product_id);
479   evel_init_option_string(&instance_id->subsystem_id);
480   evel_init_option_string(&instance_id->event_friendly_name);
481
482   EVEL_EXIT();
483 }
484
485 /**************************************************************************//**
486  * Free an event instance id.
487  *
488  * @param instance_id   Pointer to the event instance id being initialized.
489  *****************************************************************************/
490 void evel_free_event_instance_id(EVEL_EVENT_INSTANCE_ID * const instance_id)
491 {
492   EVEL_ENTER();
493
494   /***************************************************************************/
495   /* Check preconditions.                                                    */
496   /***************************************************************************/
497   assert(instance_id != NULL);
498   assert(instance_id->vendor_id != NULL);
499   assert(instance_id->event_id != NULL);
500
501   /***************************************************************************/
502   /* Free everything.                                                        */
503   /***************************************************************************/
504   free(instance_id->vendor_id);
505   free(instance_id->event_id);
506   evel_free_option_string(&instance_id->product_id);
507   evel_free_option_string(&instance_id->subsystem_id);
508   evel_free_option_string(&instance_id->event_friendly_name);
509
510   EVEL_EXIT();
511 }
512
513 /**************************************************************************//**
514  * Encode the instance id as a JSON object according to AT&T's schema.
515  *
516  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
517  * @param instance_id   Pointer to the ::EVEL_EVENT_INSTANCE_ID to encode.
518  *****************************************************************************/
519 void evel_json_encode_instance_id(EVEL_JSON_BUFFER * jbuf,
520                                   EVEL_EVENT_INSTANCE_ID * instance_id)
521 {
522   EVEL_ENTER();
523
524   /***************************************************************************/
525   /* Check preconditions.                                                    */
526   /***************************************************************************/
527   assert(jbuf != NULL);
528   assert(jbuf->json != NULL);
529   assert(jbuf->max_size > 0);
530   assert(instance_id != NULL);
531   assert(instance_id->vendor_id != NULL);
532   assert(instance_id->event_id != NULL);
533
534   evel_json_open_named_object(jbuf, "eventInstanceIdentifier");
535
536   /***************************************************************************/
537   /* Mandatory fields.                                                       */
538   /***************************************************************************/
539   evel_enc_kv_string(jbuf, "vendorId", instance_id->vendor_id);
540   evel_enc_kv_string(jbuf, "eventId", instance_id->event_id);
541
542   /***************************************************************************/
543   /* Optional fields.                                                        */
544   /***************************************************************************/
545   evel_enc_kv_opt_string(jbuf, "productId", &instance_id->product_id);
546   evel_enc_kv_opt_string(jbuf, "subsystemId", &instance_id->subsystem_id);
547   evel_enc_kv_opt_string(
548     jbuf, "eventFriendlyName", &instance_id->event_friendly_name);
549
550   evel_json_close_object(jbuf);
551
552   EVEL_EXIT();
553 }