<!-- Module User's Guide -->

<chapter>

	<title>&adminguide;</title>

	<section id="overview" xreflabel="Overview">
	<title>Overview</title>
	<para>
		Offer a possibility to store incoming/outgoing SIP messages in database.
		Since version 2.2, proto_hep module needs to be loaded in order to duplicate
		with hep. All hep parameters moved inside proto_hep.
	</para>
	<para>
		The 2.2 version of &osips; came with a major improvement in tracer module.
		Now all you have to do is call <emphasis>trace()</emphasis> function
		with the proper parameters and it will do the job for you. Now you can trace
		messages, transactions and dialogs with the same function. Also, you can trace
		to multiple databases, multiple hep destinations and sip destinations using
		only one parameter. All you need now is defining <emphasis>trace_id</emphasis>
		parameters in modparam section and switch between them in
		tracer function. Also you cand turn tracing  on
		and off using <emphasis>trace_on</emphasis> either globally(for all trace_ids)
		or for a certain trace_id.
	</para>

	<para>
		IMPORTANT: In 2.2 version support for stateless trace has been removed.
	</para>

	<para>
	The tracing tracing can be turned on/off using fifo command.
	</para>
	<para>
	opensips-cli -x mi trace on
	opensips-cli -x mi trace [some_trace_id] on
	</para>
	<para>
	opensips-cli -x mi trace off
	opensips-cli -x mi trace [some_trace_id] off
	</para>

	<para>
		Starting with &osips; 3.0 you can use the <emphasis>trace_start</emphasis> to
		create dynamic dynamic tracing destinations based on some custom filters.
	</para>
	</section>
	<section id="dependencies" xreflabel="Dependencies">
	<title>Dependencies</title>
	<section>
		<title>&osips; Modules</title>
		<para>
		The following modules must be loaded before this module:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>database module</emphasis> - mysql, postrgress,
				dbtext, unixodbc... only if you are using a database type
				trace id
			</para>
			</listitem>
			<listitem>
			<para>
				<emphasis>b2b_logic</emphasis> - only if you want to trace
				B2B sessions.
			</para>
			</listitem>
			<listitem>
			<para>
				<emphasis>dialog</emphasis> - only if you want to trace
				SIP dialogs (INVITE based).
			</para>
			</listitem>
			<listitem>
			<para>
				<emphasis>tm</emphasis> - only if you want to trace 
				SIP transactions.
			</para>
			</listitem>
			<listitem>
			<para>
				<emphasis>proto_hep</emphasis> - only if you want to 
				trace / replicate messages over HEP protocol.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>
	<section>
		<title>External Libraries or Applications</title>
		<para>
		The following libraries or applications must be installed before running
		&osips; with this module loaded:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>None</emphasis>.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>
	</section>
	<section id="exported_parameters" xreflabel="Exported Parameters">
	<title>Exported Parameters</title>
		<section id="param_trace_on" xreflabel="trace_on">
		<title><varname>trace_on</varname> (integer)</title>
		<para>
		Parameter to enable/disable trace (on(1)/off(0))
		</para>
		<para>
		<emphasis>
			Default value is "1"(enabled).
		</emphasis>
		</para>
		<example>
		<title>Set <varname>trace_on</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("tracer", "trace_on", 1)
...
</programlisting>
		</example>
	</section>

	<section id="param_trace_local_ip" xreflabel="trace_local_ip">
		<title><varname>trace_local_ip</varname> (str)</title>
		<para>
			The address to be used in the fields that specify the source address
		(protocol, ip and port) for locally generated messages. If not set,
		the module sets it to the address of the socket that will be used to send
		the message. Protocol and/or port are optional and if omitted will take
		the default values: udp and 5060.
		</para>
		<para>
		<emphasis>
			Default value is "NULL".
		</emphasis>
		</para>
		<example>
		<title>Set <varname>trace_local_ip</varname> parameter</title>
		<programlisting format="linespecific">
...
#Resulting address: udp:10.1.1.1:5064
modparam("tracer", "trace_local_ip", "10.1.1.1:5064")
...

...
#Resulting address: tcp:10.1.1.1:5060
modparam("tracer, "trace_local_ip", "tcp:10.1.1.1")
...

...
#Resulting address: tcp:10.1.1.1:5064
modparam("tracer", "trace_local_ip", "tcp:10.1.1.1:5064")
...

...
#Resulting address: udp:10.1.1.1:5060
modparam("tracer", "trace_local_ip", "10.1.1.1")
...
</programlisting>
		</example>
	</section>

	<section id="param_trace_id" xreflabel="trace_id">
		<title><varname>trace_id</varname> (str)</title>
		<para>
			Specify a destination for the trace. This can be a hep id defined
			in proto_hep, a sip uri, a file, a syslog facility or a database
			url and a table. All parameters inside
			<emphasis>trace_id</emphasis> must be separated by
			<emphasis>;</emphasis>, excepting the last one. The parameters
			are given in key-value format, the possible keys being
			<emphasis>uri</emphasis> for HEP and SIP IDs and
			<emphasis>uri</emphasis> and <emphasis>table</emphasis>
			for databases. The format is
			<emphasis>[id_name]key1=value1;key2=value2;</emphasis>. HEP
			id's <emphasis role="bold">MUST</emphasis> be defined in proto_hep in order
			to be able to use them here.
		</para>
		<para>
			When the uri is a <emphasis>file</emphasis>, the path to the file has
			to be specified after the colon. The output is always appended if the file
			exists, or created if it doesn't, using <xref linkend="param_file_mode"/>
			permissions.
		</para>
		<para>
			When the uri is <emphasis>syslog</emphasis>, it has to follow the following
			format: <emphasis>syslog[:FACILITY[:LEVEL]]</emphasis>. The default
			facility and levels are the ones used by &osips;
			(<emphasis>syslog_facility</emphasis> and <emphasis>log_level</emphasis>).
			These can be tuned using
			<xref linkend="param_syslog_default_facility"/> and
			<xref linkend="param_syslog_default_level"/> parameters.
		</para>
		<para>
			One can declare multiple types of tracing under the same trace
			id, being identified by their name. So if you define two
			database url, one hep uri and one sip uri with the same name,
			when calling trace() with this name tracing shall be done
			to all the destinations.
		</para>
		<para>
			All the old parameter such as db_url, table and duplicate_uri
			will form the trace id with the name "default".
		</para>
		<para>
		<emphasis>
			No default value. If not set the module will be useless.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>trace_id</varname> parameter</title>
		<programlisting format="linespecific">
...
/*DB trace id*/
modparam("tracer", "trace_id",
"[tid]
uri=mysql://xxxx:xxxx@10.10.10.10/opensips;
table=new_sip_trace;")
/* hep trace id with the hep id defined in proto_hep; check proto_hep docs
 * for more information */
modparam("proto_hep", "hep_id",  "[hid]10.10.10.10")
modparam("tracer", "trace_id", "[tid]uri=hep:hid")
/*sip trace id*/
modparam("tracer", "trace_id",
"[tid]uri=sip:10.10.10.11:5060")
/* notice that they all have the same name
 * meaning that calling trace("tid",...)
 * will do sql, sip and hep tracing */
/*file trace id*/
modparam("tracer", "trace_id",
"[tid]uri=file:/path/to/file")
/*syslog trace id at error (level -1)*/
modparam("tracer", "trace_id",
"[tid]uri=syslog:local0:-1")
...
</programlisting>
		</example>
	</section>
		<section id="param_syslog_default_facility" xreflabel="syslog_default_facility">
		<title><varname>syslog_default_facility</varname> (string)</title>
		<para>
			When <emphasis>syslog</emphasis> tracing is used, this parameter specifies
			the log facility to write traces to.
		</para>
		<para>
		<emphasis>
			Default value is the value of <emphasis>syslog_facility</emphasis>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>syslog_default_facility</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("tracer", "syslog_default_facility", "LOG_DAEMON")
...
</programlisting>
		</example>
	</section>
		<section id="param_syslog_default_level" xreflabel="syslog_default_level">
		<title><varname>syslog_default_level</varname> (integer)</title>
		<para>
			When <emphasis>syslog</emphasis> tracing is used, this parameter specifies
			the level to write traces to.
		</para>
		<para>
		<emphasis>
			Default value is the value of <emphasis>log_level</emphasis>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>syslog_default_level</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("tracer", "syslog_default_level", 2) # NOTICE
...
</programlisting>
		</example>
	</section>
		<section id="param_file_mode" xreflabel="file_mode">
		<title><varname>file_mode</varname> (integer)</title>
		<para>
			When <emphasis>file</emphasis> tracing is used, this parameter
			specifies the permissions to be used to create the trace files.
			It follows the UNIX conventions.
		</para>
		<para>
		<emphasis>
			Default value is <emphasis>0600 (rw-------)</emphasis>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>file_mode</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("tracer", "file_mode", 0644)
...
</programlisting>
		</example>
	</section>

	</section>

	<section id="exported_functions" xreflabel="exported_functions">
	<title>Exported Functions</title>
	<section id="func_trace" xreflabel="trace()">
		<title>
		<function moreinfo="none">trace(trace_id, [scope], [type], [trace_attrs], [flags], [correlation_id])</function>
		</title>
		<para>This function has replaced the <emphasis>sip_trace()</emphasis> in &osips; 3.0.</para>
		<para>
			Store or replicate current processed SIP message, transaction / dialog or B2B session.
			It is stored in the form prior applying chages made to it. The traced_user_avp
			parameter is now an argument to trace() function. Since version 2.2, this function
			also catches internally generated replies in stateless mode(sl_send_reply(...)).
		</para>
		<para>
		This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE.
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>trace_id (string)</emphasis>
			the name of the <emphasis>trace_id</emphasis> specifying where to do
			the tracing.
			</para>
		</listitem>
		<listitem>
		<para><emphasis>scope (string, optional)</emphasis> what do you 
		want to trace: dialog, transaction, B2B session or only the message. 
		If not specified, will try the topmost trace that can be done: 
		if dialog module loaded will trace dialogs, else if tm module loaded
		will trace transaction and if none of these loaded will trace messages.
		</para>
			<para>Types can be the following:</para>
			<itemizedlist>
			<listitem>
				<para><emphasis>'m'/'M'</emphasis> trace messages. Is the only
				one you should use in stateless mode.</para>
			</listitem>
			<listitem>
				<para><emphasis>'t'/'T'</emphasis> trace transactions. If tm
					module not loaded, it will be in stateless transaction aware
					mode meaning that will catch selected requests both in and out
				and internally generated replies.</para>
			</listitem>
			<listitem>
				<para><emphasis>'d'/'D'</emphasis> trace dialog</para>
			</listitem>
			<listitem>
				<para><emphasis>'b'/'B'</emphasis> trace all the traffic
				related to the B2B session to be later created</para>
			</listitem>
			</itemizedlist>
		</listitem>
		<listitem>
			<para><emphasis>type (string, optional)</emphasis> list of types of messages to
			be traced by this function; if not set only sip messages shall be traced;
			if the parameter is set, but <emphasis>sip</emphasis> is not specified,
			<emphasis>sip</emphasis> shall not be traced;
			all the parameters from the list shall be separated by '|'</para>
			<para>Current possible types to be traced are the following:</para>
			<itemizedlist>
				<listitem>
					<para><emphasis>sip</emphasis> - enable sip messages 
					tracing;</para>
				</listitem>
				<listitem>
					<para><emphasis>xlog</emphasis> - enable xlog messages 
					tracing in current scope(dialog, transaction, B2B session
					or message);</para>
				</listitem>
				<listitem>
					<para><emphasis>rest</emphasis> - enable rest messages 
					tracing;</para>
				</listitem>
			</itemizedlist>
		</listitem>
		<listitem>
			<para><emphasis>trace_attrs (string, optional)</emphasis> this parameter
			replaces the traced_user_avp from the old version. To avoid duplicating
			an entry only for this parameter, whatever you put here(string/pvar)
			shall be stored in the trace_attrs column in the sip_trace table.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>flags (string,pvar)</emphasis> are some control
			flags over the tracing process (how and what to be traced).
			</para>
			<itemizedlist>
				<listitem>
					<para><emphasis>C</emphasis> - trace only the SIP caller side;</para>
				</listitem>
				<listitem>
					<para><emphasis>c</emphasis> - trace onlt the SIP callee side;</para>
				</listitem>
			</itemizedlist>
			<para>If both <emphasis>C</emphasis> and <emphasis>c</emphasis> flags are missing, tracing of both sides/legs is assumed.</para>
			<para>NOTE these flags are supported only by transactional and dialog tracing</para>
		</listitem>

		<listitem>
			<para><emphasis>correlation_id (string,pvar)</emphasis> a custom
			SIP correlation ID to be forced (normally the SIP Call-ID is used)
			to correlate this traffic (transaction, dialog) with other traffic.
			</para>
		</listitem>

		</itemizedlist>
		<example>
		<title><function>trace()</function> usage</title>
		<programlisting format="linespecific">
...
/* see declaration of tid in trace_id section */
	$var(trace_id) = "tid";
	$var(user) = "osip_user@opensips.org";

...
/* Example 1: how to trace a dialog sip and xlog */
	if (has_totag()) {
		match_dialog();
	} else {
		if (is_method("INVITE") {
			trace($var(trace_id), "d", "sip|xlog", $var(user));
		}
	}
...
/* Example 2: how to trace initial INVITE and BYE, sip and rest */
	if (has_totag()) {
		if (is_method("BYE")) {
			trace($var(trace_id), "m", "sip|rest", $var(user));
		}
	} else {
		if (is_method("INVITE")) {
			trace($var(trace_id), "m", "sip|rest", $var(user));
		}
	}

...
/* Example 3: trace initial INVITE transaction's only xlog and rest, no sip */
	if (!has_totag()) {
		if (is_method("INVITE")) {
			trace($var(trace_id), "t", "xlog|rest", $var(user));
		}
	}
...
/* Example 4: stateless transaction aware mode!*/
/* tm module must not be loaded */
	if (is_method("REGISTER")) {
		trace($var(trace_id), "t", "xlog|rest", $var(user));
		if (!www_authorize("", "subscriber")) {
			/* tracer will also catch the 401 generated by www_challenge() */
			www_challenge("", "auth");
		}
	}
</programlisting>
		</example>
	</section>
	</section>

   <section id="exported_mi_functions" xreflabel="Exported MI Functions">
	<title>Exported MI Functions</title>
	<section id="mi_trace" xreflabel="trace">
		<title>
		<function moreinfo="none">trace</function>
		</title>
		<para>
			Enable/disable tracing(globally or for a specific trace id) or dump
			info about trace ids. This command requires named parameters
			(each parameter is ginven in the format param_name=param_value).
		</para>
		<para>
			Name: <emphasis>trace</emphasis>
		</para>
		<para>
			Parameters:
		</para>
		<itemizedlist>
		<listitem>
			<para>
				<emphasis>id</emphasis> (optional) - the name of the tracing instance.
				If this parameter is missing the command will
				either dump info for all tace ids(and return the global tracing state)
				or set the global tracing state.
			</para>
		</listitem>
		<listitem>
			<para>
				<emphasis>mode</emphasis> (optional) - 
				possible values are:
			</para>
			<itemizedlist>
				<listitem><para> "on" - enable tracing </para></listitem>
				<listitem><para> "off" - disable tracing </para></listitem>
			</itemizedlist>
			<para>
				If the first parameter is missing, the command wil set the global
				tracing state, otherwise it will set the state for a specific trace id.
				If you turn global trace on but some of the trace ids had tracing set to
				off, then they shall not do tracing. If you want to turn the tracing on
				for all trace ids you will have to set it separately for each of them.
			</para>
			<para>
				If this parameter is missing but the first is set, the command will
				only dump info about that specific trace id. If both parameters are
				missing, the command will return the global tracing state and dump
				info for each id.
			</para>
		</listitem>
		</itemizedlist>

		<para>
		MI FIFO Command Format:
		</para>
		<programlisting  format="linespecific">
# Display global tracing mode and all trace destinations:
opensips-cli -x mi trace
# Turn off global tracing:
opensips-cli -x mi trace mode=off
# Turn on tracing for destination id tid2:
opensips-cli -x mi trace id=tid2 mode=on
		</programlisting>
	</section>

	<section id="mi_trace_start" xreflabel="trace">
		<title>
		<function moreinfo="none">trace_start</function>
		</title>
		<para>
			Creates a dynamic tracing destination based using custom filters.
			This function can be used to debug calls for certain destinations
			real-time.
		</para>
		<para>
			Dynamic destinations are not restart persistent!
		</para>
		<para>
			Name: <emphasis>trace_start</emphasis>
		</para>
		<para>
			Parameters:
		</para>
		<itemizedlist>
		<listitem>
			<para>
				<emphasis>id</emphasis> - the name of the tracing instance.
			</para>
		</listitem>
		<listitem>
			<para>
				<emphasis>uri</emphasis> - the destination uri for this instance.
			</para>
		</listitem>
		<listitem>
			<para>
				<emphasis>filter</emphasis> (optional) - used to filter the traffic
				received by the sender. This parameter should be an array that can
				contain multiple filters in the <emphasis>condition=value</emphasis>
				format.
				Possible values for the <emphasis>condition</emphasis> argument are:
			</para>
			<itemizedlist>
				<listitem><para>caller</para> - filter based on the caller (From username)</listitem>
				<listitem><para>callee</para> - filter based on the callee (R-URI username)</listitem>
				<listitem><para>ip</para> - filter based on the source IP of the message</listitem>
			</itemizedlist>
			<para>
				The <emphasis>condition</emphasis> parameter can consist of multiple different filters.
				In order to satisfy the overall condition and send traffic to the desired destination,
				all conditions have to be satisfied.
			</para>
			<para>
				If this parameter is missing all traffic is forwarded to the destination.
			</para>
			<para>
				The filter is applied for any incoming request
			</para>
		</listitem>
		<listitem>
			<para>
				<emphasis>scope</emphasis> - the scope to engage the tracing for.
				The format received by this parameter is similar to the one
				received by the <emphasis>trace()</emphasis> function.
			</para>
		</listitem>
		<listitem>
			<para>
				<emphasis>type</emphasis> - the type of messages you want to receive.
				The format received by this parameter is similar to the one
				received by the <emphasis>trace()</emphasis> function.
			</para>
		</listitem>
		</itemizedlist>

		<para>
		MI FIFO Command to start tracing calls from IP 127.0.0.1 to HEP destination 10.0.0.1:9060:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi trace_start id=ip_filter uri=hep:10.0.0.1:9060 filter=ip=127.0.0.1
		</programlisting>

		<para>
		MI FIFO Command to start tracing calls from user Alice to user Bob:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi trace_start id=alice_bob uri=hep:10.0.0.1:9060 filter=caller=Alice filter=caller=Bob
		</programlisting>
	</section>

	<section id="mi_trace_stop" xreflabel="trace">
		<title>
		<function moreinfo="none">trace_stop</function>
		</title>
		<para>
			Stops &osips; from sending traffic to a dynamic trace id created
			using the <emphasis>trace_start</emphasis> command.
		</para>
		<para>
			Name: <emphasis>trace_stop</emphasis>
		</para>
		<para>
			Parameters:
		</para>
		<itemizedlist>
		<listitem>
			<para>
				<emphasis>id</emphasis> - the name of the tracing instance to be stopped.
			</para>
		</listitem>
		</itemizedlist>

		<para>
		MI FIFO Command to stop tracing calls from user Alice to user Bob:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi trace_stop alice_bob
		</programlisting>
	</section>


	</section>

	<section>
		<title>Database setup</title>
		<para>
			Before running &osips; with tracer, you have to setup the database
			tables where the module will store the data. For that, if the
			table were not created by the installation script or you choose
			to install everything by yourself you can use the tracer-create.sql
			<acronym>SQL</acronym> script in the database directories in the
			opensips/scripts folder as template.
			You can also find the complete database documentation on the
			project webpage, &osipsdbdocslink;.
		</para>
	</section>

	<section>
		<title>Known issues</title>
		<para>
			ACKs related to a transaction that are leaving &osips; are not
			traced since they are handled statelessly using forward_request function.
			Fixing it would mean to register a fwdcb callback that would be called
			for all the messages but would be used only by ACKs, which would be
			highly ineffective.
		</para>
	</section>

</chapter>

