Documentation

Documentation.Tutorials-Advanced-Accounting History

Hide minor edits - Show changes to markup

November 03, 2016, at 04:50 PM by liviu -
Changed line 41 from:
  • it dialog scope - the call was successfully established:
to:
  • in dialog scope - the call was successfully established:
November 03, 2016, at 04:49 PM by liviu -
Changed lines 38-39 from:
  • success event. Such even generates an accounting record when:
    • in transaction scope the transaction when successfully completed (with a 2xx reply);
to:
  • success event. Such events generate an accounting record when:
    • in transaction scope - the transaction when successfully completed (with a 2xx reply):
Changed line 41 from:
  • it dialog scope when the call was successfully established ;
to:
  • it dialog scope - the call was successfully established:
Changed line 44 from:
  • missed call event. Such event may be generated only during the dialog setup phase (during the lifetime of the transaction for the initial INVITE), when a call attempt (or branch) did not established, as the UAS destination rejected or declined the call; There can be multiple such events per a single SIP call (due SIP forking). Note that a SIP call generating a accounting success event may also generate some missed call event because of the SIP branches (call attempts) that failed during serial or parallel forking; The missed call events are also known as UAS-side accounting (as they are related to the relation between OpenSIPS and callee/UAS side).
to:
  • missed call event. Such events may occur only during the dialog setup phase (during the lifetime of the transaction for the initial INVITE), when a call attempt (or branch) was not established, as the UAS destination rejected or declined the call; There can be multiple such events per a single SIP call (due SIP forking). Note that a SIP call generating an accounting success event may also generate one or more missed call event because of the SIP branches (call attempts) that failed during serial or parallel forking; The missed call events are also known as UAS-side accounting (as they are related to the relation between OpenSIPS and callee/UAS side).
Changed line 48 from:
  • failed transaction event. Such event is generated only in the transaction scope, when a transaction fails (reply code >=300) on the UAC side of OpenSIPS - this is a complementary event for the successfully transaction event.
to:
  • failed transaction event. Such event is generated only in the transaction scope, when a transaction fails (reply code >=300) on the UAC side of OpenSIPS - this is a complementary event for the successful transaction event.
Changed line 54 from:

When doing accounting, one can choose between a variety of engines to do accounting with or even combine them together:

to:

When doing accounting, one can choose between a variety of engines or even combine them together:

Changed lines 168-169 from:
  • enable multiple missed calls events during SIP serial forking. Let's take the case when there is a call for user Alice but Alice has multiple contacts registered (via SIP registration), like Contact1, Contact2 and Contacct3. The order for serial forking should be Contact1, Contact2 and Contact3. That is first time we try to call Contact1, if Contact1 does not respond Contact2 shall be tried and the last try should be made to Contact3. Last, but not least, if the call is to established (to any of the contacts), the call will be accounted.
to:
  • enable multiple missed calls events during SIP serial forking. Let's take the case when there is a call for user Alice but Alice has multiple contacts registered (via SIP registration), like Contact1, Contact2 and Contact3. The order for serial forking should be Contact1, Contact2 and Contact3. That is first time we try to call Contact1, if Contact1 does not respond Contact2 shall be tried and the last try should be made to Contact3. Last, but not least, if the call is to established (to any of the contacts), the call will be accounted.
Changed line 315 from:

In the script, everything that concerns lookup function was moved into a route, in order to use it multiple times. For the initial call, we'll get the URI of the caller from the From header. The URI of the callee is in the R-URI:

to:

In the script, everything that concerns the lookup() function was moved into a route, in order to use it multiple times. For the initial call, we'll get the URI of the caller from the From header. The URI of the callee is in the R-URI:

Changed line 320 from:

In case our call leg to Bob, as described above, fails and we will get into failure route where we will do serial forking to the redirect URI (to Charlie). In failure route, the redirected URI is resolved in the same way we did with the first uri, using lookup function. Now the leg Bob to Charlie is about to start, so we'll create a new leg and populate the $acc_leg variables accordingly for this new leg. The caller URI will be the callee URI of the previous leg, while the callee U will be the new redirect URI:

to:

In case our call leg to Bob (as described above) fails, script execution will resume from the failure_route, where we will do serial forking to the redirect URI (to Charlie). In failure route, the redirected URI is resolved in the same way we did with the first uri, using lookup function. Now the leg Bob to Charlie is about to start, so we'll create a new leg and populate the $acc_leg variables accordingly for this new leg. The caller URI will be the callee URI of the previous leg, while the callee U will be the new redirect URI:

November 03, 2016, at 12:47 PM by 109.99.227.30 -
Changed lines 10-13 from:

Concepts such as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. More complex scenarios including advanced features like extra accounting (extending the CDR format and collecting information from the entire call), and multi-leg accounting (multiple CDR records per SIP call) are also covered.
Everything in this tutorial is backed up with practical examples which you can run and dissect in order to get a better picture about how accounting works, and what are the best accounting options for your needs. Most of the features presented in this tutorial are available in versions starting with OpenSIPS 2.2, where there has been a major rework affecting the accounting module. There are many great improvements over previous versions of OpenSips which will ultimately help you to better understand and use the accounting module.

to:


Concepts such as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. More complex scenarios including advanced features like extra accounting (extending the CDR format and collecting information from the entire call), and multi-leg accounting (multiple CDR records per SIP call) are also covered.


Everything in this tutorial is backed up with practical examples which you can run and dissect in order to get a better picture about how accounting works, and what are the best accounting options for your needs. Most of the features presented in this tutorial are available in versions starting with OpenSIPS 2.2, where there has been a major rework affecting the accounting module. Nevertheless, this rework continued with OpenSIPS 2.3 when comes to simplifying the user experience in regards to the scripting.

November 03, 2016, at 12:44 PM by 109.99.227.30 -
Deleted line 1:

This page has been visited 21721 times.

November 03, 2016, at 12:06 PM by ionutionita92 -
Changed line 27 from:
  • SIP dialog level accounting: the generated accounting record covers a whole SIP call/dialog; such accounting record is also known as CDR (Call Data Record). This record, in addition to the transaction-scope accounting records, may contain information from the dialog level (call duration, BYE reason, RTP stats); In terms of usage, the dialog accounting is armed/set while handling the initial INVITE request; the CDR itself will be generated when the SIP dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
to:
  • SIP dialog level accounting: the generated accounting record covers a whole SIP call/dialog; such accounting record is also known as CDR (Call Detail Record). This record, in addition to the transaction-scope accounting records, may contain information from the dialog level (call duration, BYE reason, RTP stats); In terms of usage, the dialog accounting is armed/set while handling the initial INVITE request; the CDR itself will be generated when the SIP dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
November 03, 2016, at 12:02 PM by 109.99.227.30 -
Deleted line 323:
        $var(prev_callee) = $acc_leg(callee);
Changed lines 326-328 from:
        $acc_leg(caller) = $var(prev_callee);
to:
        # new caller is the callee of the previous leg
        $acc_leg(caller) = $(acc_leg(callee)[-2]);
        # new callee is the new destination
November 02, 2016, at 04:59 PM by 109.99.227.30 -
Added lines 28-31:


To conclude, if you do SIP stateless processing or if you need to manually account some really custom corner-cases, you should use the SIP message level accounting. Otherwise, if in stateful mode, for non-INVITE traffic, the SIP transaction level accounting gives you the best results - a single accounting record aggregating all the transaction related information. For INVITE based sessions, the SIP dialog level accounting is the easiest and most powerful way to get ready to use CDRs.

November 02, 2016, at 04:44 PM by 109.99.227.30 -
Changed lines 311-312 from:
      $acc_leg(caller) = $fU;
      $acc_leg(callee) = $rU;
to:
      $acc_leg(caller) = $fu;
      $acc_leg(callee) = $ru;
November 01, 2016, at 07:43 PM by 109.99.227.30 -
Changed lines 344-347 from:

If using db engine two rows will be generated, one with the leg from Alice to Bob and one with the leg from Bob to Charlie. The non-leg fields will be the same in all the legs:

to:


If using db backend two rows will be generated, one with the leg from Alice to Bob and one with the leg from Bob to Charlie. The non-leg fields will be the same in all the legs:

Added lines 353-359:


Here it is the full OpenSIPS config file used in this example.


November 01, 2016, at 07:42 PM by 109.99.227.30 -
Changed line 314 from:

In case our call to B, as described above, fails and we will get into failure route where we will fetch the next destination as usual. For redirects, we check if the new destination is a local uri, meaning that we have to resolve the same way we did with the first uri, using lookup function. Now the call from B to C starts, so we'll create a new leg. We need to store the name of the caller before calling next_branches() function, because after this call we will lose it:

to:

In case our call leg to Bob, as described above, fails and we will get into failure route where we will do serial forking to the redirect URI (to Charlie). In failure route, the redirected URI is resolved in the same way we did with the first uri, using lookup function. Now the leg Bob to Charlie is about to start, so we'll create a new leg and populate the $acc_leg variables accordingly for this new leg. The caller URI will be the callee URI of the previous leg, while the callee U will be the new redirect URI:

Changed lines 316-318 from:
        $var(old_rU) = $rU;

        next_branches();
to:
    if ( $avp(redirect_uri)!=NULL ) {
        # set the new destination
        $ru = $avp(redirect_uri);

        $var(prev_callee) = $acc_leg(callee);
        # create a new call leg
        acc_new_leg();
        $acc_leg(caller) = $var(prev_callee);
        $acc_leg(callee) = $ru;

        t_on_failure("missed_call");
        route(lookup);
        exit;
    }
Changed line 332 from:

If the call is a redirect, we will create a new leg and populate $acc_leg accordingly. The name of the calle will be in the URI populated by next_branches() function.

to:

For one redirect, we will have two account lines. One for the missed call from Alice to Bob

Changed lines 334-344 from:
        /* local contact; lookup needed */
        if (uri == myself) {
                acc_new_leg();
                $acc_leg(caller) = $var(old_rU);
                $acc_leg(callee) = $rU;

                route(lookup);

                serialize_branches(1);
        }
to:

ACC: call missed: timestamp=1474899448;created=1474899444;setuptime=4;method=INVITE; from_tag=1766231375;to_tag=;call_id=604787970;code=408;reason=Request Timeout; src_ip=10.0.0.101;dst_ip=10.0.0.203;caller=Alice;callee=Bob

Changed lines 338-339 from:

For one redirect, we will have two account lines. One for the missed call from A to B

to:

and the CDR record, with both legs, Alice to Bob and Bob to Charlie:

Deleted lines 339-344:

ACC: call missed: timestamp=1474899448;created=1474899444;setuptime=4;method=INVITE; from_tag=1766231375;to_tag=;call_id=604787970;code=408;reason=Request Timeout; caller_domain=10.0.0.135;callee_domain=10.0.0.135;caller=A;callee=B @] and the CDR record, with both legs, A to B and B to c: [@

Changed line 342 from:
  caller_domain=10.0.0.135;callee_domain=10.0.0.135;caller=A;callee=B;caller=B;callee=C
to:
  src_ip=10.0.0.101;dst_ip=10.0.0.203;caller=Alice;callee=Bob;caller=Bob;callee=Charlie
Changed lines 344-346 from:

If using db engine two lines will be generated, one with the leg from A to B and one with the leg from B to C. The rest of the information will be the same.

to:

If using db engine two rows will be generated, one with the leg from Alice to Bob and one with the leg from Bob to Charlie. The non-leg fields will be the same in all the legs:

|   created  | .... |reason|   src_ip   |   dst_ip   | caller | callee  |
| 1474899444 | .... |  OK  | 10.0.0.101 | 10.0.0.203 | Alice  |   Bob   |
| 1474899444 | .... |  OK  | 10.0.0.101 | 10.0.0.203 |  Bob   | Charlie |
November 01, 2016, at 07:26 PM by 109.99.227.30 -
Added lines 244-247:

This is the full OpenSIPS config file used for this example.


Changed lines 286-287 from:

Sometimes the extra values are not enough. One such scenario is when user A calls to user B, but B doesn't not respond and he's got a redirect to user C. In this case we have two legs, from A to B and from B to C. We may need to account separate information for these legs. In the current scenario caller and callee usernames for both legs will be accounted. There are backends that will generate multiple accounting requests, one for each leg. For example, if using db backend, you will have one line in your table for each leg. All dialogs will be accounted with their CDRs including each destination that we have a missed call with. The backend that will be used is the same as in the previous examples, the syslog backend.

to:

Sometimes the extra values are not enough. One such scenario is when user Alice calls to user Bob, but Bob doesn't not respond and he's got a redirect to user Charlie. In this case we have two logical legs, from Alice to Bob and from Bob to Charlie. And we want to get separate accounting information for each of these legs. In OpenSIPS, this is called multi-leg accounting or per-leg accounting.


In our example, we want to account the caller and callee usernames for each leg (as they we differ for the two legs). Depending on the accounting backend, when using multi-leg accounting, a single accounting records may translate into multiple backend records (one for each leg). For example, if using db backend, you will have one row per leg in the accounting table (this is because in SQL the format of the table is fixed, and it cannot vary with the number of legs).


This is the full OpenSIPS config file used for this example.


Changed lines 302-304 from:

The same is the case for $acc_leg variable. The only difference is that this variable can be indexed using the leg number. No index means the current leg. You can also get the number of the last leg using $acc_current_leg variable. New legs can be created with acc_new_leg() function.

In the script, everything that concerns lookup function was moved into a route, in order to use it multiple times. For the initial call, we'll get the name of the caller from the From header. The name of the callee is in the R-URI:

to:


The same is the case for $acc_leg variable. The only difference is that this variable can be indexed using the leg number. No index means the current leg. You can also get the number of the last leg using $acc_current_leg variable. New additional legs can be created with acc_new_leg() function.


In the script, everything that concerns lookup function was moved into a route, in order to use it multiple times. For the initial call, we'll get the URI of the caller from the From header. The URI of the callee is in the R-URI:

November 01, 2016, at 07:05 PM by 109.99.227.30 -
Changed line 244 from:

Starting from the previous script, we try to add extra accounting information about the caller's and callee's URI. First of all we need to define the additional data that will be added to our accounted information in the modparam section using the extra_fields parameter

to:

Starting from the previous script, we try to add extra accounting information about the IP addresses where the call was originated from and terminated to. First of all we need to define the additional data that will be added to our accounted information in the modparam section using the extra_fields parameter

Changed line 246 from:
   modparam("acc", "extra_fields", "log: caller_uri; callee_uri")
to:
   modparam("acc", "extra_fields", "log: src_ip; dst_ip")
Changed line 250 from:
   modparam("acc", "extra_fields", "log: caller_uri->callee_uri; callee_uri->callee_uri")
to:
   modparam("acc", "extra_fields", "log: src_ip->src_ip; src_ip->dst_ip")
Changed lines 256-257 from:

In terms of scripting, all we need to do is to set the $acc_extra variable with the values we what. In the current scenario we set the domains

to:

In terms of scripting, all we need to do is to set the $acc_extra variable with the values we what. In the current scenario we set the IPs as follow:

  • for the originating IP of the call we consider the source IP of the INVITE (initial request), so in request route, when handling initial SIP requests, we do (see line 224):
Changed lines 259-261 from:
        $acc_extra(caller_uri) = $ru;
        $acc_extra(callee_uri) = $tu;
to:
        $acc_extra(src_ip) = $si;
Changed lines 261-262 from:

The CDR for the current call will contain the new extra values, as we set them

to:
  • for the termination IP of the call we consider the source IP of final SIP reply (>=200), so in the onreply route, when handling SIP replies, we do (see line 268):
Added lines 263-269:
    if ( $rs >= 200 )
        $acc_extra(dst_ip) = $si;

@]

The CDR for the current call will contain the new extra values, as we set them [@

Changed line 272 from:
  call_id=604787970;code=200;reason=OK;caller_uri=sip:alice@opensips.org;callee_uri=sip:bob@opensips.org
to:
  call_id=604787970;code=200;reason=OK;src_ip=10.0.0.101;dst_ip=10.0.0.203
November 01, 2016, at 06:45 PM by 109.99.227.30 -
Changed line 238 from:
to:

Added lines 271-275:


Here it is the full OpenSIPS config file used in this example.


November 01, 2016, at 06:20 PM by 109.99.227.30 -
Changed lines 240-242 from:

There are cases when you may need to add some extra values to the default accounted information. Since version 2.3 this engine was modified in order to make it easier for the users to provision additional information in their account entries. In order to do this we will use the extra accounting engine, with which we will be able to add additional information together with the basic information that is provided by default. All dialogs will be accounted with their CDRs including each destination that we have a missed call with. The backend that will be use is the same as in the previous examples, the syslog backend. Starting from the previous script, we try to add extra information about the caller's and callee's domains. First of all we need to define the additional data that will be added to our accounted information in the modparam section using the extra_fields parameter

to:

There are cases when you may need to extend your accounting capabilities and to add some additional custom values to the accounting records (in addition to the default fields). This is called extra accounting - shortly, you define some new accounting fields and set what values is to be placed into them.


Starting from the previous script, we try to add extra accounting information about the caller's and callee's URI. First of all we need to define the additional data that will be added to our accounted information in the modparam section using the extra_fields parameter

Changed line 246 from:
   modparam("acc", "extra_fields", "log: caller_domain; callee_domain")
to:
   modparam("acc", "extra_fields", "log: caller_uri; callee_uri")
Changed line 250 from:
   modparam("acc", "extra_fields", "log: caller_domain->callee_domain; callee_domain->callee_domain")
to:
   modparam("acc", "extra_fields", "log: caller_uri->callee_uri; callee_uri->callee_uri")
Changed lines 252-254 from:

The first part of the declaration is the backend for which the values are declared, in this case the log backend. The following are declarations in form of script-tag->account-tag. The script-tag is the tag used for referencing $acc_extra variable, which will hold all our extra values. The scope of the variable depends on the accounting type used. If the cdr flag is used when calling do_accounting(), the variable will be visible for the whole duration of the dialog, else it will be visible as long as the transaction will be visible. The account-tag is how the information will be identified when accounted, that is the tag identifier for log, column name for db or AVP name for aaa. As concers the script, all we need to do is to set $acc_extra variable. In the current scenario we set the domains

to:

The first part of the declaration is the backend for which the extra fields are defined, in this case the log backend. The definitions are in form of script-tag -> backend-tag. The script-tag is the tag to be used in OpenSIPS script to reference the $acc_extra variable, which will hold all our extra values. The scope of the variable depends on the accounting type used. If the cdr flag is used when calling do_accounting(), the variable will be visible for the whole duration of the dialog, else it will be visible as long as the transaction will be visible. The backend-tag is where the values will be stored in the accounting backend ( for log it is a display label, for db it is a column name or for aaa it is an RADIUS/DIAMETER AVP name).


In terms of scripting, all we need to do is to set the $acc_extra variable with the values we what. In the current scenario we set the domains

Changed lines 259-261 from:
        $acc_extra(caller_domain) = $rd;
        $acc_extra(callee_domain) = $td;
to:
        $acc_extra(caller_uri) = $ru;
        $acc_extra(callee_uri) = $tu;
Changed line 268 from:
  call_id=604787970;code=200;reason=OK;caller_domain=X.X.X.X;callee_domain=X.X.X.X
to:
  call_id=604787970;code=200;reason=OK;caller_uri=sip:alice@opensips.org;callee_uri=sip:bob@opensips.org
November 01, 2016, at 03:29 PM by 109.99.227.30 -
Added line 62:
Changed lines 71-74 from:

The leg_fields module parameter defines a list of new fields that will be different from leg to leg (all the other fields - the default and extra accounting ones - will be the same for all the legs). Each set of leg_fields values will translate into a separate leg for the call.\\

to:

The leg_fields module parameter defines a list of new fields that will be different from leg to leg (all the other fields - the default and extra accounting ones - will be the same for all the legs). Each set of leg_fields values will translate into a separate leg for the call.


Changed line 167 from:
  • add dialog scope (cdr keyword) when setting the success event for the INVITE requests
to:
  • add dialog scope (cdr keyword) when setting the success event for the INVITE requests
Changed line 187 from:

To get directly CDR as accounting records, when doing do_accounting() (line 193) for initial INVITEs (which create SIP calls/dialogs), we need to switch it from transaction scope to dialog scope, by using the cdr keyword to the flags:

to:

To get directly CDR as accounting records, when doing do_accounting() (line 193) for initial INVITEs (which create SIP calls/dialogs), we need to switch it from transaction scope to dialog scope, by using the cdr keyword to the flags:

Added lines 233-236:


Once again, this is the full OpenSIPS config file we used for this example.

November 01, 2016, at 03:27 PM by 109.99.227.30 -
Changed lines 23-29 from:
  • SIP message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request(), acc_db_request(), acc_aaa_request() or acc_evi_request() depending on the backend used;
  • SIP transaction level accounting: the generated CDR covers a SIP transaction (the duration and data from the SIP request and all its replies); such accounting is used when OpenSIPS acts as a stateful SIP proxy; this accounting is armed/set during the request processing, but the CDR itself will be generated when the SIP transaction (including all its branches) will be completed;
  • SIP dialog level accounting: the generated CDR covers a whole SIP call/dialog; such CDR may additionally (to the SIP transaction CDRs) contain information from the dialog level (call duration, BYE reason, RTP stats); In terms of usage, the dialog accounting is armed/set while handling the initial INVITE request; the CDR itself will be generated when the SIP dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
to:
  • SIP message level accounting: the generated accounting record covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request(), acc_db_request(), acc_aaa_request() or acc_evi_request() depending on the backend used;
  • SIP transaction level accounting: the generated accounting record covers a SIP transaction (the duration and data from the SIP request and all its replies); such accounting is used when OpenSIPS acts as a stateful SIP proxy; this accounting is armed/set during the request processing, but the accounting record itself will be generated when the SIP transaction (including all its branches) will be completed;
  • SIP dialog level accounting: the generated accounting record covers a whole SIP call/dialog; such accounting record is also known as CDR (Call Data Record). This record, in addition to the transaction-scope accounting records, may contain information from the dialog level (call duration, BYE reason, RTP stats); In terms of usage, the dialog accounting is armed/set while handling the initial INVITE request; the CDR itself will be generated when the SIP dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
Changed line 32 from:
  • success event. Such even generates a CDR when:
to:
  • success event. Such even generates an accounting record when:
Changed lines 60-61 from:

This mechanism allows you to extend the CDR field by adding custom fields to it (with data collected anytime during the scope of the accounting).
The extra_fields module parameter allows the definition of a list of new fields to be added to the CDR formt. During the script processing, those fields may be populated anywhere and anytime as you are still in the scope of that accounting action. There is a special script variable defined for this mechanism called $acc_extra which can be populated with whatever you want; the $acc_extra variable is persistent across the whole accounting scope - for example, if you do transaction based accounting, you can collect data (to be pushed into the extra accounting fields) during the request handling, in reply route or during a call forking in failure route.\\

to:

This mechanism allows you to extend the accounting record field by adding custom fields to it (with data collected anytime during the scope of the accounting).
The extra_fields module parameter allows the definition of a list of new fields to be added to the format of the accounting record. During the script processing, those fields may be populated anywhere and anytime as you are still in the scope of that accounting action.
There is a special script variable defined for this mechanism called $acc_extra which can be populated with whatever you want; the $acc_extra variable is persistent across the whole accounting scope - for example, if you do transaction based accounting, you can collect data (to be pushed into the extra accounting fields) during the request handling, in reply route or during a call forking in failure route.\\

Changed line 69 from:

There are SIP scenarios where there is a need to get multiple CDRs for a single SIP call. Typically this happens when implementing call redirect or call forward and the actual SIP call consists out of several call legs (logical calls between SIP entities).\\

to:

There are SIP scenarios where there is a need to get multiple accounting records for a single SIP call. Typically this happens when implementing call redirect or call forward and the actual SIP call consists out of several call legs (logical calls between SIP entities).\\

Changed line 107 from:
                                # do accunting, even if the transaction fails
to:
                                # do accounting, even if the transaction fails
Changed lines 158-159 from:
  • enable multiple missed calls events during SIP serial forking. Let's take the case when there is a call for user Alice but Alice has multiple contacts registered (via SIP registration), like Contact1, Contact2 and Contacct3. The order for serial forking should be Contact1, Contact2 and Contact3. That is first time we try to call Contact1, if Contact1 does not respond Contact2 shall be tried and the last try should be made to Contact3. Last, but not least, if the call is to established (to any of the contacts), the CDR will be accounted.
to:
  • enable multiple missed calls events during SIP serial forking. Let's take the case when there is a call for user Alice but Alice has multiple contacts registered (via SIP registration), like Contact1, Contact2 and Contacct3. The order for serial forking should be Contact1, Contact2 and Contact3. That is first time we try to call Contact1, if Contact1 does not respond Contact2 shall be tried and the last try should be made to Contact3. Last, but not least, if the call is to established (to any of the contacts), the call will be accounted.
Added lines 169-172:

This is the config file corresponding to this scenario. All below explanations are relative to this script.


Changed lines 215-217 from:

If do_accounting() would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. The next_branches() function call will get the next destination for us. If we still have contacts to call to we arm the failure route again in order to be able to send the message to next destination.

A missed call account event will be generated for each destiantion that did not respond looking like this

to:

If do_accounting() would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. The next_branches() function call will get the next destination for us. If we still have contacts to call to we arm the failure route again in order to be able to send the call to the next destination.

A missed call event will be generated for each destination that did not accept the call:

Changed line 222 from:

The reply code and the reason may change depending on the scenario. If at least one of the contacts answered and the call is established, a CDR will be generated after the call ended:

to:

The reply code and the reason may change depending on the scenario. If at least one of the contacts answered and the call is established, the CDR (as success event) will be generated after the call ended:

Changed line 228 from:

Here, aside from the basic information that is present in every account record we can see the call_start_time, and the call duration both in seconds and milliseconds.

to:

Here, besides the basic information that is present in every accounting record we can see the the additional fields call_start_time, and the call duration both in seconds and milliseconds.

November 01, 2016, at 03:01 PM by 109.99.227.30 -
Changed lines 159-162 from:

To achieve this behavior we do the following extensions to the accounting functions:

  • add dialog scope (cdr keyword) when setting the success event for the INVITE transactions
  • enable missed call event in failure route, when doing serial forking.
to:

To achieve this behavior we do the following changes to the accounting functions:

  • add dialog scope (cdr keyword) when setting the success event for the INVITE requests
  • as we do accounting at dialog level (we get CDRs directly), there is no need to separately account the BYE transaction, so we remove any accounting for them
  • enable missed call event also in failure route, so we can get such events during the sequential steps of the serial forking.
Changed lines 172-176 from:

The last do_accounting() call from the default script was changed to

to:

Now, in terms of scripting we remove the do_accounting() for the BYE transactions (as we do accounting at dialog level, not transaction level any more) - see the sequential request block, line 127 where the accounting call was stripped out.


To get directly CDR as accounting records, when doing do_accounting() (line 193) for initial INVITEs (which create SIP calls/dialogs), we need to switch it from transaction scope to dialog scope, by using the cdr keyword to the flags:

Changed lines 178-179 from:
        # when routing via usrloc, log the missed calls also
        do_accounting("log","cdr|missed");
to:
        # account only INVITEs
	if (is_method("INVITE")) {
		do_accounting("log", "cdr");
	}
Changed lines 183-184 from:

which, aside from the missed calls, enables logging the CDRs. Keep in mind that the CDR flag affects only the calls(dialogs). To enable serial forking the following lines were added below do_accounting() call.

to:

Keep in mind that the CDR flag affects only the calls(dialogs).


To enable serial forking (for all the registered contacts) the following lines were added after a successful lookup into location table. The code is serializing the found contact based on their priority (Q parameter) - first we send the call to the higher priority contacts and in case of failure (no call established), we serial fork the call to the next contacts with lower priority (see serialize_branches() description) . This re-attempting (serial forking) is done until there are no more contacts left.

Changed line 208 from:

If do_accounting() would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. next_branches() function call will get the next destination for us. If we still have contacts to call to we arm the failure route again in order to be able to send the message to next destination.

to:

If do_accounting() would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. The next_branches() function call will get the next destination for us. If we still have contacts to call to we arm the failure route again in order to be able to send the message to next destination.

October 31, 2016, at 07:04 PM by 109.99.227.30 -
Changed lines 151-155 from:

CDR and serial forking accounting

In this scenario, the default script has be modified, in order to show you how all the missed calls can be accounted when it comes to serial forking. Let's take the case when there is a call for user X but X has multiple contacts, let's call them A, B and C. The order for serial forking should be A, B and C. That is first time we try to call A, if A does not respond B shall be tried and the last try should be made to C. Last, but not least, if the call is to happen(any of A,B or C will respond), CDR will also be accounted. This will happen only for the internally registered users using usrloc module. Same backend shall be used as in the previous example, the syslog daemon.

First of all, in order to be able to use the CDR engine, dialog module needs to be loaded

to:

CDR-based and serial forking accounting

In this new example, we extend the accounting functionality offered by the previous script in order to additionally achieve :

  • enable dialog level accounting so we can get CDRs (as accounting records)
  • enable multiple missed calls events during SIP serial forking. Let's take the case when there is a call for user Alice but Alice has multiple contacts registered (via SIP registration), like Contact1, Contact2 and Contacct3. The order for serial forking should be Contact1, Contact2 and Contact3. That is first time we try to call Contact1, if Contact1 does not respond Contact2 shall be tried and the last try should be made to Contact3. Last, but not least, if the call is to established (to any of the contacts), the CDR will be accounted.


To achieve this behavior we do the following extensions to the accounting functions:

  • add dialog scope (cdr keyword) when setting the success event for the INVITE transactions
  • enable missed call event in failure route, when doing serial forking.


First of all, in order to be able to use the CDR engine, dialog module needs to be loaded (we do it here in the simplest possible way):

October 31, 2016, at 05:24 PM by 109.99.227.30 -
Changed lines 122-123 from:

Also in the request route, when handling the initial requests, for INVITE requests we do (see line xxx):

to:

Also in the request route, when handling the initial requests, for INVITE requests we do (see line 194):

Changed line 140 from:

The last do_accounting() usage in the script is for triggering the missed call events for the calls (INVITE requests) sent to our registered users.

to:

The last do_accounting() usage in the script (line 231) is for triggering the missed call events for the calls (INVITE requests) sent to our registered users.

Added lines 145-147:

Once again, this is the full OpenSIPS config file we used for this example.

October 31, 2016, at 05:17 PM by 109.99.227.30 -
Changed lines 120-121 from:

to:


Changed lines 138-140 from:

The last do_accounting() usage in the script is for enabling missed call events for the calls (INVITE requests) sent to our registered users.

to:


The last do_accounting() usage in the script is for triggering the missed call events for the calls (INVITE requests) sent to our registered users.

Changed line 146 from:

For them missed calls accounting is also enabled. Keep in mind that missed call accounting is related only to INVITE transactions, it will have no effect for other types.

to:

October 31, 2016, at 05:15 PM by 109.99.227.30 -
Added lines 79-80:


Added lines 86-87:


Changed lines 90-91 from:

In the routing section of the script the do_accounting() function is used for setting the accounting process (as events, scope and backend). In all case the log backend is used, which means that all the accounting records will be pushed as logs. This script is logging to syslog service, using log facility LOG_DAEMON (see log_facility ) with log level L_NOTICE (see log_level.

to:


In the routing section of the script the do_accounting() function is used for setting the accounting process (as events, scope and backend). In all case the log backend is used, which means that all the accounting records will be pushed as logs. This script is logging to syslog service, using log facility LOG_DAEMON (see log_facility ) with log level L_NOTICE (see log_level).


Changed line 111 from:

This line will trigger for all the BYE transactions the success and the failed transactions(reply code >= 300) accounting events. Here is an example of how the accounted lines should look line in your syslog

to:

Here is an example of how the accounted lines should look line in your syslog

October 31, 2016, at 04:57 PM by 109.99.227.30 -
Deleted lines 78-80:
opensips.cfg sample script
Added lines 84-85:

Now, let's walk through the opensips.cfg and explain step by step all the accounting related actions.

Changed line 88 from:

When handling the SIP requests in the request route, inside the block for sequential request, the do_accounting() function is used at line 127:

to:

When processing the SIP requests in the request route, when handling the sequential request, the do_accounting() function is used (see line 127) to trigger accounting records on success and failed transactions(reply code >= 300) events for all the BYE transactions:

October 31, 2016, at 03:18 PM by 109.99.227.30 -
Changed line 36 from:
to:

http://opensips.org/pub/docs/tutorials/accounting/images/acc_event_success_dialog.png

October 31, 2016, at 03:15 PM by 109.99.227.30 -
October 31, 2016, at 03:01 PM by 109.99.227.30 -
Added line 22:
Added line 24:
Added line 26:
Changed lines 39-41 from:

http://opensips.org/images/tutorials/acc_event_missed.png

to:

http://opensips.org/pub/docs/tutorials/accounting/images/acc_event_missed.png

Changed line 43 from:

http://opensips.org/images/tutorials/acc_event_failed.png

to:

http://opensips.org/pub/docs/tutorials/accounting/images/acc_event_failed.png

October 31, 2016, at 03:00 PM by 109.99.227.30 -
Changed line 31 from:

http://opensips.org/images/tutorials/acc_event_success.png

to:

http://opensips.org/pub/docs/tutorials/accounting/images/acc_event_success.png

October 31, 2016, at 02:44 PM by 109.99.227.30 -
Changed line 74 from:

Starting from default opensips script examples will be given which will help have a better picture about how accounting works in OpenSIPS and how the parameter can be used in real case scenarios.

to:

The OpenSIPS default config file provides a simple accounting support. This will be used as a starting point in our quest to understand and script more and more complex accounting scenarios.

October 31, 2016, at 02:11 PM by 109.99.227.30 -
Changed lines 79-82 from:

First example will account successful INVITE transactions and all BYE transactions, no matter the response code. The syslog backend shall be used for accounting which has the keyword log. No missed calls shall be accounted. By default OpenSIPS comes with a sample script called opensips.cfg which uses the accounting module. In the following lines every line that involves the module shall be explained.

First of all, the module is loaded using the modparam statement. All the parameters declared here have their default value, so they can be very easily removed.

to:

In this script, we want to get accounting records only for call related requests - for INVITE and BYE transactions. So, the accounting is done only at transaction level and the following accounting events are configured:

  • success event for the INVITE transactions
  • success event and failed transaction event for the BYE transactions - we want an accounting record no matter response code we get for the BYE.

The syslog backend shall be used for accounting - this has the keyword log.

In the routing section of the script the do_accounting() function is used for setting the accounting process (as events, scope and backend). In all case the log backend is used, which means that all the accounting records will be pushed as logs. This script is logging to syslog service, using log facility LOG_DAEMON (see log_facility ) with log level L_NOTICE (see log_level.

When handling the SIP requests in the request route, inside the block for sequential request, the do_accounting() function is used at line 127:

Deleted lines 87-97:

loadmodule "acc.so" /* what special events should be accounted ? */ modparam("acc", "early_media", 0) modparam("acc", "report_cancels", 0) modparam("acc", "detect_direction", 0) @]

Next every section in the script where do_accounting() function is used will be explained. First of all, we can see that, for every call the log backend is used, which will mean that all the accounted information will go wherever all the other logs will go, that is the LOCAL0 facility of the syslog service for this configuration. One can change this behaviour by modifying the log_facility parameter in the acc modparam section.

The first time we can see do_accounting() function used is on line 127 where the following is used [@

Changed line 101 from:

This line will account all the BYE transactions, including the failed transactions(reply code >= 300). Here is an example of how the accounted lines should look line in your syslog

to:

This line will trigger for all the BYE transactions the success and the failed transactions(reply code >= 300) accounting events. Here is an example of how the accounted lines should look line in your syslog

Changed lines 108-109 from:

Not using the failed flag for do_accounting() would have resulted in not having this account line, since the reply code is 400.

to:

If the failed option is not used, the do_accounting() will not trigger the failed transactions event and the above record will not be generated (since the transaction completes with a 400 reply code).

Changed lines 111-112 from:

Next in the script we can see the following line

to:

Also in the request route, when handling the initial requests, for INVITE requests we do (see line xxx):

Changed line 120 from:

As you can see, this function call applies only to INVITE transactions where the request is also an initial request, sequential requests are handled above. Since no flag is specified, only successful transactions will be accounted. Accounted information will look more or less the same as the one for the BYE transaction:

to:

Since no flag is specified, only success events will be accounted for the transaction:

Changed line 127 from:

The last do_accounting() usage in the script is related only to calls to registered users

to:

The last do_accounting() usage in the script is for enabling missed call events for the calls (INVITE requests) sent to our registered users.

October 31, 2016, at 01:31 PM by 109.99.227.30 -
Added lines 20-26:

Accounting scopes

The accounting may have different scopes and it may be in-line with different SIP elements :

  • SIP message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request(), acc_db_request(), acc_aaa_request() or acc_evi_request() depending on the backend used;
  • SIP transaction level accounting: the generated CDR covers a SIP transaction (the duration and data from the SIP request and all its replies); such accounting is used when OpenSIPS acts as a stateful SIP proxy; this accounting is armed/set during the request processing, but the CDR itself will be generated when the SIP transaction (including all its branches) will be completed;
  • SIP dialog level accounting: the generated CDR covers a whole SIP call/dialog; such CDR may additionally (to the SIP transaction CDRs) contain information from the dialog level (call duration, BYE reason, RTP stats); In terms of usage, the dialog accounting is armed/set while handling the initial INVITE request; the CDR itself will be generated when the SIP dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
Changed lines 28-29 from:

OpenSIPS can account different events happening during a transaction/dialog lifetime, such as:

  • successful transactions/dialogs: transaction/call has successfully established from the UAC/caller perspective; it can be only one such event per SIP call;
to:

OpenSIPS can account different events during the accounting scope, such as:

  • success event. Such even generates a CDR when:
    • in transaction scope the transaction when successfully completed (with a 2xx reply);
Changed lines 32-35 from:
  • missed calls: a call branch did not established, as the UAS rejected or declined the call attempted ; there can be multiple such events per a single SIP call (due SIP forking). Note that a SIP call that generated a ACC successfully established event may generate some missed call event (for the SIP branches that failed during serial or parallel forking); The missed call events are also known as UAS-side accounting (as they are related to the relation between OpenSIPS and callee/UAS side).
to:
  • it dialog scope when the call was successfully established ;
  • missed call event. Such event may be generated only during the dialog setup phase (during the lifetime of the transaction for the initial INVITE), when a call attempt (or branch) did not established, as the UAS destination rejected or declined the call; There can be multiple such events per a single SIP call (due SIP forking). Note that a SIP call generating a accounting success event may also generate some missed call event because of the SIP branches (call attempts) that failed during serial or parallel forking; The missed call events are also known as UAS-side accounting (as they are related to the relation between OpenSIPS and callee/UAS side).
Changed lines 37-39 from:
  • failed transaction: generated when a transaction fails (reply code >=300) on the UAC side of OpenSIPS - this is a complementary event for the successfully transaction event.
to:
  • failed transaction event. Such event is generated only in the transaction scope, when a transaction fails (reply code >=300) on the UAC side of OpenSIPS - this is a complementary event for the successfully transaction event.
Deleted lines 41-45:

Accounting scopes

The accounting CDR may have different scopes and may get aligned to different SIP entities :

  • message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request(), acc_db_request(), acc_aaa_request() or acc_evi_request() depending on the backend used;
  • transaction level accounting: the generated CDR covers only one SIP transaction; such accounting is used when OpenSIPS is used as a stateful SIP proxy; the accounting is triggered when the request is processed and the CDR will be generated when the SIP transaction (including all its branches) will be completed;
  • dialog level accounting: the generated CDR covers a whole SIP call; you have to enable it when the initial INVITE is processed and the actual CDR will be generated when the dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
October 12, 2016, at 07:41 PM by etamme -
Changed line 229 from:

In case our call to B, as described above, fails we will get into failure route where we will fetch the next destination as usual. For redirects, we check if the new destination is a local uri, meaning that we have to resolve the same way we did with the first uri, using lookup function. Now the call from B to C starts, so we'll create a new leg. We need to store the name of the caller before calling next_branches() function, because after this call we will lose it:

to:

In case our call to B, as described above, fails and we will get into failure route where we will fetch the next destination as usual. For redirects, we check if the new destination is a local uri, meaning that we have to resolve the same way we did with the first uri, using lookup function. Now the call from B to C starts, so we'll create a new leg. We need to store the name of the caller before calling next_branches() function, because after this call we will lose it:

October 12, 2016, at 07:40 PM by etamme -
Changed line 229 from:

In case our call to B as described upwards fails we'll get to failure route where we will fetch the next destination, as usual. For redirects, we check if the new destination is a local uri, meaning that we have to resolve the same way we did with the first uri, using lookup function. Now the call from B to C starts, so we'll create a new leg. We need to store the name of the caller before calling next_branches() function, because after this call we will lose it:

to:

In case our call to B, as described above, fails we will get into failure route where we will fetch the next destination as usual. For redirects, we check if the new destination is a local uri, meaning that we have to resolve the same way we did with the first uri, using lookup function. Now the call from B to C starts, so we'll create a new leg. We need to store the name of the caller before calling next_branches() function, because after this call we will lose it:

October 12, 2016, at 07:38 PM by etamme -
Changed line 216 from:

Sometimes the extra values are not enough. One such scenario is when user A calls to user B, but B doesn't not respond and he's got a redirect to user C. In this case we have two legs, from A to B and from B to C. We may need to account separate information for these legs. In the current scenario caller and callee usernames for both legs will be accounted. There are backends that will generate multiple accounting requests, one for each leg. For example, if using db backend, you will have one line in your table for each leg. All dialogs will be accounted with their CDRs including each destination that we have a missed call with. The backend that will be use is the same as in the previous examples, the syslog backend.

to:

Sometimes the extra values are not enough. One such scenario is when user A calls to user B, but B doesn't not respond and he's got a redirect to user C. In this case we have two legs, from A to B and from B to C. We may need to account separate information for these legs. In the current scenario caller and callee usernames for both legs will be accounted. There are backends that will generate multiple accounting requests, one for each leg. For example, if using db backend, you will have one line in your table for each leg. All dialogs will be accounted with their CDRs including each destination that we have a missed call with. The backend that will be used is the same as in the previous examples, the syslog backend.

October 12, 2016, at 07:35 PM by etamme -
Changed line 198 from:

The first part of the declaration is the backend for which the values are declared, in this case the log backend. The following are declarations in form of script-tag->account-tag. The script-tag is the tag used for referencing $acc_extra variable, which will hold all our extra values. The scope of the variable depends on the accounting type used. If the cdr flag is used, the variable will be visible for the whole duration of the dialog, else it will be visible as long as the transaction will be visible. The account-tag is how the information will be identified when accounted, that is the tag identifier for log, column name for db or AVP name for aaa.

to:

The first part of the declaration is the backend for which the values are declared, in this case the log backend. The following are declarations in form of script-tag->account-tag. The script-tag is the tag used for referencing $acc_extra variable, which will hold all our extra values. The scope of the variable depends on the accounting type used. If the cdr flag is used when calling do_accounting(), the variable will be visible for the whole duration of the dialog, else it will be visible as long as the transaction will be visible. The account-tag is how the information will be identified when accounted, that is the tag identifier for log, column name for db or AVP name for aaa.

October 12, 2016, at 05:46 PM by etamme -
Changed line 49 from:

This mechanism allow you to extend the CDR field by adding custom fields to it (with data collected anytime during the scope of the accounting).\\

to:

This mechanism allows you to extend the CDR field by adding custom fields to it (with data collected anytime during the scope of the accounting).\\

Changed line 55 from:

There are SIP scenario where there is a need to get multiple CDRs for a single SIP call. Typically this happens when implementing call redirect or call forward and the actual SIP call consists out of several call legs (logical calls between SIP entities).\\

to:

There are SIP scenarios where there is a need to get multiple CDRs for a single SIP call. Typically this happens when implementing call redirect or call forward and the actual SIP call consists out of several call legs (logical calls between SIP entities).\\

October 12, 2016, at 05:36 PM by etamme -
Changed line 11 from:

Concepts such as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. More complex scenarios including advanced features like extra accounting (extending the CDR format and collect information from the entire call), and multi-leg accounting (multiple CDR records per SIP call) are also covered.\\

to:

Concepts such as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. More complex scenarios including advanced features like extra accounting (extending the CDR format and collecting information from the entire call), and multi-leg accounting (multiple CDR records per SIP call) are also covered.\\

October 12, 2016, at 05:35 PM by etamme -
Changed lines 11-14 from:

Concepts such as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. For more complex scenarios, advanced features like extra accounting (extend the CDR format and collect information from the entire call) and multi-leg accounting (multiple CDR records per SIP call) are described and put to work.
Everything in this tutorial is backed up with practical examples which you can run and disect in order to get a better picture about how accouting works and what can be the best option for your needs. Most of the features presented in this tutorial are available in versions starting with OpenSIPS 2.2, when there's been a major rework affecting the accounting module. There are many great improvements since the previous version which will ultimately help you having an easier jobs understanding and using the module.

to:

Concepts such as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. More complex scenarios including advanced features like extra accounting (extending the CDR format and collect information from the entire call), and multi-leg accounting (multiple CDR records per SIP call) are also covered.
Everything in this tutorial is backed up with practical examples which you can run and dissect in order to get a better picture about how accounting works, and what are the best accounting options for your needs. Most of the features presented in this tutorial are available in versions starting with OpenSIPS 2.2, where there has been a major rework affecting the accounting module. There are many great improvements over previous versions of OpenSips which will ultimately help you to better understand and use the accounting module.

October 12, 2016, at 05:30 PM by etamme -
Changed line 11 from:

Concepts as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. For more complex scenarios, advanced features like extra accounting (extend the CDR format and collect information from the entire call) and multi-leg accounting (multiple CDR records per SIP call) are described and put to work.\\

to:

Concepts such as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. For more complex scenarios, advanced features like extra accounting (extend the CDR format and collect information from the entire call) and multi-leg accounting (multiple CDR records per SIP call) are described and put to work.\\

October 12, 2016, at 05:28 PM by etamme -
Changed line 9 from:

SIP call accounting is a sensitive and challenging task. Even more, the flexibility and complexity of OpenSIPS escalates the understanding and the correctness of the accounting approaches. This tutorial explains all the elements and notions about accounting, as well as how to take full advantage of the powerful accounting engine provided by OpenSIPS.\\

to:

SIP call accounting is a sensitive and challenging task. The flexibility and complexity of OpenSIPS escalates the need to understand the complete details of the accounting approaches. This tutorial explains all the elements and notions about accounting, as well as how to take full advantage of the powerful accounting engine provided by OpenSIPS.\\

October 12, 2016, at 05:26 PM by etamme -
Changed line 9 from:

The SIP call accounting is a sensitive and challenging task. Even more, the flexibility and complexity of OpenSIPS escalates the understanding and the correctness of the accounting approaches. This tutorial explains all the elements and notions about accounting, as well as how to take full advantage of the powerful accounting engine provided by OpenSIPS.\\

to:

SIP call accounting is a sensitive and challenging task. Even more, the flexibility and complexity of OpenSIPS escalates the understanding and the correctness of the accounting approaches. This tutorial explains all the elements and notions about accounting, as well as how to take full advantage of the powerful accounting engine provided by OpenSIPS.\\

October 10, 2016, at 07:49 PM by 109.99.227.30 -
Changed line 23 from:

http://opensips.org/images/tutorials/acc_event_success.png

to:

http://opensips.org/images/tutorials/acc_event_success.png

Changed line 25 from:

http://opensips.org/images/tutorials/acc_event_missed.png

to:

http://opensips.org/images/tutorials/acc_event_missed.png

Changed line 27 from:

http://opensips.org/images/tutorials/acc_event_failed.png

to:

http://opensips.org/images/tutorials/acc_event_failed.png

October 10, 2016, at 07:45 PM by 109.99.227.30 -
Added line 23:

http://opensips.org/images/tutorials/acc_event_success.png

Added line 25:

http://opensips.org/images/tutorials/acc_event_missed.png

Changed lines 27-28 from:
to:

http://opensips.org/images/tutorials/acc_event_failed.png

Changed line 31 from:
  • message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request(), acc_db_request(), acc_aaa_request() or acc_evi_request() depending on the backend used;
to:
  • message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request(), acc_db_request(), acc_aaa_request() or acc_evi_request() depending on the backend used;
October 10, 2016, at 06:29 PM by 109.99.227.30 -
Added lines 16-17:

Changed lines 40-41 from:
to:

Added line 57:

October 10, 2016, at 06:29 PM by ionutionita92 -
Added line 64:

First example will account successful INVITE transactions and all BYE transactions, no matter the response code. The syslog backend shall be used for accounting which has the keyword log. No missed calls shall be accounted.

Changed lines 129-130 from:

In this scenario, the default script has be modified, in order to show you how all the missed calls can be accounted when it comes to serial forking. Let's take the case when there is a call for user X but X has multiple contacts, let's call them A, B and C. The order for serial forking should be A, B and C. That is first time we try to call A, if A does not respond B shall be tried and the last try should be made to C. Last, but not least, if the call is to happen(any of A,B or C will respond), CDR will also be accounted. This will happen only for the internally registered users using usrloc module.

to:

In this scenario, the default script has be modified, in order to show you how all the missed calls can be accounted when it comes to serial forking. Let's take the case when there is a call for user X but X has multiple contacts, let's call them A, B and C. The order for serial forking should be A, B and C. That is first time we try to call A, if A does not respond B shall be tried and the last try should be made to C. Last, but not least, if the call is to happen(any of A,B or C will respond), CDR will also be accounted. This will happen only for the internally registered users using usrloc module. Same backend shall be used as in the previous example, the syslog daemon.

Changed line 182 from:

provision additional information in their account entries.

to:

provision additional information in their account entries. In order to do this we will use the extra accounting engine, with which we will be able to add additional information together with the basic information that is provided by default. All dialogs will be accounted with their CDRs including each destination that we have a missed call with. The backend that will be use is the same as in the previous examples, the syslog backend.

Changed line 209 from:

Sometimes the extra values are not enough. One such scenario is when user A calls to user B, but B doesn't not respond and he's got a redirect to user C. In this case we have two legs, from A to B and from B to C. We may need to account separate information for these legs. In the current scenario caller and callee usernames for both legs will be accounted. There are backends that will generate multiple accounting requests, one for each leg. For example, if using db backend, you will have one line in your table for each leg.

to:

Sometimes the extra values are not enough. One such scenario is when user A calls to user B, but B doesn't not respond and he's got a redirect to user C. In this case we have two legs, from A to B and from B to C. We may need to account separate information for these legs. In the current scenario caller and callee usernames for both legs will be accounted. There are backends that will generate multiple accounting requests, one for each leg. For example, if using db backend, you will have one line in your table for each leg. All dialogs will be accounted with their CDRs including each destination that we have a missed call with. The backend that will be use is the same as in the previous examples, the syslog backend.

October 10, 2016, at 06:13 PM by ionutionita92 -
Changed lines 190-192 from:

The first part of the declaration is the backend for which the values are declared, in this case the log backend. The following are declarations in form of script-tag->account-tag. The script-tag is the tag used for referencing acc_extra variable, which will hold all our extra values. The scope of the variable depends on the accounting type used. If the cdr flag is used, the variable will be visible for the whole duration of the dialog, else it will be visible as long as the transaction will be visible. The account-tag is how the information will be identified when accounted, that is the tag identifier for log, column name for db or AVP name for aaa. As concers the script, all we need to do is to set acc_extra variable. In the current scenario we set the domains

to:

The first part of the declaration is the backend for which the values are declared, in this case the log backend. The following are declarations in form of script-tag->account-tag. The script-tag is the tag used for referencing $acc_extra variable, which will hold all our extra values. The scope of the variable depends on the accounting type used. If the cdr flag is used, the variable will be visible for the whole duration of the dialog, else it will be visible as long as the transaction will be visible. The account-tag is how the information will be identified when accounted, that is the tag identifier for log, column name for db or AVP name for aaa. As concers the script, all we need to do is to set $acc_extra variable. In the current scenario we set the domains

Changed lines 214-215 from:

The same is the case for acc_leg variable. The only difference is that this variable can be indexed using the leg number. No index means the current leg. You can also get the number of the last leg using acc_current_leg variable. New legs can be created with acc_new_leg function.

to:

The same is the case for $acc_leg variable. The only difference is that this variable can be indexed using the leg number. No index means the current leg. You can also get the number of the last leg using $acc_current_leg variable. New legs can be created with acc_new_leg() function.

Changed line 228 from:

If the call is a redirect, we will create a new leg and populate acc_leg accordingly. The name of the calle will be in the URI populated by next_branches() function.

to:

If the call is a redirect, we will create a new leg and populate $acc_leg accordingly. The name of the calle will be in the URI populated by next_branches() function.

October 10, 2016, at 06:10 PM by ionutionita92 -
Changed line 26 from:
  • message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request, acc_db_request, acc_aaa_request or acc_evi_request depending on the backend used;
to:
  • message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request(), acc_db_request(), acc_aaa_request() or acc_evi_request() depending on the backend used;
Changed lines 75-77 from:

Next every section in the script where do_accounting function is used will be explained. First of all, we can see that, for every call the log backend is used, which will mean that all the accounted information will go wherever all the other logs will go, that is the LOCAL0 facility of the syslog service for this configuration. One can change this behaviour by modifying the log_facility parameter in the acc modparam section.

The first time we can see do_accounting function used is on line 127 where the following is used

to:

Next every section in the script where do_accounting() function is used will be explained. First of all, we can see that, for every call the log backend is used, which will mean that all the accounted information will go wherever all the other logs will go, that is the LOCAL0 facility of the syslog service for this configuration. One can change this behaviour by modifying the log_facility parameter in the acc modparam section.

The first time we can see do_accounting() function used is on line 127 where the following is used

Changed lines 99-100 from:

Not using the failed flag for do_accounting would have resulted in not having this account line, since the reply code is 400.

to:

Not using the failed flag for do_accounting() would have resulted in not having this account line, since the reply code is 400.

Changed line 118 from:

The last do_accounting usage in the script is related only to calls to registered users

to:

The last do_accounting() usage in the script is related only to calls to registered users

Changed line 136 from:

The last do_accounting call from the default script was changed to

to:

The last do_accounting() call from the default script was changed to

Changed line 142 from:

To enable serial forking the following lines were added below do_accounting call.

to:

To enable serial forking the following lines were added below do_accounting() call.

Changed line 163 from:

If do_accounting would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. next_branches() function call will get the next destination for us. If we still have contacts to call to we arm the failure route again in order to be able to send the message to next destination.

to:

If do_accounting() would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. next_branches() function call will get the next destination for us. If we still have contacts to call to we arm the failure route again in order to be able to send the message to next destination.

October 10, 2016, at 06:06 PM by ionutionita92 -
Changed line 26 from:
  • message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request, acc_db_request, acc_aaa_request or acc_evi_request depending on the backend used;
to:
  • message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request, acc_db_request, acc_aaa_request or acc_evi_request depending on the backend used;
October 10, 2016, at 05:58 PM by liviu -
Changed line 180 from:
    There are cases when you may need to add some extra values to the default accounted information. Since version 2.3 this engine was modified in order to make it easier for the users to 
to:

There are cases when you may need to add some extra values to the default accounted information. Since version 2.3 this engine was modified in order to make it easier for the users to

Changed line 182 from:
     Starting from the previous script, we try to add extra information about the caller's and callee's domains. First of all we need to define the additional data that will be added to our accounted information in the modparam section using the extra_fields parameter
to:

Starting from the previous script, we try to add extra information about the caller's and callee's domains. First of all we need to define the additional data that will be added to our accounted information in the modparam section using the extra_fields parameter

October 10, 2016, at 05:55 PM by 109.99.227.30 -
Changed lines 126-127 from:
CDR and serial forking accounting
to:

CDR and serial forking accounting

Changed lines 178-179 from:
Extra values accounting
to:

Extra fields accounting

Changed line 206 from:
Multi-leg accounting
to:

Multi-leg accounting

October 10, 2016, at 05:44 PM by 109.99.227.30 -
Changed lines 94-96 from:

ACC: transaction answered: timestamp=1474540760;method=BYE;from_tag=2whdajbp4e-dzLdUwo8-coqaNKKh.oSp;to_tag=11562SIPpTag012;call_id=ezUcDyVPC9jgwtk35eamdhmIo31RSScI;code=400;reason=Reason

to:

ACC: transaction answered: timestamp=1474540760;method=BYE; from_tag=2whdajbp4e-dzLdUwo8-coqaNKKh.oSp;to_tag=11562SIPpTag012; call_id=ezUcDyVPC9jgwtk35eamdhmIo31RSScI;code=400;reason=Reason

Changed lines 113-115 from:

ACC: transaction answered: timestamp=1474540997;method=INVITE;from_tag=U49E.iWKOkX1URnBlpKMD.0hM4rIM2U0;to_tag=1173610.0.0.1351;call_id=vonxx1.d4qh9nfPmFBpu46u7Vvq5c8re;code=200;reason=OK

to:

ACC: transaction answered: timestamp=1474540997;method=INVITE; from_tag=U49E.iWKOkX1URnBlpKMD.0hM4rIM2U0;to_tag=1173610.0.0.1351; call_id=vonxx1.d4qh9nfPmFBpu46u7Vvq5c8re;code=200;reason=OK

Changed lines 167-168 from:

ACC: call missed: timestamp=1474637733;method=INVITE;from_tag=1931529157;to_tag=;call_id=182969767;code=408;reason=Request Timeout

to:

ACC: call missed: timestamp=1474637733;method=INVITE; from_tag=1931529157;to_tag=;call_id=182969767;code=408;reason=Request Timeout

Changed lines 172-174 from:

ACC: call ended: created=1474639265;call_start_time=1474639281;duration=5;ms_duration=4250;setuptime=16;method=INVITE;from_tag=1515466979;to_tag=1284910.0.0.1351;call_id=1766189979;code=200;reason=OK

to:

ACC: call ended: created=1474639265;call_start_time=1474639281; duration=5;ms_duration=4250;setuptime=16;method=INVITE;from_tag=1515466979; to_tag=1284910.0.0.1351;call_id=1766189979;code=200;reason=OK

Changed lines 200-202 from:

ACC: call ended: created=1474899444;call_start_time=1474899448;duration=5;ms_duration=4762;setuptime=4;method=INVITE;from_tag=1766231375;to_tag=2826210.0.0.1351;call_id=604787970;code=200;reason=OK;caller_domain=X.X.X.X;callee_domain=X.X.X.X

to:

ACC: call ended: created=1474899444;call_start_time=1474899448; duration=5;ms_duration=4762;setuptime=4;method=INVITE;from_tag=1766231375;to_tag=2826210.0.0.1351; call_id=604787970;code=200;reason=OK;caller_domain=X.X.X.X;callee_domain=X.X.X.X

Changed lines 244-246 from:

ACC: call missed: timestamp=1474899448;created=1474899444;setuptime=4;method=INVITE;from_tag=1766231375;to_tag=;call_id=604787970;code=408;reason=Request Timeout;caller_domain=10.0.0.135;callee_domain=10.0.0.135;caller=A;callee=B

to:

ACC: call missed: timestamp=1474899448;created=1474899444;setuptime=4;method=INVITE; from_tag=1766231375;to_tag=;call_id=604787970;code=408;reason=Request Timeout; caller_domain=10.0.0.135;callee_domain=10.0.0.135;caller=A;callee=B

Changed lines 250-252 from:

ACC: call ended: created=1474899444;call_start_time=1474899448;duration=5;ms_duration=4762;setuptime=4;method=INVITE;from_tag=1766231375;to_tag=2826210.0.0.1351;call_id=604787970;code=200;reason=OK;caller_domain=10.0.0.135;callee_domain=10.0.0.135;caller=A;callee=B;caller=B;callee=C

to:

ACC: call ended: created=1474899444;call_start_time=1474899448;duration=5;ms_duration=4762; setuptime=4;method=INVITE;from_tag=1766231375;to_tag=2826210.0.0.1351;call_id=604787970;code=200;reason=OK; caller_domain=10.0.0.135;callee_domain=10.0.0.135;caller=A;callee=B;caller=B;callee=C

October 10, 2016, at 05:41 PM by 109.99.227.30 -
Changed lines 44-45 from:

The extra_fields module parameter allows the definition of a list of new fields to be added to the CDR formt. During the script processing, those fields may be populated anywhere and anytime as you are still in the scope of that accounting action. There is a special script variable defined for this mechanism called $acc_extra which can be populated with whatever you want; the $acc_extra variable is persistent across the whole accounting scope - for example, if you do transaction based accounting, you can collect data (to be pushed into the extra accounting fields) during the request handling, in reply route or during a call forking in failure route.

to:

The extra_fields module parameter allows the definition of a list of new fields to be added to the CDR formt. During the script processing, those fields may be populated anywhere and anytime as you are still in the scope of that accounting action. There is a special script variable defined for this mechanism called $acc_extra which can be populated with whatever you want; the $acc_extra variable is persistent across the whole accounting scope - for example, if you do transaction based accounting, you can collect data (to be pushed into the extra accounting fields) during the request handling, in reply route or during a call forking in failure route.
NOTE that you need to take care and adjust your backend (database or radius) to accommodate the extra added values!!

Changed lines 48-52 from:
  • leg_fields: almost the same as the extra data, but this time one can set multiple legs for a call, which will result in multiple accounting requests; this shall be useful when logically, there are multiple calls, that is A calls to B and B redirects the call to C, meaning that there are two legs for this call: A to B and B to C. It is the script writer's job to decide whether a new leg has been created using acc_new_leg script function. The variable used to define extra leg fields is acc_leg;


IMPORTANT: In order to uses these features, some settings need to be made. That is, if you will use the database engine, the default accounting table will have to be changed. Also for aaa accounting, if using AVPs that are not defined, they will have to be defined in the dictionary.

to:

There are SIP scenario where there is a need to get multiple CDRs for a single SIP call. Typically this happens when implementing call redirect or call forward and the actual SIP call consists out of several call legs (logical calls between SIP entities).
The leg_fields module parameter defines a list of new fields that will be different from leg to leg (all the other fields - the default and extra accounting ones - will be the same for all the legs). Each set of leg_fields values will translate into a separate leg for the call.
As said, this shall be useful when logically, there are multiple legs inside a SIP call - like A calls to B and B redirects the call to C, meaning that there are two legs for this call: A to B and B to C. It is the script writer's job to decide whether a new leg has to be created by using acc_new_leg() script function. The variable used to hold the per-leg fields is $acc_leg - anytime, in the context of that leg, you can set the values for the per-leg fields.
NOTE that you need to take care and adjust your backend (database or radius) to accommodate the extra added values!!

Changed lines 56-58 from:
Intro
to:

Basic accounting

October 10, 2016, at 05:31 PM by 109.99.227.30 -
Changed lines 43-45 from:

This mechanism allow you to extend the CDR field by adding custom fields to it (with data collected anytime during the scope of the accounting). There might be cases when extra information, other than what's already accounted, might be needed. For this we've got:

  • extra_fields: you can define new fields for the accounting engine which shall be populated at the time when the accounting is being made; there is a special variable defined for this mechanism called acc_extra which can be populated with whatever you want; the acc_extra variable is persistent as concerns messages, transactions and dialogs, depending of the type of transaction used;
to:

This mechanism allow you to extend the CDR field by adding custom fields to it (with data collected anytime during the scope of the accounting).
The extra_fields module parameter allows the definition of a list of new fields to be added to the CDR formt. During the script processing, those fields may be populated anywhere and anytime as you are still in the scope of that accounting action. There is a special script variable defined for this mechanism called $acc_extra which can be populated with whatever you want; the $acc_extra variable is persistent across the whole accounting scope - for example, if you do transaction based accounting, you can collect data (to be pushed into the extra accounting fields) during the request handling, in reply route or during a call forking in failure route.

October 10, 2016, at 05:07 PM by 109.99.227.30 -
Changed line 24 from:

Accounting scope

to:

Accounting scopes

Changed lines 30-31 from:
Accounting backends
to:

Accounting backends

Changed lines 39-40 from:
Extending the accounting engine
to:

Extending the accounting engine

Extra accounting fields

This mechanism allow you to extend the CDR field by adding custom fields to it (with data collected anytime during the scope of the accounting).

Added lines 46-47:

Multi-leg accounting

October 10, 2016, at 05:01 PM by 109.99.227.30 -
Changed lines 24-29 from:
Accounting scope

Depending on the type of the accounting, there are multiple possibilities as concerns the scope:

  • message level accounting: this is mostly used when the reply is internally generated, OpenSIPS being the endpoint for a certain transaction; accounting is being made on the spot and this can be achieved using one of the following acc_log_request, acc_db_request, acc_aaa_request or acc_evi_request depending on the backend used;
  • transaction level accounting: that is when OpenSIPS is a proxy forwarding requests and replies; this transaction shall be accounted only at the moment when the reply came.
  • dialog level accounting: this type of accounting shall be used for accounting CDRs; you have to enable it when the initial INVITE have been received and the actual accounting shall be made when the dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
to:

Accounting scope

The accounting CDR may have different scopes and may get aligned to different SIP entities :

  • message level accounting: the generated CDR covers only the currently processed SIP request; this is also known as manual accounting, where the CDR is generated on the spot by using one of the script functions acc_log_request, acc_db_request, acc_aaa_request or acc_evi_request depending on the backend used;
  • transaction level accounting: the generated CDR covers only one SIP transaction; such accounting is used when OpenSIPS is used as a stateful SIP proxy; the accounting is triggered when the request is processed and the CDR will be generated when the SIP transaction (including all its branches) will be completed;
  • dialog level accounting: the generated CDR covers a whole SIP call; you have to enable it when the initial INVITE is processed and the actual CDR will be generated when the dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
October 10, 2016, at 04:48 PM by 109.99.227.30 -
Changed line 1 from:
Documentation -> Tutorials -> Advanced Accounting
to:
Documentation -> Tutorials -> Call Accounting
Changed lines 5-11 from:

Tutorial Scope

This tutorial will describe the means through which accounting can be made in latest OpenSIPS versions, the types of accounting that can be made(dialogs, missed calls etc.), the level of the accounting(message level, transaction level, dialog level), the available backends(syslog, databases...) and some optional features(extra and leg accounting). Alongside the first half of the tutorial there will be a brief description about all these above mechanisms followed by practical examples which you can read in order to have a better picture about how everything works and what can be the best option for your needs. Most of the features presented in this tutorial are available only since version 2.2, when there's been a major rework affecting the accounting module. There are many great improvements since the previous version which will ultimately help you having an easier jobs understanding and using the module.

to:

Overview

The SIP call accounting is a sensitive and challenging task. Even more, the flexibility and complexity of OpenSIPS escalates the understanding and the correctness of the accounting approaches. This tutorial explains all the elements and notions about accounting, as well as how to take full advantage of the powerful accounting engine provided by OpenSIPS.
Concepts as accounting events (missed calls, failed calls) , the accounting scope (transaction, dialog), accounting backends (database, log, radius) are explained and covered by full script examples. For more complex scenarios, advanced features like extra accounting (extend the CDR format and collect information from the entire call) and multi-leg accounting (multiple CDR records per SIP call) are described and put to work.
Everything in this tutorial is backed up with practical examples which you can run and disect in order to get a better picture about how accouting works and what can be the best option for your needs. Most of the features presented in this tutorial are available in versions starting with OpenSIPS 2.2, when there's been a major rework affecting the accounting module. There are many great improvements since the previous version which will ultimately help you having an easier jobs understanding and using the module.

Added lines 17-23:

Accounting events

OpenSIPS can account different events happening during a transaction/dialog lifetime, such as:

  • successful transactions/dialogs: transaction/call has successfully established from the UAC/caller perspective; it can be only one such event per SIP call;
  • missed calls: a call branch did not established, as the UAS rejected or declined the call attempted ; there can be multiple such events per a single SIP call (due SIP forking). Note that a SIP call that generated a ACC successfully established event may generate some missed call event (for the SIP branches that failed during serial or parallel forking); The missed call events are also known as UAS-side accounting (as they are related to the relation between OpenSIPS and callee/UAS side).
  • failed transaction: generated when a transaction fails (reply code >=300) on the UAC side of OpenSIPS - this is a complementary event for the successfully transaction event.
Deleted lines 38-42:
Accounting events

OpenSIPS can account all the events happening during a transaction/dialog lifetime, that is:

  • successful transactions/dialogs: transaction has ended without any issues;
  • missed calls: accounts a missed call; callee did not answer the call
  • failed transaction: accounts a failed transaction(reply code >=300)
September 26, 2016, at 07:24 PM by ionutionita92 -
Changed lines 183-229 from:
 do_accounting
to:

Sometimes the extra values are not enough. One such scenario is when user A calls to user B, but B doesn't not respond and he's got a redirect to user C. In this case we have two legs, from A to B and from B to C. We may need to account separate information for these legs. In the current scenario caller and callee usernames for both legs will be accounted. There are backends that will generate multiple accounting requests, one for each leg. For example, if using db backend, you will have one line in your table for each leg.

The modparam declaration for leg_fields is very similar to the extra_fields

modparam("acc", "leg_fields", "log: caller; callee")

The same is the case for acc_leg variable. The only difference is that this variable can be indexed using the leg number. No index means the current leg. You can also get the number of the last leg using acc_current_leg variable. New legs can be created with acc_new_leg function.

In the script, everything that concerns lookup function was moved into a route, in order to use it multiple times. For the initial call, we'll get the name of the caller from the From header. The name of the callee is in the R-URI:

      $acc_leg(caller) = $fU;
      $acc_leg(callee) = $rU;

In case our call to B as described upwards fails we'll get to failure route where we will fetch the next destination, as usual. For redirects, we check if the new destination is a local uri, meaning that we have to resolve the same way we did with the first uri, using lookup function. Now the call from B to C starts, so we'll create a new leg. We need to store the name of the caller before calling next_branches() function, because after this call we will lose it:

        $var(old_rU) = $rU;

        next_branches();

If the call is a redirect, we will create a new leg and populate acc_leg accordingly. The name of the calle will be in the URI populated by next_branches() function.

        /* local contact; lookup needed */
        if (uri == myself) {
                acc_new_leg();
                $acc_leg(caller) = $var(old_rU);
                $acc_leg(callee) = $rU;

                route(lookup);

                serialize_branches(1);
        }

For one redirect, we will have two account lines. One for the missed call from A to B

ACC: call missed: timestamp=1474899448;created=1474899444;setuptime=4;method=INVITE;from_tag=1766231375;to_tag=;call_id=604787970;code=408;reason=Request Timeout;caller_domain=10.0.0.135;callee_domain=10.0.0.135;caller=A;callee=B

and the CDR record, with both legs, A to B and B to c:

ACC: call ended: created=1474899444;call_start_time=1474899448;duration=5;ms_duration=4762;setuptime=4;method=INVITE;from_tag=1766231375;to_tag=2826210.0.0.1351;call_id=604787970;code=200;reason=OK;caller_domain=10.0.0.135;callee_domain=10.0.0.135;caller=A;callee=B;caller=B;callee=C

If using db engine two lines will be generated, one with the leg from A to B and one with the leg from B to C. The rest of the information will be the same.

September 26, 2016, at 06:40 PM by ionutionita92 -
Changed lines 169-170 from:

I

to:

As concers the script, all we need to do is to set acc_extra variable. In the current scenario we set the domains

        $acc_extra(caller_domain) = $rd;
        $acc_extra(callee_domain) = $td;

The CDR for the current call will contain the new extra values, as we set them

ACC: call ended: created=1474899444;call_start_time=1474899448;duration=5;ms_duration=4762;setuptime=4;method=INVITE;from_tag=1766231375;to_tag=2826210.0.0.1351;call_id=604787970;code=200;reason=OK;caller_domain=X.X.X.X;callee_domain=X.X.X.X
September 26, 2016, at 06:06 PM by ionutionita92 -
Added lines 157-172:
Extra values accounting
    There are cases when you may need to add some extra values to the default accounted information. Since version 2.3 this engine was modified in order to make it easier for the users to 

provision additional information in their account entries.

     Starting from the previous script, we try to add extra information about the caller's and callee's domains. First of all we need to define the additional data that will be added to our accounted information in the modparam section using the extra_fields parameter
   modparam("acc", "extra_fields", "log: caller_domain; callee_domain")

The following definition would also be valid

   modparam("acc", "extra_fields", "log: caller_domain->callee_domain; callee_domain->callee_domain")

The first part of the declaration is the backend for which the values are declared, in this case the log backend. The following are declarations in form of script-tag->account-tag. The script-tag is the tag used for referencing acc_extra variable, which will hold all our extra values. The scope of the variable depends on the accounting type used. If the cdr flag is used, the variable will be visible for the whole duration of the dialog, else it will be visible as long as the transaction will be visible. The account-tag is how the information will be identified when accounted, that is the tag identifier for log, column name for db or AVP name for aaa. I

Multi-leg accounting
September 23, 2016, at 05:14 PM by ionutionita92 -
Changed line 155 from:

Here, aside from the basic information that is present in every account record we can see the call_start_time, the duration both in seconds and milliseconds.

to:

Here, aside from the basic information that is present in every account record we can see the call_start_time, and the call duration both in seconds and milliseconds.

September 23, 2016, at 05:13 PM by ionutionita92 -
Changed line 145 from:

If do_accounting would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. next_branches() function call will get the next destination for us. If we still have got contacts to call to we arm the failure route again in order to be able to send the message to next destination.

to:

If do_accounting would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. next_branches() function call will get the next destination for us. If we still have contacts to call to we arm the failure route again in order to be able to send the message to next destination.

September 23, 2016, at 05:11 PM by ionutionita92 -
Changed line 112 from:

The last do_accounting call from the default script was changed to

to:

First of all, in order to be able to use the CDR engine, dialog module needs to be loaded

Changed lines 114-115 from:
        # when routing via usrloc, log the missed calls also
        do_accounting("log","cdr|missed");
to:

loadmodule "dialog.so" modparam("dialog", "db_mode, 0)

Changed lines 117-118 from:

which, aside from the missed calls, enables logging the CDRs. Keep in mind that the CDR flag affects only the calls(dialogs). To enable serial forking the following lines were added below do_accounting call.

to:

The last do_accounting call from the default script was changed to

Changed lines 120-121 from:
        serialize_branches(1);
        next_branches();
to:
        # when routing via usrloc, log the missed calls also
        do_accounting("log","cdr|missed");
Changed lines 123-124 from:

In the failure route the following lines were added:

to:

which, aside from the missed calls, enables logging the CDRs. Keep in mind that the CDR flag affects only the calls(dialogs). To enable serial forking the following lines were added below do_accounting call.

Changed lines 126-127 from:
       do_accounting("log","missed");
to:
        serialize_branches(1);
Added lines 128-134:

@]

In the failure route the following lines were added: [@

       do_accounting("log","missed");

        next_branches();
Changed line 151 from:

The reply code and the reason may change depending on the scenario. When the call is established we will receive a basic accounting line confirming this

to:

The reply code and the reason may change depending on the scenario. If at least one of the contacts answered and the call is established, a CDR will be generated after the call ended:

Changed line 153 from:

ACC: transaction answered: timestamp=1474637744;method=INVITE;from_tag=1931529157;to_tag=1195810.0.0.1351;call_id=182969767;code=200;reason=OK

to:

ACC: call ended: created=1474639265;call_start_time=1474639281;duration=5;ms_duration=4250;setuptime=16;method=INVITE;from_tag=1515466979;to_tag=1284910.0.0.1351;call_id=1766189979;code=200;reason=OK

Changed line 155 from:
to:

Here, aside from the basic information that is present in every account record we can see the call_start_time, the duration both in seconds and milliseconds.

September 23, 2016, at 04:57 PM by ionutionita92 -
Changed lines 108-109 from:
CDR accounting with failover support
to:
CDR and serial forking accounting

In this scenario, the default script has be modified, in order to show you how all the missed calls can be accounted when it comes to serial forking. Let's take the case when there is a call for user X but X has multiple contacts, let's call them A, B and C. The order for serial forking should be A, B and C. That is first time we try to call A, if A does not respond B shall be tried and the last try should be made to C. Last, but not least, if the call is to happen(any of A,B or C will respond), CDR will also be accounted. This will happen only for the internally registered users using usrloc module.

The last do_accounting call from the default script was changed to

        # when routing via usrloc, log the missed calls also
        do_accounting("log","cdr|missed");

which, aside from the missed calls, enables logging the CDRs. Keep in mind that the CDR flag affects only the calls(dialogs). To enable serial forking the following lines were added below do_accounting call.

        serialize_branches(1);
        next_branches();

In the failure route the following lines were added:

       do_accounting("log","missed");

        next_branches();
        # if we've got any more branches arm the failure route
        if ($rc != 2) {
                t_on_failure("missed_call");
        }

        if (!t_relay()) {
                send_reply("500","Internal Error");
        };

If do_accounting would not have been called again, in case of failure, only the first missed call would have been accounted. The flag resets each time a missed call is accounted. next_branches() function call will get the next destination for us. If we still have got contacts to call to we arm the failure route again in order to be able to send the message to next destination.

A missed call account event will be generated for each destiantion that did not respond looking like this

ACC: call missed: timestamp=1474637733;method=INVITE;from_tag=1931529157;to_tag=;call_id=182969767;code=408;reason=Request Timeout

The reply code and the reason may change depending on the scenario. When the call is established we will receive a basic accounting line confirming this

ACC: transaction answered: timestamp=1474637744;method=INVITE;from_tag=1931529157;to_tag=1195810.0.0.1351;call_id=182969767;code=200;reason=OK
September 22, 2016, at 03:41 PM by ionutionita92 -
September 22, 2016, at 03:39 PM by ionutionita92 -
Added lines 86-108:

Next in the script we can see the following line

        # account only INVITEs
	if (is_method("INVITE")) {
		do_accounting("log");
	}

As you can see, this function call applies only to INVITE transactions where the request is also an initial request, sequential requests are handled above. Since no flag is specified, only successful transactions will be accounted. Accounted information will look more or less the same as the one for the BYE transaction:

ACC: transaction answered: timestamp=1474540997;method=INVITE;from_tag=U49E.iWKOkX1URnBlpKMD.0hM4rIM2U0;to_tag=1173610.0.0.1351;call_id=vonxx1.d4qh9nfPmFBpu46u7Vvq5c8re;code=200;reason=OK

The last do_accounting usage in the script is related only to calls to registered users

        # when routing via usrloc, log the missed calls also
        do_accounting("log","missed");

For them missed calls accounting is also enabled. Keep in mind that missed call accounting is related only to INVITE transactions, it will have no effect for other types.

CDR accounting with failover support
September 22, 2016, at 01:47 PM by ionutionita92 -
Changed lines 61-90 from:

Next let's explain every section in the script where do_accounting function is used.

to:

Next every section in the script where do_accounting function is used will be explained. First of all, we can see that, for every call the log backend is used, which will mean that all the accounted information will go wherever all the other logs will go, that is the LOCAL0 facility of the syslog service for this configuration. One can change this behaviour by modifying the log_facility parameter in the acc modparam section.

The first time we can see do_accounting function used is on line 127 where the following is used

        if (has_totag()) {
                # sequential requests within a dialog should
                # take the path determined by record-routing
                if (loose_route()) {

                        if (is_method("BYE")) {
                                # do accunting, even if the transaction fails
                                do_accounting("log","failed");
                        }
         ...
        }

This line will account all the BYE transactions, including the failed transactions(reply code >= 300). Here is an example of how the accounted lines should look line in your syslog

ACC: transaction answered: timestamp=1474540760;method=BYE;from_tag=2whdajbp4e-dzLdUwo8-coqaNKKh.oSp;to_tag=11562SIPpTag012;call_id=ezUcDyVPC9jgwtk35eamdhmIo31RSScI;code=400;reason=Reason

Not using the failed flag for do_accounting would have resulted in not having this account line, since the reply code is 400.


 do_accounting
September 22, 2016, at 01:12 PM by ionutionita92 -
Added lines 50-52:

By default OpenSIPS comes with a sample script called opensips.cfg which uses the accounting module. In the following lines every line that involves the module shall be explained.

First of all, the module is loaded using the modparam statement. All the parameters declared here have their default value, so they can be very easily removed.

Added lines 60-62:

Next let's explain every section in the script where do_accounting function is used.

September 22, 2016, at 01:06 PM by ionutionita92 -
Changed line 48 from:
{@opensips.cfg@} sample script
to:
opensips.cfg sample script
September 22, 2016, at 01:05 PM by ionutionita92 -
Changed line 48 from:
opensips.cfg sample script
to:
{@opensips.cfg@} sample script
September 22, 2016, at 01:05 PM by ionutionita92 -
Added lines 46-58:
opensips.cfg sample script
loadmodule "acc.so"
/* what special events should be accounted ? */
modparam("acc", "early_media", 0)
modparam("acc", "report_cancels", 0)
modparam("acc", "detect_direction", 0)
September 21, 2016, at 07:09 PM by ionutionita92 -
Changed lines 34-35 from:
Extending accounting engine
to:
Extending the accounting engine
Added lines 41-46:

Examples

Intro

Starting from default opensips script examples will be given which will help have a better picture about how accounting works in OpenSIPS and how the parameter can be used in real case scenarios.

September 21, 2016, at 06:51 PM by ionutionita92 -
Added lines 20-27:
Accounting backends

When doing accounting, one can choose between a variety of engines to do accounting with or even combine them together:

  • log: the accounting shall be logged wherever you choose to log it, via syslog, either in the same location as the OpenSIPS logs or in any other location you choose; backend
  • db(database): use one of the many database backends currently implemented in OpenSIPS(mysql, postgres, sqlite etc.);
  • aaa: account your data using an aaa protocol(currently only radius is available);
  • evi: information shall be accounted using the event interface;
Changed lines 39-40 from:

IMPORTANT: In order to uses these features, some settings need to be made. That is, if you will use the database engine, the default accounting table will have to be changed. Also for aaa accounting, if using AVPs that are not defined, they will have to be defined in the dictionary.

to:


IMPORTANT: In order to uses these features, some settings need to be made. That is, if you will use the database engine, the default accounting table will have to be changed. Also for aaa accounting, if using AVPs that are not defined, they will have to be defined in the dictionary.

September 21, 2016, at 06:42 PM by ionutionita92 -
Changed line 32 from:

''IMPORTANT': In order to uses these features, some settings need to be made. That is, if you will use the database engine, the default accounting table will have to be changed. Also for aaa accounting, if using AVPs that are not defined, they will have to be defined in the dictionary.

to:

IMPORTANT: In order to uses these features, some settings need to be made. That is, if you will use the database engine, the default accounting table will have to be changed. Also for aaa accounting, if using AVPs that are not defined, they will have to be defined in the dictionary.

September 21, 2016, at 06:42 PM by ionutionita92 -
Changed lines 23-32 from:
  • missed calls: a called t
to:
  • missed calls: accounts a missed call; callee did not answer the call
  • failed transaction: accounts a failed transaction(reply code >=300)
Extending accounting engine

There might be cases when extra information, other than what's already accounted, might be needed. For this we've got:

  • extra_fields: you can define new fields for the accounting engine which shall be populated at the time when the accounting is being made; there is a special variable defined for this mechanism called acc_extra which can be populated with whatever you want; the acc_extra variable is persistent as concerns messages, transactions and dialogs, depending of the type of transaction used;
  • leg_fields: almost the same as the extra data, but this time one can set multiple legs for a call, which will result in multiple accounting requests; this shall be useful when logically, there are multiple calls, that is A calls to B and B redirects the call to C, meaning that there are two legs for this call: A to B and B to C. It is the script writer's job to decide whether a new leg has been created using acc_new_leg script function. The variable used to define extra leg fields is acc_leg;

''IMPORTANT': In order to uses these features, some settings need to be made. That is, if you will use the database engine, the default accounting table will have to be changed. Also for aaa accounting, if using AVPs that are not defined, they will have to be defined in the dictionary.

September 21, 2016, at 05:51 PM by ionutionita92 -
Changed lines 12-15 from:

Accounting scope

to:

Accounting concepts

Accounting scope

Depending on the type of the accounting, there are multiple possibilities as concerns the scope:

  • message level accounting: this is mostly used when the reply is internally generated, OpenSIPS being the endpoint for a certain transaction; accounting is being made on the spot and this can be achieved using one of the following acc_log_request, acc_db_request, acc_aaa_request or acc_evi_request depending on the backend used;
  • transaction level accounting: that is when OpenSIPS is a proxy forwarding requests and replies; this transaction shall be accounted only at the moment when the reply came.
  • dialog level accounting: this type of accounting shall be used for accounting CDRs; you have to enable it when the initial INVITE have been received and the actual accounting shall be made when the dialog ends(that is when all the messages belonging to a dialog have been processed, including the replies for BYE messages);
Accounting events

OpenSIPS can account all the events happening during a transaction/dialog lifetime, that is:

  • successful transactions/dialogs: transaction has ended without any issues;
  • missed calls: a called t
September 21, 2016, at 04:50 PM by ionutionita92 -
Changed lines 7-14 from:

This tutorial will describe the means through which accounting can be made in latest OpenSIPS versions, the types of accounting that can be made(dialogs, missed calls etc.), the level of the accounting(message level, transaction level, dialog level), the available backends(syslog, databases...) and some optional features(extra and leg accounting). In the first part of the tutorial there will be a brief description about all these above mechanisms followed by practical examples which you can read in order to have a better picture about how everything works and what can be the best option for your current project.

to:

This tutorial will describe the means through which accounting can be made in latest OpenSIPS versions, the types of accounting that can be made(dialogs, missed calls etc.), the level of the accounting(message level, transaction level, dialog level), the available backends(syslog, databases...) and some optional features(extra and leg accounting). Alongside the first half of the tutorial there will be a brief description about all these above mechanisms followed by practical examples which you can read in order to have a better picture about how everything works and what can be the best option for your needs. Most of the features presented in this tutorial are available only since version 2.2, when there's been a major rework affecting the accounting module. There are many great improvements since the previous version which will ultimately help you having an easier jobs understanding and using the module.

Accounting scope

September 21, 2016, at 04:25 PM by ionutionita92 -
Changed lines 3-14 from:

(:toc-float Table of Content:)

to:

(:toc-float Table of Content:)

Tutorial Scope

This tutorial will describe the means through which accounting can be made in latest OpenSIPS versions, the types of accounting that can be made(dialogs, missed calls etc.), the level of the accounting(message level, transaction level, dialog level), the available backends(syslog, databases...) and some optional features(extra and leg accounting). In the first part of the tutorial there will be a brief description about all these above mechanisms followed by practical examples which you can read in order to have a better picture about how everything works and what can be the best option for your current project.

September 21, 2016, at 12:57 PM by ionutionita92 -
Added lines 1-3:
Documentation -> Tutorials -> Advanced Accounting

This page has been visited 21721 times. (:toc-float Table of Content:)


Page last modified on November 03, 2016, at 04:50 PM