<p>Friendly Automation <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11696">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  George Joseph: Looks good to me, but someone else must approve
  Kevin Harwell: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">cdr / cel: Use event time at event creation instead of processing.<br><br>When updating times on CDR or CEL records using the time at which<br>it is done can result in times being incorrect if the system is<br>heavily loaded and stasis message processing is delayed.<br><br>This change instead makes it so CDR and CEL use the time at which<br>the stasis messages that drive the systems are created. This allows<br>them to be backed up while still producing correct records.<br><br>ASTERISK-28498<br><br>Change-Id: I6829227e67aefa318efe5e183a94d4a1b4e8500a<br>---<br>M include/asterisk/cel.h<br>M main/cdr.c<br>M main/cel.c<br>3 files changed, 108 insertions(+), 48 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/cel.h b/include/asterisk/cel.h</span><br><span>index fed2085..c0b8848 100644</span><br><span>--- a/include/asterisk/cel.h</span><br><span>+++ b/include/asterisk/cel.h</span><br><span>@@ -264,6 +264,28 @@</span><br><span>             struct ast_json *extra, const char *peer_str);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Allocate and populate a CEL event structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param snapshot An ast_channel_snapshot of the primary channel associated</span><br><span style="color: hsl(120, 100%, 40%);">+ *        with this channel event.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param event_type The type of call event being reported.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param event_time The time at which the event occurred.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param userdefevname Custom name for the call event. (optional)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param extra An event-specific opaque JSON blob to be rendered and placed</span><br><span style="color: hsl(120, 100%, 40%);">+ *        in the "CEL_EXTRA" information element of the call event. (optional)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param peer_str A list of comma-separated peer channel names. (optional)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.29.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.6.0</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The created ast_event structure</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_event *ast_cel_create_event_with_time(struct ast_channel_snapshot *snapshot,</span><br><span style="color: hsl(120, 100%, 40%);">+           enum ast_cel_event_type event_type, const struct timeval *event_time,</span><br><span style="color: hsl(120, 100%, 40%);">+         const char *userdefevname, struct ast_json *extra, const char *peer_str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \brief CEL backend callback</span><br><span>  */</span><br><span> /*typedef int (*ast_cel_backend_cb)(struct ast_cel_event_record *cel);*/</span><br><span>diff --git a/main/cdr.c b/main/cdr.c</span><br><span>index f8f038c..2c3ca97 100644</span><br><span>--- a/main/cdr.c</span><br><span>+++ b/main/cdr.c</span><br><span>@@ -718,6 +718,7 @@</span><br><span>     struct timeval start;                   /*!< When this CDR was created */</span><br><span>         struct timeval answer;                  /*!< Either when the channel was answered, or when the path between channels was established */</span><br><span>   struct timeval end;                     /*!< When this CDR was finalized */</span><br><span style="color: hsl(120, 100%, 40%);">+        struct timeval lastevent;               /*!< The time at which the last event was created regarding this CDR */</span><br><span>   unsigned int sequence;                  /*!< A monotonically increasing number for each CDR */</span><br><span>    struct ast_flags flags;                 /*!< Flags on the CDR */</span><br><span>  AST_DECLARE_STRING_FIELDS(</span><br><span>@@ -1035,7 +1036,7 @@</span><br><span>  * This implicitly sets the state of the newly created CDR to the Single state</span><br><span>  * (\ref single_state_fn_table)</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)</span><br><span> {</span><br><span>    struct cdr_object *cdr;</span><br><span> </span><br><span>@@ -1055,6 +1056,7 @@</span><br><span>  ast_string_field_set(cdr, linkedid, chan->peer->linkedid);</span><br><span>     cdr->disposition = AST_CDR_NULL;</span><br><span>  cdr->sequence = ast_atomic_fetchadd_int(&global_cdr_sequence, +1);</span><br><span style="color: hsl(120, 100%, 40%);">+     cdr->lastevent = *event_time;</span><br><span> </span><br><span>         cdr->party_a.snapshot = chan;</span><br><span>     ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");</span><br><span>@@ -1070,14 +1072,14 @@</span><br><span>  * \brief Create a new \ref cdr_object and append it to an existing chain</span><br><span>  * \param cdr The \ref cdr_object to append to</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)</span><br><span> {</span><br><span>         struct cdr_object *new_cdr;</span><br><span>  struct cdr_object *it_cdr;</span><br><span>   struct cdr_object *cdr_last;</span><br><span> </span><br><span>     cdr_last = cdr->last;</span><br><span style="color: hsl(0, 100%, 40%);">-        new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+    new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot, event_time);</span><br><span>       if (!new_cdr) {</span><br><span>              return NULL;</span><br><span>         }</span><br><span>@@ -1440,7 +1442,7 @@</span><br><span>    if (!ast_tvzero(cdr->end)) {</span><br><span>              return;</span><br><span>      }</span><br><span style="color: hsl(0, 100%, 40%);">-       cdr->end = ast_tvnow();</span><br><span style="color: hsl(120, 100%, 40%);">+    cdr->end = cdr->lastevent;</span><br><span> </span><br><span>         if (cdr->disposition == AST_CDR_NULL) {</span><br><span>           if (!ast_tvzero(cdr->answer)) {</span><br><span>@@ -1490,7 +1492,7 @@</span><br><span> static void cdr_object_check_party_a_answer(struct cdr_object *cdr)</span><br><span> {</span><br><span>       if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         cdr->answer = ast_tvnow();</span><br><span style="color: hsl(120, 100%, 40%);">+         cdr->answer = cdr->lastevent;</span><br><span>          /* tv_usec is suseconds_t, which could be int or long */</span><br><span>             CDR_DEBUG("%p - Set answered time to %ld.%06ld\n", cdr,</span><br><span>                    (long)cdr->answer.tv_sec,</span><br><span>@@ -1634,7 +1636,7 @@</span><br><span> </span><br><span> static void single_state_init_function(struct cdr_object *cdr)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- cdr->start = ast_tvnow();</span><br><span style="color: hsl(120, 100%, 40%);">+  cdr->start = cdr->lastevent;</span><br><span>   cdr_object_check_party_a_answer(cdr);</span><br><span> }</span><br><span> </span><br><span>@@ -2149,6 +2151,7 @@</span><br><span> </span><br><span>   ao2_lock(cdr);</span><br><span>       for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                it_cdr->lastevent = *stasis_message_timestamp(message);</span><br><span>           if (ast_strlen_zero(dial_status)) {</span><br><span>                  if (!it_cdr->fn_table->process_dial_begin) {</span><br><span>                           continue;</span><br><span>@@ -2179,7 +2182,7 @@</span><br><span>    if (res && ast_strlen_zero(dial_status)) {</span><br><span>           struct cdr_object *new_cdr;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         new_cdr = cdr_object_create_and_append(cdr);</span><br><span style="color: hsl(120, 100%, 40%);">+          new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));</span><br><span>              if (new_cdr) {</span><br><span>                       new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);</span><br><span>          }</span><br><span>@@ -2281,7 +2284,7 @@</span><br><span>    }</span><br><span> </span><br><span>        if (update->new_snapshot && !update->old_snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">-              cdr = cdr_object_alloc(update->new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+              cdr = cdr_object_alloc(update->new_snapshot, stasis_message_timestamp(message));</span><br><span>          if (!cdr) {</span><br><span>                  return;</span><br><span>              }</span><br><span>@@ -2300,6 +2303,7 @@</span><br><span> </span><br><span>                ao2_lock(cdr);</span><br><span>               for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        it_cdr->lastevent = *stasis_message_timestamp(message);</span><br><span>                   if (!it_cdr->fn_table->process_party_a) {</span><br><span>                              continue;</span><br><span>                    }</span><br><span>@@ -2309,7 +2313,7 @@</span><br><span>                    /* We're not hung up and we have a new snapshot - we need a new CDR */</span><br><span>                   struct cdr_object *new_cdr;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                 new_cdr = cdr_object_create_and_append(cdr);</span><br><span style="color: hsl(120, 100%, 40%);">+                  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));</span><br><span>                      if (new_cdr) {</span><br><span>                               new_cdr->fn_table->process_party_a(new_cdr, update->new_snapshot);</span><br><span>                  }</span><br><span>@@ -2321,6 +2325,7 @@</span><br><span>            ao2_lock(cdr);</span><br><span>               CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);</span><br><span>            for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        it_cdr->lastevent = *stasis_message_timestamp(message);</span><br><span>                   cdr_object_finalize(it_cdr);</span><br><span>                 }</span><br><span>            cdr_object_dispatch(cdr);</span><br><span>@@ -2429,6 +2434,7 @@</span><br><span>    /* Party A */</span><br><span>        ao2_lock(cdr);</span><br><span>       for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                it_cdr->lastevent = *stasis_message_timestamp(message);</span><br><span>           if (!it_cdr->fn_table->process_bridge_leave) {</span><br><span>                         continue;</span><br><span>            }</span><br><span>@@ -2463,7 +2469,7 @@</span><br><span> {</span><br><span>       struct cdr_object *new_cdr;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- new_cdr = cdr_object_create_and_append(cdr);</span><br><span style="color: hsl(120, 100%, 40%);">+  new_cdr = cdr_object_create_and_append(cdr, &cdr->lastevent);</span><br><span>         if (!new_cdr) {</span><br><span>              return;</span><br><span>      }</span><br><span>@@ -2574,7 +2580,8 @@</span><br><span>  */</span><br><span> static void handle_parking_bridge_enter_message(struct cdr_object *cdr,</span><br><span>          struct ast_bridge_snapshot *bridge,</span><br><span style="color: hsl(0, 100%, 40%);">-             struct ast_channel_snapshot *channel)</span><br><span style="color: hsl(120, 100%, 40%);">+         struct ast_channel_snapshot *channel,</span><br><span style="color: hsl(120, 100%, 40%);">+         const struct timeval *event_time)</span><br><span> {</span><br><span>       int res = 1;</span><br><span>         struct cdr_object *it_cdr;</span><br><span>@@ -2583,6 +2590,8 @@</span><br><span>   ao2_lock(cdr);</span><br><span> </span><br><span>   for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                it_cdr->lastevent = *event_time;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                if (it_cdr->fn_table->process_parking_bridge_enter) {</span><br><span>                  res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);</span><br><span>            }</span><br><span>@@ -2595,7 +2604,7 @@</span><br><span> </span><br><span>        if (res) {</span><br><span>           /* No one handled it - we need a new one! */</span><br><span style="color: hsl(0, 100%, 40%);">-            new_cdr = cdr_object_create_and_append(cdr);</span><br><span style="color: hsl(120, 100%, 40%);">+          new_cdr = cdr_object_create_and_append(cdr, event_time);</span><br><span>             if (new_cdr) {</span><br><span>                       /* Let the single state transition us to Parked */</span><br><span>                   cdr_object_transition_state(new_cdr, &single_state_fn_table);</span><br><span>@@ -2612,7 +2621,8 @@</span><br><span>  */</span><br><span> static void handle_standard_bridge_enter_message(struct cdr_object *cdr,</span><br><span>                 struct ast_bridge_snapshot *bridge,</span><br><span style="color: hsl(0, 100%, 40%);">-             struct ast_channel_snapshot *channel)</span><br><span style="color: hsl(120, 100%, 40%);">+         struct ast_channel_snapshot *channel,</span><br><span style="color: hsl(120, 100%, 40%);">+         const struct timeval *event_time)</span><br><span> {</span><br><span>       enum process_bridge_enter_results result;</span><br><span>    struct cdr_object *it_cdr;</span><br><span>@@ -2623,6 +2633,8 @@</span><br><span> </span><br><span> try_again:</span><br><span>         for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                it_cdr->lastevent = *event_time;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                if (it_cdr->fn_table->process_party_a) {</span><br><span>                       CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,</span><br><span>                           channel->base->name);</span><br><span>@@ -2669,7 +2681,7 @@</span><br><span>          handle_bridge_pairings(handled_cdr, bridge);</span><br><span>         } else {</span><br><span>             /* Nothing handled it - we need a new one! */</span><br><span style="color: hsl(0, 100%, 40%);">-           new_cdr = cdr_object_create_and_append(cdr);</span><br><span style="color: hsl(120, 100%, 40%);">+          new_cdr = cdr_object_create_and_append(cdr, event_time);</span><br><span>             if (new_cdr) {</span><br><span>                       /* This is guaranteed to succeed: the new CDR is created in the single state</span><br><span>                          * and will be able to handle the bridge enter message</span><br><span>@@ -2717,9 +2729,9 @@</span><br><span>       }</span><br><span> </span><br><span>        if (!strcmp(bridge->subclass, "parking")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                handle_parking_bridge_enter_message(cdr, bridge, channel);</span><br><span style="color: hsl(120, 100%, 40%);">+            handle_parking_bridge_enter_message(cdr, bridge, channel, stasis_message_timestamp(message));</span><br><span>        } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                handle_standard_bridge_enter_message(cdr, bridge, channel);</span><br><span style="color: hsl(120, 100%, 40%);">+           handle_standard_bridge_enter_message(cdr, bridge, channel, stasis_message_timestamp(message));</span><br><span>       }</span><br><span>    ao2_cleanup(cdr);</span><br><span> }</span><br><span>@@ -2769,6 +2781,7 @@</span><br><span>       ao2_lock(cdr);</span><br><span> </span><br><span>   for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+                it_cdr->lastevent = *stasis_message_timestamp(message);</span><br><span>           if (it_cdr->fn_table->process_parked_channel) {</span><br><span>                        unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);</span><br><span>            }</span><br><span>@@ -2778,7 +2791,7 @@</span><br><span>            /* Nothing handled the messgae - we need a new one! */</span><br><span>               struct cdr_object *new_cdr;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         new_cdr = cdr_object_create_and_append(cdr);</span><br><span style="color: hsl(120, 100%, 40%);">+          new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));</span><br><span>              if (new_cdr) {</span><br><span>                       /* As the new CDR is created in the single state, it is guaranteed</span><br><span>                    * to have a function for the parked call message and will handle</span><br><span>@@ -3607,6 +3620,7 @@</span><br><span>            memset(&it_cdr->end, 0, sizeof(it_cdr->end));</span><br><span>              memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));</span><br><span>                it_cdr->start = ast_tvnow();</span><br><span style="color: hsl(120, 100%, 40%);">+               it_cdr->lastevent = it_cdr->start;</span><br><span>             cdr_object_check_party_a_answer(it_cdr);</span><br><span>     }</span><br><span>    ao2_unlock(cdr);</span><br><span>@@ -3628,6 +3642,7 @@</span><br><span> </span><br><span>         {</span><br><span>            SCOPED_AO2LOCK(lock, cdr);</span><br><span style="color: hsl(120, 100%, 40%);">+            struct timeval now = ast_tvnow();</span><br><span> </span><br><span>                cdr_obj = cdr->last;</span><br><span>              if (cdr_obj->fn_table == &finalized_state_fn_table) {</span><br><span>@@ -3641,7 +3656,7 @@</span><br><span>                  * copied over automatically as part of the append</span><br><span>            */</span><br><span>          ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);</span><br><span style="color: hsl(0, 100%, 40%);">-             new_cdr = cdr_object_create_and_append(cdr);</span><br><span style="color: hsl(120, 100%, 40%);">+          new_cdr = cdr_object_create_and_append(cdr, &now);</span><br><span>               if (!new_cdr) {</span><br><span>                      return -1;</span><br><span>           }</span><br><span>@@ -3671,6 +3686,7 @@</span><br><span>            }</span><br><span>            new_cdr->start = cdr_obj->start;</span><br><span>               new_cdr->answer = cdr_obj->answer;</span><br><span style="color: hsl(120, 100%, 40%);">+              new_cdr->lastevent = ast_tvnow();</span><br><span> </span><br><span>             /* Modify the times based on the flags passed in */</span><br><span>          if (ast_test_flag(options, AST_CDR_FLAG_SET_ANSWER)</span><br><span>diff --git a/main/cel.c b/main/cel.c</span><br><span>index 1e77d25..00020ea 100644</span><br><span>--- a/main/cel.c</span><br><span>+++ b/main/cel.c</span><br><span>@@ -519,14 +519,23 @@</span><br><span>             struct ast_json *extra, const char *peer)</span><br><span> {</span><br><span>       struct timeval eventtime = ast_tvnow();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return ast_cel_create_event_with_time(snapshot, event_type, &eventtime,</span><br><span style="color: hsl(120, 100%, 40%);">+           userdefevname, extra, peer);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_event *ast_cel_create_event_with_time(struct ast_channel_snapshot *snapshot,</span><br><span style="color: hsl(120, 100%, 40%);">+            enum ast_cel_event_type event_type, const struct timeval *event_time,</span><br><span style="color: hsl(120, 100%, 40%);">+         const char *userdefevname, struct ast_json *extra, const char *peer)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span>      RAII_VAR(char *, extra_txt, NULL, ast_json_free);</span><br><span>    if (extra) {</span><br><span>                 extra_txt = ast_json_dump_string(extra);</span><br><span>     }</span><br><span>    return ast_event_new(AST_EVENT_CEL,</span><br><span>          AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,</span><br><span style="color: hsl(120, 100%, 40%);">+                AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, event_time->tv_sec,</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, event_time->tv_usec,</span><br><span>          AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, S_OR(userdefevname, ""),</span><br><span>                 AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->name,</span><br><span>             AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->number,</span><br><span>@@ -558,8 +567,9 @@</span><br><span> }</span><br><span> </span><br><span> static int cel_report_event(struct ast_channel_snapshot *snapshot,</span><br><span style="color: hsl(0, 100%, 40%);">-          enum ast_cel_event_type event_type, const char *userdefevname,</span><br><span style="color: hsl(0, 100%, 40%);">-          struct ast_json *extra, const char *peer_str)</span><br><span style="color: hsl(120, 100%, 40%);">+         enum ast_cel_event_type event_type, const struct timeval *event_time,</span><br><span style="color: hsl(120, 100%, 40%);">+         const char *userdefevname, struct ast_json *extra,</span><br><span style="color: hsl(120, 100%, 40%);">+            const char *peer_str)</span><br><span> {</span><br><span>   struct ast_event *ev;</span><br><span>        RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);</span><br><span>@@ -587,7 +597,7 @@</span><br><span>              return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ev = ast_cel_create_event(snapshot, event_type, userdefevname, extra, peer_str);</span><br><span style="color: hsl(120, 100%, 40%);">+      ev = ast_cel_create_event_with_time(snapshot, event_type, event_time, userdefevname, extra, peer_str);</span><br><span>       if (!ev) {</span><br><span>           return -1;</span><br><span>   }</span><br><span>@@ -601,7 +611,7 @@</span><br><span> </span><br><span> /* called whenever a channel is destroyed or a linkedid is changed to</span><br><span>  * potentially emit a CEL_LINKEDID_END event */</span><br><span style="color: hsl(0, 100%, 40%);">-static void check_retire_linkedid(struct ast_channel_snapshot *snapshot)</span><br><span style="color: hsl(120, 100%, 40%);">+static void check_retire_linkedid(struct ast_channel_snapshot *snapshot, const struct timeval *event_time)</span><br><span> {</span><br><span>     RAII_VAR(struct ao2_container *, linkedids, ao2_global_obj_ref(cel_linkedids), ao2_cleanup);</span><br><span>         struct cel_linkedid *lid;</span><br><span>@@ -632,7 +642,7 @@</span><br><span>              ao2_unlink(linkedids, lid);</span><br><span>          ao2_unlock(linkedids);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-              cel_report_event(snapshot, AST_CEL_LINKEDID_END, NULL, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+           cel_report_event(snapshot, AST_CEL_LINKEDID_END, event_time, NULL, NULL, NULL);</span><br><span>      } else {</span><br><span>             ao2_unlock(linkedids);</span><br><span>       }</span><br><span>@@ -852,7 +862,8 @@</span><br><span> /*! \brief Typedef for callbacks that get called on channel snapshot updates */</span><br><span> typedef void (*cel_channel_snapshot_monitor)(</span><br><span>  struct ast_channel_snapshot *old_snapshot,</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_channel_snapshot *new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_channel_snapshot *new_snapshot,</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct timeval *event_time);</span><br><span> </span><br><span> static struct cel_dialstatus *get_dialstatus(const char *uniqueid)</span><br><span> {</span><br><span>@@ -884,12 +895,13 @@</span><br><span> /*! \brief Handle channel state changes */</span><br><span> static void cel_channel_state_change(</span><br><span>     struct ast_channel_snapshot *old_snapshot,</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_channel_snapshot *new_snapshot)</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_channel_snapshot *new_snapshot,</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct timeval *event_time)</span><br><span> {</span><br><span>       int is_hungup, was_hungup;</span><br><span> </span><br><span>       if (!old_snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">-            cel_report_event(new_snapshot, AST_CEL_CHANNEL_START, NULL, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+              cel_report_event(new_snapshot, AST_CEL_CHANNEL_START, event_time, NULL, NULL, NULL);</span><br><span>                 return;</span><br><span>      }</span><br><span> </span><br><span>@@ -904,26 +916,27 @@</span><br><span>                        "hangupcause", new_snapshot->hangup->cause,</span><br><span>                  "hangupsource", new_snapshot->hangup->source,</span><br><span>                        "dialstatus", dialstatus ? dialstatus->dialstatus : "");</span><br><span style="color: hsl(0, 100%, 40%);">-         cel_report_event(new_snapshot, AST_CEL_HANGUP, NULL, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+            cel_report_event(new_snapshot, AST_CEL_HANGUP, event_time, NULL, extra, NULL);</span><br><span>               ast_json_unref(extra);</span><br><span>               ao2_cleanup(dialstatus);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-            cel_report_event(new_snapshot, AST_CEL_CHANNEL_END, NULL, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                cel_report_event(new_snapshot, AST_CEL_CHANNEL_END, event_time, NULL, NULL, NULL);</span><br><span>           if (ast_cel_track_event(AST_CEL_LINKEDID_END)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        check_retire_linkedid(new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+                  check_retire_linkedid(new_snapshot, event_time);</span><br><span>             }</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span>        if (old_snapshot->state != new_snapshot->state && new_snapshot->state == AST_STATE_UP) {</span><br><span style="color: hsl(0, 100%, 40%);">-               cel_report_event(new_snapshot, AST_CEL_ANSWER, NULL, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+             cel_report_event(new_snapshot, AST_CEL_ANSWER, event_time, NULL, NULL, NULL);</span><br><span>                return;</span><br><span>      }</span><br><span> }</span><br><span> </span><br><span> static void cel_channel_linkedid_change(</span><br><span>       struct ast_channel_snapshot *old_snapshot,</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_channel_snapshot *new_snapshot)</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_channel_snapshot *new_snapshot,</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct timeval *event_time)</span><br><span> {</span><br><span>       if (!old_snapshot) {</span><br><span>                 return;</span><br><span>@@ -935,13 +948,14 @@</span><br><span>      if (ast_cel_track_event(AST_CEL_LINKEDID_END)</span><br><span>                && strcmp(old_snapshot->peer->linkedid, new_snapshot->peer->linkedid)) {</span><br><span>                 cel_linkedid_ref(new_snapshot->peer->linkedid);</span><br><span style="color: hsl(0, 100%, 40%);">-           check_retire_linkedid(old_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+          check_retire_linkedid(old_snapshot, event_time);</span><br><span>     }</span><br><span> }</span><br><span> </span><br><span> static void cel_channel_app_change(</span><br><span>    struct ast_channel_snapshot *old_snapshot,</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_channel_snapshot *new_snapshot)</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_channel_snapshot *new_snapshot,</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct timeval *event_time)</span><br><span> {</span><br><span>       if (old_snapshot && !strcmp(old_snapshot->dialplan->appl, new_snapshot->dialplan->appl)) {</span><br><span>               return;</span><br><span>@@ -949,12 +963,12 @@</span><br><span> </span><br><span>  /* old snapshot has an application, end it */</span><br><span>        if (old_snapshot && !ast_strlen_zero(old_snapshot->dialplan->appl)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             cel_report_event(old_snapshot, AST_CEL_APP_END, NULL, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+            cel_report_event(old_snapshot, AST_CEL_APP_END, event_time, NULL, NULL, NULL);</span><br><span>       }</span><br><span> </span><br><span>        /* new snapshot has an application, start it */</span><br><span>      if (!ast_strlen_zero(new_snapshot->dialplan->appl)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             cel_report_event(new_snapshot, AST_CEL_APP_START, NULL, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+          cel_report_event(new_snapshot, AST_CEL_APP_START, event_time, NULL, NULL, NULL);</span><br><span>     }</span><br><span> }</span><br><span> </span><br><span>@@ -988,7 +1002,7 @@</span><br><span>    }</span><br><span> </span><br><span>        for (i = 0; i < ARRAY_LEN(cel_channel_monitors); ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">-              cel_channel_monitors[i](update->old_snapshot, update->new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+            cel_channel_monitors[i](update->old_snapshot, update->new_snapshot, stasis_message_timestamp(message));</span><br><span>        }</span><br><span> }</span><br><span> </span><br><span>@@ -1056,7 +1070,8 @@</span><br><span>           return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   cel_report_event(chan_snapshot, AST_CEL_BRIDGE_ENTER, NULL, extra, ast_str_buffer(peer_str));</span><br><span style="color: hsl(120, 100%, 40%);">+ cel_report_event(chan_snapshot, AST_CEL_BRIDGE_ENTER, stasis_message_timestamp(message),</span><br><span style="color: hsl(120, 100%, 40%);">+              NULL, extra, ast_str_buffer(peer_str));</span><br><span> }</span><br><span> </span><br><span> static void cel_bridge_leave_cb(</span><br><span>@@ -1085,7 +1100,8 @@</span><br><span>                 return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   cel_report_event(chan_snapshot, AST_CEL_BRIDGE_EXIT, NULL, extra, ast_str_buffer(peer_str));</span><br><span style="color: hsl(120, 100%, 40%);">+  cel_report_event(chan_snapshot, AST_CEL_BRIDGE_EXIT, stasis_message_timestamp(message),</span><br><span style="color: hsl(120, 100%, 40%);">+               NULL, extra, ast_str_buffer(peer_str));</span><br><span> }</span><br><span> </span><br><span> static void cel_parking_cb(</span><br><span>@@ -1102,7 +1118,8 @@</span><br><span>                      "parker_dial_string", parked_payload->parker_dial_string,</span><br><span>                       "parking_lot", parked_payload->parkinglot);</span><br><span>             if (extra) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    cel_report_event(parked_payload->parkee, AST_CEL_PARK_START, NULL, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                   cel_report_event(parked_payload->parkee, AST_CEL_PARK_START, stasis_message_timestamp(message),</span><br><span style="color: hsl(120, 100%, 40%);">+                            NULL, extra, NULL);</span><br><span>          }</span><br><span>            return;</span><br><span>      case PARKED_CALL_TIMEOUT:</span><br><span>@@ -1131,7 +1148,8 @@</span><br><span>    }</span><br><span> </span><br><span>        if (extra) {</span><br><span style="color: hsl(0, 100%, 40%);">-            cel_report_event(parked_payload->parkee, AST_CEL_PARK_END, NULL, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+             cel_report_event(parked_payload->parkee, AST_CEL_PARK_END, stasis_message_timestamp(message),</span><br><span style="color: hsl(120, 100%, 40%);">+                      NULL, extra, NULL);</span><br><span>  }</span><br><span> }</span><br><span> </span><br><span>@@ -1224,7 +1242,8 @@</span><br><span> </span><br><span>               extra = ast_json_pack("{s: s}", "forward", get_blob_variable(blob, "forward"));</span><br><span>                if (extra) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    cel_report_event(snapshot, AST_CEL_FORWARD, NULL, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                       cel_report_event(snapshot, AST_CEL_FORWARD, stasis_message_timestamp(message),</span><br><span style="color: hsl(120, 100%, 40%);">+                                NULL, extra, NULL);</span><br><span>                  ast_json_unref(extra);</span><br><span>               }</span><br><span>    }</span><br><span>@@ -1247,7 +1266,8 @@</span><br><span>            {</span><br><span>                    const char *event = ast_json_string_get(ast_json_object_get(event_details, "event"));</span><br><span>                      struct ast_json *extra = ast_json_object_get(event_details, "extra");</span><br><span style="color: hsl(0, 100%, 40%);">-                 cel_report_event(obj->snapshot, event_type, event, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                   cel_report_event(obj->snapshot, event_type, stasis_message_timestamp(message),</span><br><span style="color: hsl(120, 100%, 40%);">+                             event, extra, NULL);</span><br><span>                         break;</span><br><span>               }</span><br><span>    default:</span><br><span>@@ -1276,7 +1296,8 @@</span><br><span>             "transferee_channel_name", transfer_msg->transferee ? transfer_msg->transferee->base->name : "N/A",</span><br><span>          "transferee_channel_uniqueid", transfer_msg->transferee ? transfer_msg->transferee->base->uniqueid  : "N/A");</span><br><span>        if (extra) {</span><br><span style="color: hsl(0, 100%, 40%);">-            cel_report_event(chan_snapshot, AST_CEL_BLINDTRANSFER, NULL, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+            cel_report_event(chan_snapshot, AST_CEL_BLINDTRANSFER, stasis_message_timestamp(message),</span><br><span style="color: hsl(120, 100%, 40%);">+                     NULL, extra, NULL);</span><br><span>          ast_json_unref(extra);</span><br><span>       }</span><br><span> }</span><br><span>@@ -1339,7 +1360,8 @@</span><br><span>               }</span><br><span>            break;</span><br><span>       }</span><br><span style="color: hsl(0, 100%, 40%);">-       cel_report_event(channel1, AST_CEL_ATTENDEDTRANSFER, NULL, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      cel_report_event(channel1, AST_CEL_ATTENDEDTRANSFER, stasis_message_timestamp(message),</span><br><span style="color: hsl(120, 100%, 40%);">+               NULL, extra, NULL);</span><br><span>  ast_json_unref(extra);</span><br><span> }</span><br><span> </span><br><span>@@ -1363,7 +1385,7 @@</span><br><span>              return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   cel_report_event(target, AST_CEL_PICKUP, NULL, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+  cel_report_event(target, AST_CEL_PICKUP, stasis_message_timestamp(message), NULL, extra, NULL);</span><br><span>      ast_json_unref(extra);</span><br><span> }</span><br><span> </span><br><span>@@ -1387,7 +1409,7 @@</span><br><span>              return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   cel_report_event(localone, AST_CEL_LOCAL_OPTIMIZE, NULL, extra, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+        cel_report_event(localone, AST_CEL_LOCAL_OPTIMIZE, stasis_message_timestamp(message), NULL, extra, NULL);</span><br><span>    ast_json_unref(extra);</span><br><span> }</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/11696">change 11696</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/11696"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 17.0 </div>
<div style="display:none"> Gerrit-Change-Id: I6829227e67aefa318efe5e183a94d4a1b4e8500a </div>
<div style="display:none"> Gerrit-Change-Number: 11696 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>