<p>Joshua Colp has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11692">View Change</a></p><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;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/92/11692/1</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 1d43c11..7dfb74c 100644</span><br><span>--- a/main/cdr.c</span><br><span>+++ b/main/cdr.c</span><br><span>@@ -725,6 +725,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>@@ -1042,7 +1043,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>@@ -1062,6 +1063,7 @@</span><br><span> ast_string_field_set(cdr, linkedid, chan->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>@@ -1077,14 +1079,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>@@ -1447,7 +1449,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>@@ -1497,7 +1499,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>@@ -1643,7 +1645,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>@@ -2151,6 +2153,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>@@ -2181,7 +2184,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>@@ -2291,7 +2294,7 @@</span><br><span> }</span><br><span> </span><br><span> if (new_snapshot && !old_snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">- cdr = cdr_object_alloc(new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ cdr = cdr_object_alloc(new_snapshot, stasis_message_timestamp(message));</span><br><span> if (!cdr) {</span><br><span> return;</span><br><span> }</span><br><span>@@ -2316,6 +2319,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>@@ -2325,7 +2329,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, new_snapshot);</span><br><span> }</span><br><span>@@ -2335,6 +2339,7 @@</span><br><span> ao2_lock(cdr);</span><br><span> CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, old_snapshot->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>@@ -2441,6 +2446,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>@@ -2475,7 +2481,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>@@ -2586,7 +2592,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>@@ -2595,6 +2602,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>@@ -2607,7 +2616,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>@@ -2624,7 +2633,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>@@ -2635,6 +2645,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->name);</span><br><span>@@ -2681,7 +2693,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>@@ -2729,9 +2741,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>@@ -2781,6 +2793,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>@@ -2790,7 +2803,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>@@ -3592,6 +3605,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>@@ -3613,6 +3627,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>@@ -3626,7 +3641,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->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>@@ -3656,6 +3671,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 31fd1ca..cdf14fd 100644</span><br><span>--- a/main/cel.c</span><br><span>+++ b/main/cel.c</span><br><span>@@ -521,14 +521,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>@@ -560,8 +569,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>@@ -589,7 +599,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>@@ -603,7 +613,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>@@ -634,7 +644,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>@@ -854,7 +864,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>@@ -886,20 +897,21 @@</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 (!new_snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">- cel_report_event(old_snapshot, AST_CEL_CHANNEL_END, NULL, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ cel_report_event(old_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(old_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ check_retire_linkedid(old_snapshot, event_time);</span><br><span> }</span><br><span> return;</span><br><span> }</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>@@ -914,21 +926,22 @@</span><br><span> "hangupcause", new_snapshot->hangupcause,</span><br><span> "hangupsource", new_snapshot->hangupsource,</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> 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 || !new_snapshot) {</span><br><span> return;</span><br><span>@@ -940,13 +953,14 @@</span><br><span> if (ast_cel_track_event(AST_CEL_LINKEDID_END)</span><br><span> && strcmp(old_snapshot->linkedid, new_snapshot->linkedid)) {</span><br><span> cel_linkedid_ref(new_snapshot->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 (new_snapshot && old_snapshot</span><br><span> && !strcmp(old_snapshot->appl, new_snapshot->appl)) {</span><br><span>@@ -955,12 +969,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->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 (new_snapshot && !ast_strlen_zero(new_snapshot->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>@@ -1000,7 +1014,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](old_snapshot, new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ cel_channel_monitors[i](old_snapshot, new_snapshot, stasis_message_timestamp(message));</span><br><span> }</span><br><span> }</span><br><span> }</span><br><span>@@ -1069,7 +1083,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>@@ -1098,7 +1113,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>@@ -1115,7 +1131,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>@@ -1144,7 +1161,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>@@ -1237,7 +1255,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>@@ -1260,7 +1279,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>@@ -1289,7 +1309,8 @@</span><br><span> "transferee_channel_name", transfer_msg->transferee ? transfer_msg->transferee->name : "N/A",</span><br><span> "transferee_channel_uniqueid", transfer_msg->transferee ? transfer_msg->transferee->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>@@ -1352,7 +1373,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>@@ -1376,7 +1398,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>@@ -1400,7 +1422,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/+/11692">change 11692</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/+/11692"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-Change-Id: I6829227e67aefa318efe5e183a94d4a1b4e8500a </div>
<div style="display:none"> Gerrit-Change-Number: 11692 </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-MessageType: newchange </div>