Skip to main content

mod_format_cdr — JSON/XML CDR to Disk or HTTP

mod_format_cdr captures one Call Detail Record per call leg at hangup and delivers it as either a JSON or XML document. Records can be written to local disk, HTTP-POSTed to one or more web endpoints, or both simultaneously. Multiple named profiles may be active at once, enabling independent delivery pipelines — for example, writing XML to disk while posting JSON to a remote billing server.

The module lives in src/mod/event_handlers and registers an on_reporting state-handler callback. On SIGHUP (SWITCH_EVENT_TRAP with Trapped-Signal: HUP) the module rotates its log directories if rotate is enabled.

Loading the Module

The module name is mod_format_cdr. It is not included in the vanilla modules.conf.xml default load set and must be added manually:

<load module="mod_format_cdr"/>

No special build flag is required; the module is built as part of the standard FreeSWITCH source tree.

Configuration: format_cdr.conf.xml

The configuration file is conf/autoload_configs/format_cdr.conf.xml. It contains one or more <profile> elements inside a <profiles> block. Each profile is independent and runs for every call.

Parameters

ParameterPurposeAccepted ValuesDefault
formatOutput format for CDR data.xml, jsonxml
urlHTTP endpoint to POST the CDR to. May be repeated up to 20 times for failover. Omit or leave blank to disable HTTP delivery.HTTP/HTTPS URL(none — disk only)
credHTTP Basic or other credentials passed to libcurl.user:pass string(none)
log-dirDirectory for disk output. Blank value defaults to ${prefix}/logs/format_cdr. Relative values are interpreted under ${prefix}/logs/. Omit the parameter entirely to disable disk writes when a url is set.Absolute or relative path, or blank(none)
log-fileFilename template for each CDR file. Channel variables are expanded. When omitted, the filename is <uuid>.cdr.<format> (or a_<uuid>.cdr.<format> when prefix-a-leg is enabled).Filename string with optional ${variable} expansions<uuid>.cdr.<format>
err-log-dirDirectory where CDR files are written when HTTP POST fails. May be repeated up to 20 times. Defaults to log-dir when omitted.Absolute or relative path, or blanksame as log-dir
log-b-legWhether to generate a CDR for B-leg (originated) channels. When false, B-legs are skipped unless force_process_cdr is set on the channel.true, falsetrue (code default; vanilla conf sets false)
prefix-a-legWhen true, prepend a_ to the CDR filename for A-leg calls. Has no effect on B-legs.true, falsefalse (code default; vanilla conf sets true)
log-http-and-diskWhen true, write to disk even when HTTP delivery succeeds.true, falsefalse
encodeHTTP POST body encoding. true = URL-encoded (application/x-www-form-urlencoded), false = plaintext, base64 = base64-encoded, textxml = raw body with Content-Type: text/xml, appljson = raw body with Content-Type: application/json.true, false, base64, textxml, appljson(none set; conf example uses true)
encode-valuesWhen true, URL-encode individual JSON field values when generating JSON CDRs. Set to false for standard unescaped JSON.true, falsefalse (code default; vanilla conf sets true)
retriesNumber of additional POST attempts after the first failure (so retries=2 means up to 3 total attempts).Non-negative integer0
delaySeconds to wait between retry attempts. Automatically set to 5 if retries is non-zero and delay is 0.Non-negative integer0 (→ 5 when retries set)
timeoutlibcurl transfer timeout in seconds. 0 means no timeout.Non-negative integer0
rotateWhen true, create a new subdirectory under log-dir on SIGHUP, named with the current timestamp (YYYY-MM-DD-HH-MM-SS).true, falsefalse
auth-schemelibcurl HTTP authentication scheme. Prefix with = to use only that scheme (no bitmask).basic, digest, NTLM, GSS-NEGOTIATE, anybasic
disable-100-continueWhen true, suppress the Expect: 100-continue header. Required by some HTTP servers such as lighttpd.true, falsefalse
enable-cacert-checkWhen true, have libcurl verify the server certificate against the system CA bundle.true, falsefalse
enable-ssl-verifyhostWhen true, verify that the TLS certificate hostname matches the target host.true, falsefalse
ssl-cert-pathPath to the PEM-format client public certificate for mutual TLS.Absolute file path(none)
ssl-key-pathPath to the PEM-format client private key for mutual TLS.Absolute file path(none)
ssl-key-passwordPassphrase for the private key specified in ssl-key-path.String(none)
ssl-cacert-filePath to a custom CA certificate in PEM format for peer verification.Absolute file path(none)
ssl-versionForce a specific TLS version.SSLv3, TLSv1(libcurl auto-negotiates)

Example Configuration

<configuration name="format_cdr.conf" description="Multi Format CDR CURL logger">
<profiles>
<profile name="default">
<settings>
<param name="format" value="xml"/>
<!-- <param name="url" value="http://localhost/cdr_curl/post.php"/> -->
<param name="log-dir" value=""/>
<param name="log-b-leg" value="false"/>
<param name="prefix-a-leg" value="true"/>
<param name="encode" value="true"/>
<param name="encode-values" value="true"/>
</settings>
</profile>
</profiles>
</configuration>

Multiple profiles may coexist. Assign each a unique name attribute to run parallel delivery pipelines (for example, one profile in JSON to an HTTP endpoint and another in XML to a local directory).

Channel Variables

VariableSet / ReadPurpose
format_cdr_baseReadOverride the log-dir for an individual call. When set on the channel at hangup, the module writes the CDR to this directory instead of the profile's configured log-dir.
force_process_cdrReadWhen set to a true value on a B-leg channel and log-b-leg is false, forces the module to generate and deliver a CDR for that B-leg anyway.

Events

mod_format_cdr does not register any custom SWITCH_EVENT_CUSTOM subclasses. It consumes SWITCH_EVENT_TRAP internally to detect SIGHUP for log rotation.

See also

Source: src/mod/event_handlers/mod_format_cdr, conf/vanilla/autoload_configs/format_cdr.conf.xml