diff --git a/configs/samples/cdr_custom.conf.sample b/configs/samples/cdr_custom.conf.sample index 760c039eba..3a120428a3 100644 --- a/configs/samples/cdr_custom.conf.sample +++ b/configs/samples/cdr_custom.conf.sample @@ -106,7 +106,8 @@ ; ; The default output format for the "start", "answer" and "end" timestamp fields ; is the "%Y-%m-%d %T" strftime string format however you can also format those - ; fields as an int64 or a float: `start(int64),answer(float),end`. + ; fields as an int64 or a double: `start(int64)` or `start(double)` or + ; provide your own strftime format string: `start(%FT%T%z)`. ; ; The "disposition" and "amaflags" are formatted as their string names like ; "ANSWERED" and "DOCUMENTATION" by default but if you just want the numbers and diff --git a/configs/samples/cel_custom.conf.sample b/configs/samples/cel_custom.conf.sample index 03debc6e29..e025dd6bf1 100644 --- a/configs/samples/cel_custom.conf.sample +++ b/configs/samples/cel_custom.conf.sample @@ -111,9 +111,12 @@ ; you can force the uniqueid field to not be quoted with `uniqueid(noquote)`. The ; example in fields above shows this. ; - ; The default output format for the "EventTime" timestamp field is the "%Y-%m-%d %T" - ; strftime string format however you can also format the field as an int64 or a - ; float: `eventtime(int64)` or `eventtime(float)`. + ; The default output format for the "EventTime" timestamp field is taken from the + ; "dateformat" parameter in cel.conf. If that's not set, the default is + ; "." where "" is always 6 digits with + ; leading zeros. You can also format the field as an int64 or a double: + ; `eventtime(int64)` or `eventtime(double)` or provide your own strftime + ; format string: `eventtime(%FT%T%z)`. ; ; Unlike CDRs, the "amaflags" field is output as its numerical value by default ; for historical reasons. You can output it as its friendly string with diff --git a/res/cdrel_custom/cdrel.h b/res/cdrel_custom/cdrel.h index 84787840e9..e1542b7db4 100644 --- a/res/cdrel_custom/cdrel.h +++ b/res/cdrel_custom/cdrel.h @@ -78,12 +78,13 @@ enum cdrel_data_type { cdrel_type_uservar, cdrel_type_event_type, cdrel_type_event_enum, + cdrel_type_cel_timefmt, cdrel_data_type_strings_end, cdrel_type_int32, cdrel_type_uint32, cdrel_type_int64, cdrel_type_uint64, - cdrel_type_float, + cdrel_type_double, cdrel_data_type_end }; @@ -180,7 +181,7 @@ struct cdrel_value { int64_t int64; uint64_t uint64; struct timeval tv; - float floater; + double doubler; } values; }; diff --git a/res/cdrel_custom/config.c b/res/cdrel_custom/config.c index d4655f0792..49543df3d2 100644 --- a/res/cdrel_custom/config.c +++ b/res/cdrel_custom/config.c @@ -432,6 +432,7 @@ static struct cdrel_field *field_alloc(struct cdrel_config *config, const char * if (strchr(qualifier, '%') != NULL) { data_swap = ast_strdupa(qualifier); ast_set_flag(&field_flags, cdrel_flag_format_spec); + forced_output_data_type = cdrel_type_string; ast_debug(3, " Using qualifier '%s' for field '%s' flags: %s\n", qualifier, field_name, ast_str_tmp(128, cdrel_get_field_flags(&field_flags, &STR_TMP))); } @@ -466,6 +467,17 @@ static struct cdrel_field *field_alloc(struct cdrel_config *config, const char * return NULL; } + if (ast_test_flag(&field_flags, cdrel_flag_format_spec) + && registered_field->input_data_type != cdrel_type_timeval) { + ast_log(LOG_WARNING, "%s->%s: Custom format '%s' ignored for field '%s'." + " Only timeval types can use custom format strings.\n", + cdrel_basename(config->config_filename), cdrel_basename(config->output_filename), + data, field_name); + forced_output_data_type = cdrel_data_type_end; + ast_clear_flag(&field_flags, cdrel_flag_format_spec); + data = NULL; + } + field = ast_calloc(1, sizeof(*registered_field) + strlen(input_field_template) + 1); if (!field) { return NULL; @@ -1127,7 +1139,7 @@ static struct cdrel_config *load_text_file_legacy_config(enum cdrel_record_type return NULL; } - ast_log(LOG_NOTICE, "%s->%s: Logging %s records\n", + ast_log(LOG_NOTICE, "%s->%s: Logging legacy %s records as advanced\n", cdrel_basename(config->config_filename), cdrel_basename(config->output_filename), RECORD_TYPE_STR(config->record_type)); diff --git a/res/cdrel_custom/formatters.c b/res/cdrel_custom/formatters.c index fc4e22a5dc..2be6d26cb6 100644 --- a/res/cdrel_custom/formatters.c +++ b/res/cdrel_custom/formatters.c @@ -118,7 +118,7 @@ DEFINE_FORMATTER(uint32, uint32, uint32_t, "%u") DEFINE_FORMATTER(int32, int32, int32_t, "%d") DEFINE_FORMATTER(uint64, uint64, uint64_t, "%lu") DEFINE_FORMATTER(int64, int64, int64_t, "%ld") -DEFINE_FORMATTER(float, floater, float, "%.1f") +DEFINE_FORMATTER(double, doubler, double, "%.6f") static int format_timeval(struct cdrel_config *config, struct cdrel_field *field, struct cdrel_value *input_value, struct cdrel_value *output_value) @@ -134,11 +134,20 @@ static int format_timeval(struct cdrel_config *config, output_value->data_type = cdrel_type_int64; output_value->values.int64 = input_value->values.tv.tv_sec; return format_int64(config, field, output_value, output_value); - } else if (field->output_data_type == cdrel_type_float) { - output_value->data_type = cdrel_type_float; - output_value->values.floater = ((float)input_value->values.tv.tv_sec) + ((float)input_value->values.tv.tv_usec) / 1000000.0; - return format_float(config, field, output_value, output_value); - } else if (!ast_strlen_zero(field->data)) { + } else if (field->output_data_type == cdrel_type_double) { + output_value->data_type = cdrel_type_double; + output_value->values.doubler = ((double)input_value->values.tv.tv_sec) + ((double)input_value->values.tv.tv_usec) / 1000000.0; + return format_double(config, field, output_value, output_value); + } else if (field->output_data_type == cdrel_type_cel_timefmt) { + res = ast_cel_format_eventtime(input_value->values.tv, tempbuf, 64); + if (res != 0) { + return res; + } + input_value->values.string = tempbuf; + input_value->data_type = cdrel_type_string; + output_value->data_type = cdrel_type_string; + return format_string(config, field, input_value, output_value); + } else if (!ast_strlen_zero(field->data)) { format = field->data; } @@ -186,7 +195,7 @@ int load_formatters(void) cdrel_field_formatters[cdrel_type_int64] = format_int64; cdrel_field_formatters[cdrel_type_uint64] = format_uint64; cdrel_field_formatters[cdrel_type_timeval] = format_timeval; - cdrel_field_formatters[cdrel_type_float] = format_float; + cdrel_field_formatters[cdrel_type_double] = format_double; cdrel_field_formatters[cdrel_type_amaflags] = format_amaflags; cdrel_field_formatters[cdrel_type_disposition] = format_disposition; diff --git a/res/cdrel_custom/getters_cdr.c b/res/cdrel_custom/getters_cdr.c index 45667db57e..8e87cb25a1 100644 --- a/res/cdrel_custom/getters_cdr.c +++ b/res/cdrel_custom/getters_cdr.c @@ -53,7 +53,7 @@ DEFINE_CDR_GETTER(uint32, uint32, uint32_t) DEFINE_CDR_GETTER(int64, int64, int64_t) DEFINE_CDR_GETTER(uint64, uint64, uint64_t) DEFINE_CDR_GETTER(tv, timeval, struct timeval) -DEFINE_CDR_GETTER(floater, float, float) +DEFINE_CDR_GETTER(doubler, double, double) static int cdr_get_literal(void *record, struct cdrel_config *config, struct cdrel_field *field, struct cdrel_value *value) @@ -108,7 +108,7 @@ int load_cdr(void) cdrel_field_getters[cdrel_record_cdr][cdrel_type_int64] = cdr_get_int64; cdrel_field_getters[cdrel_record_cdr][cdrel_type_uint64] = cdr_get_uint64; cdrel_field_getters[cdrel_record_cdr][cdrel_type_timeval] = cdr_get_timeval; - cdrel_field_getters[cdrel_record_cdr][cdrel_type_float] = cdr_get_float; + cdrel_field_getters[cdrel_record_cdr][cdrel_type_double] = cdr_get_double; cdrel_field_getters[cdrel_record_cdr][cdrel_type_uservar] = cdr_get_uservar; cdrel_dummy_channel_allocators[cdrel_record_cdr] = dummy_chan_alloc_cdr; diff --git a/res/cdrel_custom/registry.c b/res/cdrel_custom/registry.c index 472b147c45..da678aee03 100644 --- a/res/cdrel_custom/registry.c +++ b/res/cdrel_custom/registry.c @@ -47,7 +47,7 @@ static const struct cdrel_field cdrel_field_registry[] = { REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_ENUM, "eventenum", cdrel_type_event_enum, cdrel_type_string), REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_TYPE, "eventtype", cdrel_type_event_type, cdrel_type_string), - REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_TIME, "eventtime", cdrel_type_timeval, cdrel_type_string), + REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_TIME, "eventtime", cdrel_type_timeval, cdrel_type_cel_timefmt), REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_TIME_USEC, "eventtimeusec", cdrel_type_uint32, cdrel_type_uint32), REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_USEREVENT_NAME, "usereventname", cdrel_type_string, cdrel_type_string), REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_USEREVENT_NAME, "userdeftype", cdrel_type_string, cdrel_type_string), diff --git a/res/res_cdrel_custom.c b/res/res_cdrel_custom.c index 179db87acc..773007a345 100644 --- a/res/res_cdrel_custom.c +++ b/res/res_cdrel_custom.c @@ -166,12 +166,13 @@ const char *cdrel_data_type_map[] = { [cdrel_type_uservar] = "uservar", [cdrel_type_event_type] = "event_type", [cdrel_type_event_enum] = "event_enum", + [cdrel_type_cel_timefmt] = "cel_timefmt", [cdrel_data_type_strings_end] = "!!STRINGS END!!", [cdrel_type_int32] = "int32", [cdrel_type_uint32] = "uint32", [cdrel_type_int64] = "int64", [cdrel_type_uint64] = "uint64", - [cdrel_type_float] = "float", + [cdrel_type_double] = "double", [cdrel_data_type_end] = "!!END!!", };