diff --git a/configs/samples/cdr.conf.sample b/configs/samples/cdr.conf.sample
index 6331760764..46ddb96b7d 100644
--- a/configs/samples/cdr.conf.sample
+++ b/configs/samples/cdr.conf.sample
@@ -32,6 +32,17 @@
 ; is "no".
 ;congestion = no
 
+; Define whether or not to ignore bridging changes in CDRs. This prevents
+; bridging changes from resulting in multiple CDRs for different parts of
+; a call. Default is "no". This setting cannot be changed on a reload.
+;ignorestatechanges = no
+
+; Define whether or not to ignore dial updates in CDRs. This prevents
+; dial updates from resulting in multiple CDRs for different parts of
+; a call. The last disposition on the channel will be used for the CDR.
+; Use with caution. Default is "no".
+;ignoredialchanges = no
+
 ; Normally, CDR's are not closed out until after all extensions are finished
 ; executing.  By enabling this option, the CDR will be ended before executing
 ; the "h" extension and hangup handlers so that CDR values such as "end" and
diff --git a/doc/CHANGES-staging/cdr_ignore.txt b/doc/CHANGES-staging/cdr_ignore.txt
new file mode 100644
index 0000000000..e82f40415a
--- /dev/null
+++ b/doc/CHANGES-staging/cdr_ignore.txt
@@ -0,0 +1,6 @@
+Subject: cdr
+
+Two new options have been added which allow
+bridging and dial state changes to be ignored
+in CDRs, which can be useful if a single CDR
+is desired for a channel.
diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h
index 2bbfbdb28b..06307c91f2 100644
--- a/include/asterisk/cdr.h
+++ b/include/asterisk/cdr.h
@@ -225,6 +225,8 @@ enum ast_cdr_settings {
 	CDR_INITIATED_SECONDS = 1 << 5,     /*!< Include microseconds into the billing time */
 	CDR_DEBUG = 1 << 6,                 /*!< Enables extra debug statements */
 	CDR_CHANNEL_DEFAULT_ENABLED = 1 << 7, /*!< Whether CDR is enabled for each channel by default */
+	CDR_IGNORE_STATE_CHANGES = 1 << 8,	/*!< Whether to ignore bridge and other call state change events */
+	CDR_IGNORE_DIAL_CHANGES = 1 << 9,	/*!< Whether to ignore dial state changes */
 };
 
 /*! \brief CDR Batch Mode settings */
diff --git a/main/cdr.c b/main/cdr.c
index b05908245f..8f1f30b0a1 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -111,6 +111,29 @@
 					to undisable (enable) CDR for a call.
 					
 				
+				
+					Whether CDR is updated or forked by bridging changes.
+					Define whether or not CDR should be updated by bridging changes.
+					This includes entering and leaving bridges and call parking.
+					If this is set to "no", bridging changes will be ignored for all CDRs.
+					This should only be done if these events should not affect CDRs and are undesired,
+					such as to use a single CDR for the lifetime of the channel.
+					This setting cannot be changed on a reload.
+					
+				
+				
+					Whether CDR is updated or forked by dial updates.
+					Define whether or not CDR should be updated by dial updates.
+					If this is set to "no", a single CDR will be used for the channel, even if
+					multiple endpoints or destinations are dialed sequentially. Note that you will also
+					lose detailed nonanswer dial dispositions if this option is enabled, which may not be acceptable,
+					e.g. instead of detailed no-answer dispositions like BUSY and CONGESTION, the disposition
+					will always be NO ANSWER if the channel was unanswered (it will still be ANSWERED
+					if the channel was answered).
+					This option should be enabled if a single CDR is desired for the lifetime of
+					the channel.
+					
+				
 				
 					Log calls that are never answered and don't set an outgoing party.
 					
@@ -208,6 +231,8 @@
 #define DEFAULT_END_BEFORE_H_EXTEN "1"
 #define DEFAULT_INITIATED_SECONDS "0"
 #define DEFAULT_CHANNEL_ENABLED "1"
+#define DEFAULT_IGNORE_STATE_CHANGES "0"
+#define DEFAULT_IGNORE_DIAL_CHANGES "0"
 
 #define DEFAULT_BATCH_SIZE "100"
 #define MAX_BATCH_SIZE 1000
@@ -222,6 +247,7 @@
 	} while (0)
 
 static int cdr_debug_enabled;
+static int dial_changes_ignored;
 
 #define CDR_DEBUG(fmt, ...) \
 	do { \
@@ -2170,6 +2196,10 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
 			if (!it_cdr->fn_table->process_dial_begin) {
 				continue;
 			}
+			if (dial_changes_ignored) {
+				CDR_DEBUG("%p - Ignoring Dial Begin message\n", it_cdr);
+				continue;
+			}
 			CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n",
 				it_cdr,
 				caller ? caller->base->name : "(none)",
@@ -2181,6 +2211,12 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
 			if (!it_cdr->fn_table->process_dial_end) {
 				continue;
 			}
+			if (dial_changes_ignored) {
+				/* Set the disposition, and do nothing else. */
+				it_cdr->disposition = dial_status_to_disposition(dial_status);
+				CDR_DEBUG("%p - Setting disposition and that's it (%s)\n", it_cdr, dial_status);
+				continue;
+			}
 			CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n",
 				it_cdr,
 				caller ? caller->base->name : "(none)",
@@ -2192,15 +2228,19 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
 		}
 	}
 
-	/* If no CDR handled a dial begin message, make a new one */
-	if (res && ast_strlen_zero(dial_status)) {
-		struct cdr_object *new_cdr;
+	/* If we're ignoring dial changes, don't allow multiple CDRs for this channel. */
+	if (!dial_changes_ignored) {
+		/* If no CDR handled a dial begin message, make a new one */
+		if (res && ast_strlen_zero(dial_status)) {
+			struct cdr_object *new_cdr;
 
-		new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
-		if (new_cdr) {
-			new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);
+			new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
+			if (new_cdr) {
+				new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);
+			}
 		}
 	}
+
 	ao2_unlock(cdr);
 	ao2_cleanup(cdr);
 }
@@ -4200,6 +4240,8 @@ static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_
 		ast_cli(a->fd, "  Log calls by default:       %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_CHANNEL_DEFAULT_ENABLED) ? "Yes" : "No");
 		ast_cli(a->fd, "  Log unanswered calls:       %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) ? "Yes" : "No");
 		ast_cli(a->fd, "  Log congestion:             %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION) ? "Yes" : "No");
+		ast_cli(a->fd, "  Ignore bridging changes:    %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_STATE_CHANGES) ? "Yes" : "No");
+		ast_cli(a->fd, "  Ignore dial state changes:  %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_DIAL_CHANGES) ? "Yes" : "No");
 		if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
 			ast_cli(a->fd, "* Batch Mode Settings\n");
 			ast_cli(a->fd, "  -------------------\n");
@@ -4379,6 +4421,8 @@ static int process_config(int reload)
 		aco_option_register(&cfg_info, "size", ACO_EXACT, general_options, DEFAULT_BATCH_SIZE, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_cdr_config, batch_settings.size), 0, MAX_BATCH_SIZE);
 		aco_option_register(&cfg_info, "time", ACO_EXACT, general_options, DEFAULT_BATCH_TIME, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_cdr_config, batch_settings.time), 1, MAX_BATCH_TIME);
 		aco_option_register(&cfg_info, "channeldefaultenabled", ACO_EXACT, general_options, DEFAULT_CHANNEL_ENABLED, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_CHANNEL_DEFAULT_ENABLED);
+		aco_option_register(&cfg_info, "ignorestatechanges", ACO_EXACT, general_options, DEFAULT_IGNORE_STATE_CHANGES, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_IGNORE_STATE_CHANGES);
+		aco_option_register(&cfg_info, "ignoredialchanges", ACO_EXACT, general_options, DEFAULT_IGNORE_DIAL_CHANGES, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_IGNORE_DIAL_CHANGES);
 	}
 
 	if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {
@@ -4541,6 +4585,7 @@ static int unload_module(void)
 
 static int load_module(void)
 {
+	struct module_config *mod_cfg = NULL;
 	if (process_config(0)) {
 		return AST_MODULE_LOAD_FAILURE;
 	}
@@ -4561,13 +4606,36 @@ static int load_module(void)
 		return AST_MODULE_LOAD_FAILURE;
 	}
 
+	mod_cfg = ao2_global_obj_ref(module_configs);
+
 	stasis_message_router_add(stasis_router, ast_channel_snapshot_type(), handle_channel_snapshot_update_message, NULL);
+
+	/* Always process dial messages, because even if we ignore most of it, we do want the dial status for the disposition. */
 	stasis_message_router_add(stasis_router, ast_channel_dial_type(), handle_dial_message, NULL);
-	stasis_message_router_add(stasis_router, ast_channel_entered_bridge_type(), handle_bridge_enter_message, NULL);
-	stasis_message_router_add(stasis_router, ast_channel_left_bridge_type(), handle_bridge_leave_message, NULL);
-	stasis_message_router_add(stasis_router, ast_parked_call_type(), handle_parked_call_message, NULL);
+	if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_DIAL_CHANGES)) {
+		dial_changes_ignored = 0;
+	} else {
+		dial_changes_ignored = 1;
+		CDR_DEBUG("Dial messages will be mostly ignored\n");
+	}
+
+	/* If explicitly instructed to ignore call state changes, then ignore bridging events, parking, etc. */
+	if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_STATE_CHANGES)) {
+		stasis_message_router_add(stasis_router, ast_channel_entered_bridge_type(), handle_bridge_enter_message, NULL);
+		stasis_message_router_add(stasis_router, ast_channel_left_bridge_type(), handle_bridge_leave_message, NULL);
+		stasis_message_router_add(stasis_router, ast_parked_call_type(), handle_parked_call_message, NULL);
+	} else {
+		CDR_DEBUG("All bridge and parking messages will be ignored\n");
+	}
+
 	stasis_message_router_add(stasis_router, cdr_sync_message_type(), handle_cdr_sync_message, NULL);
 
+	if (mod_cfg) {
+		ao2_cleanup(mod_cfg);
+	} else {
+		ast_log(LOG_WARNING, "Unable to obtain CDR configuration during module load?\n");
+	}
+
 	active_cdrs_master = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
 		AST_NUM_CHANNEL_BUCKETS, cdr_master_hash_fn, NULL, cdr_master_cmp_fn);
 	if (!active_cdrs_master) {