From 386c5e495f6e9257391f531d0590b3ae73738b7f Mon Sep 17 00:00:00 2001 From: Naveen Albert Date: Wed, 15 Dec 2021 18:36:42 +0000 Subject: [PATCH] cdr: allow disabling CDR by default on new channels Adds a new option, defaultenabled, to the CDR core to control whether or not CDR is enabled on a newly created channel. This allows CDR to be disabled by default on new channels and require the user to explicitly enable CDR if desired. Existing behavior remains unchanged. ASTERISK-29808 #close Change-Id: Ibb78c11974bda229bbb7004b64761980e0b2c6d1 --- configs/samples/cdr.conf.sample | 5 +++++ doc/CHANGES-staging/cdr_disable.txt | 8 ++++++++ include/asterisk/cdr.h | 1 + main/cdr.c | 31 +++++++++++++++++++++++++++++ tests/test_cdr.c | 6 +++--- 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 doc/CHANGES-staging/cdr_disable.txt diff --git a/configs/samples/cdr.conf.sample b/configs/samples/cdr.conf.sample index 5cd1dc17aa..4fce18b260 100644 --- a/configs/samples/cdr.conf.sample +++ b/configs/samples/cdr.conf.sample @@ -13,6 +13,11 @@ ; any loading of backend CDR modules. Default is "yes". ;enable=yes +; Define whether or not to use CDR logging on new channels by default. +; Setting this to "no" will disable CDR on channels unless it is explicitly +; enabled. Default is "yes". +;channeldefaultenabled=yes + ; Define whether or not to log unanswered calls that don't involve an outgoing ; party. Setting this to "yes" will make calls to extensions that don't answer ; and don't set a B side channel (such as by using the Dial application) diff --git a/doc/CHANGES-staging/cdr_disable.txt b/doc/CHANGES-staging/cdr_disable.txt new file mode 100644 index 0000000000..cae7a7c333 --- /dev/null +++ b/doc/CHANGES-staging/cdr_disable.txt @@ -0,0 +1,8 @@ +Subject: cdr + +A new CDR option, channeldefaultenabled, allows controlling +whether CDR is enabled or disabled by default on +newly created channels. The default behavior remains +unchanged from previous versions of Asterisk (new +channels will have CDR enabled, as long as CDR is +enabled globally). diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h index e2a5a90d7c..2bbfbdb28b 100644 --- a/include/asterisk/cdr.h +++ b/include/asterisk/cdr.h @@ -224,6 +224,7 @@ enum ast_cdr_settings { CDR_END_BEFORE_H_EXTEN = 1 << 4, /*!< End the CDR before the 'h' extension runs */ 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 */ }; /*! \brief CDR Batch Mode settings */ diff --git a/main/cdr.c b/main/cdr.c index 555809217c..8a3ad66a77 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -96,6 +96,21 @@ any loading of backend CDR modules. Default is "yes". + + Whether CDR is enabled on a channel by default + Define whether or not CDR should be enabled on a channel by default. + Setting this to "yes" will enable CDR on every channel unless it is explicitly disabled. + Setting this to "no" will disable CDR on every channel unless it is explicitly enabled. + Default is "yes". + Note that CDR must still be globally enabled (enable = yes) for this + option to have any effect. This only applies to whether CDR is enabled or disabled on + newly created channels, which can be changed in the dialplan during a call. + If this is set to "yes", you should use Set(CDR_PROP(disable)=1) + to disable CDR for a call. + If this is set to "no", you should use Set(CDR_PROP(disable)=0) + to undisable (enable) CDR for a call. + + Log calls that are never answered and don't set an outgoing party. @@ -192,6 +207,7 @@ #define DEFAULT_CONGESTION "0" #define DEFAULT_END_BEFORE_H_EXTEN "1" #define DEFAULT_INITIATED_SECONDS "0" +#define DEFAULT_CHANNEL_ENABLED "1" #define DEFAULT_BATCH_SIZE "100" #define MAX_BATCH_SIZE 1000 @@ -2281,12 +2297,25 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub } if (update->new_snapshot && !update->old_snapshot) { + struct module_config *mod_cfg = NULL; + cdr = cdr_object_alloc(update->new_snapshot, stasis_message_timestamp(message)); if (!cdr) { return; } + mod_cfg = ao2_global_obj_ref(module_configs); cdr->is_root = 1; ao2_link(active_cdrs_master, cdr); + + /* If CDR should be disabled unless enabled on a per-channel basis, then disable + CDR, right from the get go */ + if (mod_cfg) { + if (!ast_test_flag(&mod_cfg->general->settings, CDR_CHANNEL_DEFAULT_ENABLED)) { + ast_debug(3, "Disable CDR by default\n"); + ast_set_flag(&cdr->flags, AST_CDR_FLAG_DISABLE_ALL); + } + ao2_cleanup(mod_cfg); + } } else { cdr = ao2_find(active_cdrs_master, update->new_snapshot->base->uniqueid, OBJ_SEARCH_KEY); } @@ -4168,6 +4197,7 @@ static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_ ast_cli(a->fd, " Logging: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) ? "Enabled" : "Disabled"); ast_cli(a->fd, " Mode: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE) ? "Batch" : "Simple"); if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) { + 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"); if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) { @@ -4348,6 +4378,7 @@ static int process_config(int reload) aco_option_register(&cfg_info, "safeshutdown", ACO_EXACT, general_options, DEFAULT_BATCH_SAFE_SHUTDOWN, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, batch_settings.settings), BATCH_MODE_SAFE_SHUTDOWN); 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); } if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) { diff --git a/tests/test_cdr.c b/tests/test_cdr.c index bdbffccbc9..cef519de36 100644 --- a/tests/test_cdr.c +++ b/tests/test_cdr.c @@ -59,17 +59,17 @@ static struct ast_cdr_config *saved_config; /*! \brief A configuration suitable for 'normal' CDRs */ static struct ast_cdr_config debug_cdr_config = { - .settings.flags = CDR_ENABLED | CDR_DEBUG, + .settings.flags = CDR_ENABLED | CDR_CHANNEL_DEFAULT_ENABLED | CDR_DEBUG, }; /*! \brief A configuration suitable for CDRs with unanswered records */ static struct ast_cdr_config unanswered_cdr_config = { - .settings.flags = CDR_ENABLED | CDR_UNANSWERED | CDR_DEBUG, + .settings.flags = CDR_ENABLED | CDR_CHANNEL_DEFAULT_ENABLED | CDR_UNANSWERED | CDR_DEBUG, }; /*! \brief A configuration suitable for CDRs with congestion enabled */ static struct ast_cdr_config congestion_cdr_config = { - .settings.flags = CDR_ENABLED | CDR_UNANSWERED | CDR_DEBUG | CDR_CONGESTION, + .settings.flags = CDR_ENABLED | CDR_CHANNEL_DEFAULT_ENABLED | CDR_UNANSWERED | CDR_DEBUG | CDR_CONGESTION, }; /*! \brief Macro to swap a configuration out from the CDR engine. This should be