Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 613

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css">
<title>Erlang -- Advanced examples</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/et-1.4.4.2.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>Event Tracer (ET)</strong><br><strong>User's Guide</strong><br><small>Version 1.4.4.2</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../../../../doc/js/flipmenu">
<li id="no" title="Introduction" expanded="false">Introduction<ul>
<li><a href="et_intro.html">
              Top of chapter
            </a></li>
<li title="Scope and Purpose"><a href="et_intro.html#id64170">Scope and Purpose</a></li>
<li title="Prerequisites"><a href="et_intro.html#id61234">Prerequisites</a></li>
<li title="About This Manual"><a href="et_intro.html#id61059">About This Manual</a></li>
<li title="Where to Find More Information"><a href="et_intro.html#id60052">Where to Find More Information</a></li>
</ul>
</li>
<li id="no" title="Tutorial" expanded="false">Tutorial<ul>
<li><a href="et_tutorial.html">
              Top of chapter
            </a></li>
<li title="Visualizing Message Sequence Charts"><a href="et_tutorial.html#id60778">Visualizing Message Sequence Charts</a></li>
<li title="Four Modules"><a href="et_tutorial.html#id57439">Four Modules</a></li>
<li title="The Event Tracer Interface"><a href="et_tutorial.html#id61823">The Event Tracer Interface</a></li>
<li title="The Collector and Viewer"><a href="et_tutorial.html#id56971">The Collector and Viewer</a></li>
<li title="The Selector"><a href="et_tutorial.html#id58113">The Selector</a></li>
<li title="How To Put It Together"><a href="et_tutorial.html#id62590">How To Put It Together</a></li>
</ul>
</li>
<li id="no" title="Description" expanded="false">Description<ul>
<li><a href="et_desc.html">
              Top of chapter
            </a></li>
<li title="Overview"><a href="et_desc.html#id62437">Overview</a></li>
<li title="Filters and dictionary"><a href="et_desc.html#id63954">Filters and dictionary</a></li>
<li title="Trace clients"><a href="et_desc.html#id63394">Trace clients</a></li>
<li title="Global tracing"><a href="et_desc.html#id63541">Global tracing</a></li>
<li title="Viewer window"><a href="et_desc.html#id63682">Viewer window</a></li>
<li title="Configuration"><a href="et_desc.html#id65519">Configuration</a></li>
<li title="Contents viewer window"><a href="et_desc.html#id65550">Contents viewer window</a></li>
</ul>
</li>
<li id="loadscrollpos" title="Advanced examples" expanded="true">Advanced examples<ul>
<li><a href="et_examples.html">
              Top of chapter
            </a></li>
<li title="A simulated Mnesia transaction"><a href="et_examples.html#id65821">A simulated Mnesia transaction</a></li>
<li title="Some convenient functions used in the Mnesia transaction
    example"><a href="et_examples.html#id65930">Some convenient functions used in the Mnesia transaction
    example</a></li>
<li title="Erlang trace of a real Mnesia transaction"><a href="et_examples.html#id66086">Erlang trace of a real Mnesia transaction</a></li>
<li title="Erlang trace of Megaco startup"><a href="et_examples.html#id66211">Erlang trace of Megaco startup</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>4 Advanced examples</h1>
  

  <h3><a name="id65821">4.1 
        A simulated Mnesia transaction</a></h3>
    
    <p>The Erlang code for running the simulated <span class="code">Mnesia</span> transaction
    example in the previous chapter is included in the
    <span class="code">et/examples/et_demo.erl</span> file:</p>

    <p></p>

<div class="example"><pre>

sim_trans() -&gt;
    sim_trans([]).

sim_trans(ExtraOptions) -&gt;
    Options = [{dict_insert, {filter, mgr_actors}, fun mgr_actors/1}],
    {ok, Viewer} = et_viewer:start_link(Options ++ ExtraOptions),
    Collector = et_viewer:get_collector_pid(Viewer),
    et_collector:report_event(Collector, 60, my_shell, mnesia_tm, start_outer, 
                              "Start outer transaction"),
    et_collector:report_event(Collector, 40, mnesia_tm, my_shell, new_tid, 
                              "New transaction id is 4711"),
    et_collector:report_event(Collector, 20, my_shell, mnesia_locker, try_write_lock, 
                              "Acquire write lock for {my_tab, key}"),
    et_collector:report_event(Collector, 10, mnesia_locker, my_shell, granted,
                              "You got the write lock for {my_tab, key}"),
    et_collector:report_event(Collector, 60, my_shell, do_commit,
                              "Perform  transaction commit"),
    et_collector:report_event(Collector, 40, my_shell, mnesia_locker, release_tid,
                              "Release all locks for transaction 4711"),
    et_collector:report_event(Collector, 60, my_shell, mnesia_tm, delete_transaction,
                              "End of outer transaction"),
    et_collector:report_event(Collector, 20, my_shell, end_outer,
                              "Transaction returned {atomic, ok}"),
    {collector, Collector}.
</pre></div>
    <p></p>

<div class="example"><pre>

mgr_actors(E) when is_record(E, event) -&gt;
    Actor = fun(A) -&gt;
               case A of
                   mnesia_tm     -&gt; trans_mgr;
                   mnesia_locker -&gt; lock_mgr;
                   _             -&gt; A
               end
            end,
    {true, E#event{from = Actor(E#event.from),
                   to = Actor(E#event.to),
                   contents = [{orig_from, E#event.from},
                               {orig_to,   E#event.to},
                               {orig_contents, E#event.contents}]}}.</pre></div>
    <p>If you invoke the <span class="code">et_demo:sim_trans()</span> function, a
    <span class="code">Viewer</span> window will pop up and the sequence trace will be
    almost the same as if the following <span class="code">Mnesia</span> transaction
    would have been run:</p>

    <p></p>

    <div class="example"><pre>
         mnesia:transaction(fun() -&gt; mnesia:write({my_tab, key, val}) end).</pre></div>

    <p>And the viewer window will look like:</p>

    <p></p>

    <div class="example"><pre>
         Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4]
                                    [async-threads:0] [kernel-poll:false]

         Eshell V5.7.4  (abort with ^G)
         1&gt; {ok, Viewer} = et_viewer:start([]).
         {ok,&lt;0.40.0&gt;;}
         2&gt; et_demo:sim_trans().
         {ok,{table_handle,&lt;0.45.0&gt;,24596,trace_ts,
              #Fun&lt;et_collector.0.62831470&gt;}}</pre></div>

    <p></p>

    <img alt="IMAGE MISSING" src="sim_trans.png"><br>
      <em>Figure
        4.1:
         
        A simulated <span class="code">Mnesia</span> transaction which writes one
      record</em>
    

  

  <h3><a name="id65930">4.2 
        Some convenient functions used in the Mnesia transaction
    example</a></h3>
    

    <p>The <span class="code">module_as_actor</span> filter converts the <span class="code">Event
    Records</span> so the module names becomes actors and the invoked
    functions becomes labels. If the information about who the caller
    was it will be displayed as an arrow directed from the caller to
    the callee. The <span class="code">[{message, {caller}}, {return_trace}]</span>
    options to <span class="code">dbg:tpl/2</span> function will imply the necessary
    information in the Erlang traces.  Here follows the
    <span class="code">module_as_actor</span> filter:</p>


    <p></p>

<div class="example"><pre>

module_as_actor(E) when is_record(E, event) -&gt;
    case lists:keysearch(mfa, 1, E#event.contents) of
        {value, {mfa, {M, F, _A}}} -&gt;
            case lists:keysearch(pam_result, 1, E#event.contents) of
                {value, {pam_result, {M2, _F2, _A2}}} -&gt;
                    {true, E#event{label = F, from = M2, to = M}};
                _ -&gt;
                    {true, E#event{label = F, from = M, to = M}}
            end;
        _ -&gt;
            false
    end.</pre></div>
    <p>The <span class="code">plain_process_info</span> filter does not alter the
    <span class="code">Event Records</span>.  It merely ensures that the event not
    related to processes are skipped:</p>

    <p></p>

<div class="example"><pre>

plain_process_info(E) when is_record(E, event) -&gt;
    case E#event.label of
        send                          -&gt; true;
        send_to_non_existing_process  -&gt; true;
        'receive'                     -&gt; true;
        spawn                         -&gt; true;
        exit                          -&gt; true;
        link                          -&gt; true;
        unlink                        -&gt; true;
        getting_linked                -&gt; true;
        {seq_send, _Label}            -&gt; true;
        {seq_receive, _Label}         -&gt; true;
        {seq_print, _Label}           -&gt; true;
        {drop, _N}                    -&gt; true;
        _                             -&gt; false
    end.</pre></div>
    <p>The <span class="code">plain_process_info_nolink</span> filter does not alter the
    <span class="code">Event Records</span>. It do makes use of the
    <span class="code">plain_process_info</span> , but do also ensure that the process
    info related to linking and unlinking is skipped:</p>

    <p></p>

<div class="example"><pre>

plain_process_info_nolink(E) when is_record(E, event) -&gt;
    (E#event.label /= link) and
    (E#event.label /= unlink) and
    (E#event.label /= getting_linked) and
    plain_process_info(E). </pre></div>
    <p>In order to simplify the startup of an <span class="code">et_viewer</span> process
    with the filters mentioned above, plus some others (that also are
    found in <span class="code">et/examples/et_demo.erl</span> src/et_collector.erl the
    <span class="code">et_demo:start/0,1</span> functions can be used:</p>

    <p></p>

<div class="example"><pre>

start() -&gt;
    start([]).

start(ExtraOptions) -&gt;
    Options = [{trace_global, true},
               {parent_pid, undefined},
               {max_actors, infinity},
               {max_events, 1000},
               {active_filter, module_as_actor}],
    et_viewer:start_link(filters() ++ Options ++ ExtraOptions).</pre></div>
    <p>A simple one-liner starts the tool:</p>

    <div class="example"><pre>
          erl -pa ../examples -s et_demo</pre></div>

    <p>The filters are included by the following parameters:</p>

    <p></p>

<div class="example"><pre>

filters() -&gt;
    [{dict_insert, {filter, module_as_actor},
                   fun module_as_actor/1},
     {dict_insert, {filter, plain_process_info},
                   fun plain_process_info/1},
     {dict_insert, {filter, plain_process_info_nolink},
                   fun plain_process_info_nolink/1},
     {dict_insert, {filter, named_process_info},
                   fun named_process_info/1},
     {dict_insert, {filter, named_process_info_nolink},
                   fun named_process_info_nolink/1},
     {dict_insert, {filter, node_process_info},
                   fun node_process_info/1},
     {dict_insert, {filter, node_process_info_nolink},
                   fun node_process_info_nolink/1},
     {dict_insert, {filter, application_as_actor},
                   fun application_as_actor/1}
    ].</pre></div>
  

  <h3><a name="id66086">4.3 
        Erlang trace of a real Mnesia transaction</a></h3>
    

    <p>The following piece of code <span class="code">et_demo:trace_mnesia/0</span>
    activates call tracing of both local and external function calls
    for all modules in the <span class="code">Mnesia</span> application. The call traces
    are configured cover all processes (both existing and those that
    are spawned in the future) and include timestamps for trace
    data. It do also activate tracing of process related events for
    <span class="code">Mnesia</span>'s static processes plus the calling process (that is
    your shell). Please, observe that the <span class="code">whereis/1</span> call in the
    following code requires that both the traced <span class="code">Mnesia</span>
    application and the <span class="code">et_viewer</span> is running on the same
    node:</p>

    <p></p>

<div class="example"><pre>

trace_mnesia() -&gt;
    Modules = mnesia:ms(),
    Spec = [{message, {caller}}, {return_trace}],
    Flags = [send, 'receive', procs, timestamp],
    dbg:p(all, [call, timestamp]),
    [dbg:tpl(M, [{'_', [], Spec}]) || M &lt;- Modules],
    LocallyRunningServers = [M || M &lt;- Modules, whereis(M) /= undefined],
    [dbg:p(whereis(RS), Flags) || RS &lt;- LocallyRunningServers],
    dbg:p(self(), Flags),
    LocallyRunningServers.</pre></div>
    <p>The <span class="code">et_demo:live_trans/0</span> function starts the global
    <span class="code">Collector</span>, starts a <span class="code">Viewer</span>, starts <span class="code">Mnesia</span>,
    creates a local table, activates tracing (as described above) and
    registers the shell process is as 'my_shell' for clarity. Finally
    a simple <span class="code">Mnesia</span> transaction that writes a single record
    is run:</p>

    <p></p>

<div class="example"><pre>

live_trans() -&gt;
    live_trans([]).

live_trans(ExtraOptions) -&gt;
    Options = [{title, "Mnesia tracer"},
	       {hide_actions, true},
	       {active_filter, named_process_info_nolink}],
    et_demo:start(Options ++ ExtraOptions),
    mnesia:start(),
    mnesia:create_table(my_tab, [{ram_copies, [node()]}]),
    et_demo:trace_mnesia(),
    register(my_shell, self()),

    mnesia:transaction(fun() -&gt; mnesia:write({my_tab, key, val}) end).</pre></div>
    <p>Now we run the <span class="code">et_demo:live_trans/0</span> function:</p>

    <p></p>

    <div class="example"><pre>
       erl -pa ../examples
       Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4]
                                  [async-threads:0] [kernel-poll:false]

       Eshell V5.7.4  (abort with ^G)
       1&gt; et_demo:live_trans().
       {atomic,ok}</pre></div>

    <p>Please, explore the different filters in order to see how the traced
      transaction can be seen from different point of views:</p>

    <p></p>

    <img alt="IMAGE MISSING" src="live_trans.png"><br>
      <em>Figure
        4.2:
         
        A real <span class="code">Mnesia</span> transaction which writes one record</em>
    

  

  <h3><a name="id66211">4.4 
        Erlang trace of Megaco startup</a></h3>
    

    <p>The <span class="code">Event Tracer (ET)</span> tool was initially written in
    order to demonstrate how messages where sent over the
    <span class="code">Megaco</span> protocol. This were back in the old days before the
    standard bodies of <span class="code">IETF</span> and <span class="code">ITU</span> had approved
    <span class="code">Megaco</span> (also called <span class="code">H.248</span>) as an international
    standard.</p>

    <p>In the <span class="code">Megaco</span> application of Erlang/OTP, the code is
    carefully instrumented with calls to <span class="code">et:trace_me/5</span>. For
    each call a detail level is given in order to enable dynamic
    control of the trace level in a simple manner.</p>

    <p>The <span class="code">megaco_filter</span> module implements a customized filter
    for <span class="code">Megaco</span> messages. It does also make use of
    <span class="code">trace_global</span> combined with usage of the
    <span class="code">trace_pattern</span>:</p>

    <p></p>

    <div class="example"><pre>
       -module(megaco_filter).
       -export([start/0]).

       start() -&gt;
           Options =
               [{event_order, event_ts},
                {scale, 3},
                {max_actors, infinity},
                {trace_pattern, {megaco, max}},
                {trace_global, true},
                {dict_insert, {filter, megaco_filter}, fun filter/1},
                {active_filter, megaco_filter},
                {title, "Megaco tracer - Erlang/OTP"}],
           et_viewer:start(Options).</pre></div>

    <p>First we start an Erlang node with a global <span class="code">Collector</span>
    and its <span class="code">Viewer</span>.</p>

    <p></p>

    <div class="example"><pre>
          erl -sname observer
          Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4]
                                     [async-threads:0] [kernel-poll:false]

          Eshell V5.7.4  (abort with ^G)
          (observer@falco)1&gt; megaco_filter:start().
          {ok,&lt;0.48.0&gt;}</pre></div>

    <p>Secondly we start another Erlang node which we connect the
    observer node, before we start the application that we want to
    trace. In this case we start a Media Gateway Controller that
    listens for both TCP and UDP on the text and binary ports for
    Megaco:</p>

    <p></p>

    <div class="example"><pre>
          erl -sname mgc -pa ../../megaco/examples/simple
          Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4]
                                     [async-threads:0] [kernel-poll:false]

          Eshell V5.7.4  (abort with ^G)
          (mgc@falco)1&gt; net:ping(observer@falco).
          pong
          (mgc@falco)2&gt; megaco:start().
          ok
          (mgc@falco)3&gt; megaco_simple_mgc:start().
          {ok,[{ok,2944,
                   {megaco_receive_handle,{deviceName,"controller"},
                                          megaco_pretty_text_encoder,[],megaco_tcp,dynamic}},
               {ok,2944,
                   {megaco_receive_handle,{deviceName,"controller"},
                                          megaco_pretty_text_encoder,[],megaco_udp,dynamic}},
               {ok,2945,
                   {megaco_receive_handle,{deviceName,"controller"},
                                          megaco_binary_encoder,[],megaco_tcp,dynamic}},
               {ok,2945,
                   {megaco_receive_handle,{deviceName,"controller"},
                                          megaco_binary_encoder,[],megaco_udp,dynamic}}]}</pre></div>

    <p>And finally we start an Erlang node for the Media Gateways and
    connect to the observer node. Each Media Gateway connects to the
    controller and sends an initial Service Change message. The
    controller accepts the gateways and sends a reply to each one
    using the same transport mechanism and message encoding according
    to the preference of each gateway. That is all combinations of
    TCP/IP transport, UDP/IP transport, text encoding and ASN.1 BER
    encoding:</p>

    <p></p>

    <div class="example"><pre>
         Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4]
                                    [async-threads:0] [kernel-poll:false]

         Eshell V5.7.4  (abort with ^G)
         (mg@falco)1&gt; net:ping(observer@falco).
         pong
         (mg@falco)2&gt; megaco_simple_mg:start().
         [{{deviceName,"gateway_tt"},
           {error,{start_user,megaco_not_started}}},
          {{deviceName,"gateway_tb"},
           {error,{start_user,megaco_not_started}}},
          {{deviceName,"gateway_ut"},
           {error,{start_user,megaco_not_started}}},
          {{deviceName,"gateway_ub"},
           {error,{start_user,megaco_not_started}}}]
         (mg@falco)3&gt; megaco:start().
         ok
         (mg@falco)4&gt; megaco_simple_mg:start().
         [{{deviceName,"gateway_tt"},
           {1,
            {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
                     [{serviceChangeReply,
                          {'ServiceChangeReply',
                              [{megaco_term_id,false,["root"]}],
                              {serviceChangeResParms,
                                  {'ServiceChangeResParm',
                                      {deviceName,"controller"},
                                      asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
                                      asn1_NOVALUE}}}}]}]}}},
          {{deviceName,"gateway_tb"},
           {1,
            {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
                     [{serviceChangeReply,
                          {'ServiceChangeReply',
                              [{megaco_term_id,false,["root"]}],
                              {serviceChangeResParms,
                                  {'ServiceChangeResParm',
                                      {deviceName,"controller"},
                                      asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
                                      asn1_NOVALUE}}}}]}]}}},
          {{deviceName,"gateway_ut"},
           {1,
            {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
                     [{serviceChangeReply,
                          {'ServiceChangeReply',
                              [{megaco_term_id,false,["root"]}],
                              {serviceChangeResParms,
                                  {'ServiceChangeResParm',
                                      {deviceName,"controller"},
                                      asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
                                      asn1_NOVALUE}}}}]}]}}},
          {{deviceName,"gateway_ub"},
           {1,
            {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
                     [{serviceChangeReply,
                          {'ServiceChangeReply',
                              [{megaco_term_id,false,["root"]}],
                              {serviceChangeResParms,
                                  {'ServiceChangeResParm',
                                      {deviceName,"controller"},
                                      asn1_NOVALUE,asn1_NOVALUE,
                                      asn1_NOVALUE,...}}}}]}]}}}]</pre></div>

    <p>The <span class="code">Megaco</span> adopted viewer looks like this, when we have clicked
    on the <strong>[gateway_tt]</strong> actor name in order to only display the events
    regarding that actor:</p>
    
    <p></p>

    <img alt="IMAGE MISSING" src="megaco_tracer.png"><br>
      <em>Figure
        4.3:
         
        The viewer adopted for Megaco</em>
    

    <p>A pretty printed <span class="code">Megaco</span> message looks like this:</p>

    <p></p>

    <img alt="IMAGE MISSING" src="megaco_filter.png"><br>
      <em>Figure
        4.4:
         
        A textual <span class="code">Megaco</span> message</em>
    

    <p>And the corresponding internal form for the same <span class="code">Megaco</span> message
    looks like this:</p>

    <p></p>

    <img alt="IMAGE MISSING" src="megaco_collector.png"><br>
      <em>Figure
        4.5:
         
        The internal form of a <span class="code">Megaco</span> message</em>
    

  

</div>
<div class="footer">
<hr>
<p>Copyright © 2002-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>