<!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 -- Tutorial</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="loadscrollpos" title="Tutorial" expanded="true">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="no" title="Advanced examples" expanded="false">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>2 Tutorial</h1> <h3><a name="id60778">2.1 Visualizing Message Sequence Charts</a></h3> <p>The easiest way of using <span class="code">ET</span>, is to just use it as a graphical tool for displaying message sequence charts. In order to do that you need to first start a <span class="code">Viewer</span> (which by default starts a <span class="code">Collector</span>):</p> <div class="example"><pre> {ok, ViewerPid} = et_viewer:start([{title,"Coffee Order"}]), CollectorPid = et_viewer:get_collector_pid(ViewerPid).</pre></div> <a name="report_event"></a> <p>Then you send events to the <span class="code">Collector</span> with the function <span class="code">et_collector:report_event/6</span> like this:</p> <div class="example"><pre> et_collector:report_event(CollectorPid,85,from,to,message,extra_stuff).</pre></div> <p>The <span class="code">Viewer</span> will automatically pull events from the <span class="code">Collector</span> and display them on the screen.</p> <p>The number (in this case 85) is an integer from 1 to 100 that specifies the "detail level" of the message. The higher the number, the more important it is. This provides a crude form of priority filtering.</p> <p>The <span class="code">from</span>, <span class="code">to</span>, and <span class="code">message</span> parameters are exactly what they sound like. <span class="code">from</span> and <span class="code">to</span> are visualized in the <span class="code">Viewer</span> as "lifelines", with the message passing from one to the other. If <span class="code">from</span> and <span class="code">to</span> are the same value, then it is displayed next to the lifeline as an "action". The <span class="code">extra_stuff </span>value is simply data that you can attach that will be displayed when someone actually clicks on the action or message in the <span class="code">Viewer</span> window.</p> <p>The module <span class="code">et/examples/et_display_demo.erl</span> illustrates how it can be used:</p> <div class="example"><pre> -module(et_display_demo). -export([test/0]). test() -> {ok, Viewer} = et_viewer:start([{title,"Coffee Order"}, {max_actors,10}]), Drink = {drink,iced_chai_latte}, Size = {size,grande}, Milk = {milk,whole}, Flavor = {flavor,vanilla}, C = et_viewer:get_collector_pid(Viewer), et_collector:report_event(C,99,customer,barrista1,place_order,[Drink,Size,Milk,Flavor]), et_collector:report_event(C,80,barrista1,register,enter_order,[Drink,Size,Flavor]), et_collector:report_event(C,80,register,barrista1,give_total,"$5"), et_collector:report_event(C,80,barrista1,barrista1,get_cup,[Drink,Size]), et_collector:report_event(C,80,barrista1,barrista2,give_cup,[]), et_collector:report_event(C,90,barrista1,customer,request_money,"$5"), et_collector:report_event(C,90,customer,barrista1,pay_money,"$5"), et_collector:report_event(C,80,barrista2,barrista2,get_chai_mix,[]), et_collector:report_event(C,80,barrista2,barrista2,add_flavor,[Flavor]), et_collector:report_event(C,80,barrista2,barrista2,add_milk,[Milk]), et_collector:report_event(C,80,barrista2,barrista2,add_ice,[]), et_collector:report_event(C,80,barrista2,barrista2,swirl,[]), et_collector:report_event(C,80,barrista2,customer,give_tasty_beverage,[Drink,Size]), ok.</pre></div> <p>When you run the <span class="code">et_display_demo:test().</span> function in the example above, the <span class="code">Viewer</span> window will look like this:</p>. <p></p> <img alt="IMAGE MISSING" src="coffee_order.png"><br> <em>Figure 2.1: Screenshot of the <span class="code">Viewer</span> window</em> <h3><a name="id57439">2.2 Four Modules</a></h3> <p>The event tracer framework is made up of four modules:</p> <ul> <li><p><span class="code">et</span></p></li> <li><p><span class="code">et_collector</span></p></li> <li><p><span class="code">et_viewer</span></p></li> <li><p><span class="code">et_selector</span></p></li> </ul> <p>In addition, you'll probably want to familiarize yourself with the <span class="code">dbg</span> module and possibly <span class="code">seq_trace</span> module as well.</p> <h3><a name="id61823">2.3 The Event Tracer Interface</a></h3> <p>The <span class="code">et</span> module is not like other modules. It contains a function called <span class="code">et:trace_me/5</span>. Which is a function that does not do any useful stuff at all. Its sole purpose is to be a function that is easy to trace. A call to it may be something like:</p> <div class="example"><pre> et:trace_me(85,from,to,message,extra_stuff).</pre></div> <p>The parameters to <span class="code">et:trace_me/5</span> are the same as to <span class="bold_code"><a href="#report_event"><span class="code">et_collector:report_event/6</span></a></span> in the previous chapter. The big difference between the two is in the semantics of the two functions. The second actually reports an <span class="code">Event</span> to the <span class="code">Collector</span> while the first does nothing, it just returns the atom <span class="code">hopefully_traced</span>. In order to make the parameters to <span class="code">et:trace_me/5</span> turn up in the <span class="code">Collector</span>, tracing of that function must be activated and the <span class="code">Collector</span> must be registered as a <span class="code">Tracer</span> of the <span class="code">Raw Trace Data</span>.</p> <p>Erlang tracing is a seething pile of pain that involves reasonably complex knowledge of clever ports, tracing return formats, and specialized tracing <span class="code">MatchSpecs</span> (which are really their own special kind of hell). The tracing mechanism is very powerful indeed, but it can be hard to grasp.</p> <p>Luckily there is a simplified way to start tracing of <span class="code">et:trace_me/5</span> function calls. The idea is that you should instrument your code with calls to <span class="code">et:trace_me/5</span> in strategic places where you have interesting information available in your program. Then you just start the <span class="code">Collector</span> with global tracing enabled:</p> <div class="example"><pre> et_viewer:start([{trace_global, true}, {trace_pattern, {et,max}}]).</pre></div> <p>This will start a <span class="code">Collector</span>, a <span class="code">Viewer</span> and also start the tracing of <span class="code">et:trace_me/5</span> function calls. The <span class="code">Raw Trace Data</span> is collected by the <span class="code">Collector</span> and a view of it is displayed on the screen by the <span class="code">Viewer</span>. You can define your own "views" of the data by implementing your own <span class="code">Filter</span> functions and register them in the <span class="code">Viewer</span>.</p> <h3><a name="id56971">2.4 The Collector and Viewer</a></h3> <p>These two pieces work in concert. Basically, the <span class="code">Collector</span> receives <span class="code">Raw Trace Data</span> and processes it into <span class="code">Events</span> in a <span class="code">et</span> specific format (defined in <span class="code">et/include/et.hrl</span>). The <span class="code">Viewer</span> interrogates the <span class="code">Collector</span> and displays an interactive representation of the data.</p> <p>You might wonder why these aren't just one module. The <span class="code">Collector</span> is a generic full-fledged framework that allows processes to "subscribe" to the <span class="code">Events</span> that it collects. One <span class="code">Collector</span> can serve several <span class="code">Viewers</span>. The typical case is that you have one <span class="code">Viewer</span> that visualizes <span class="code">Events</span> in one flavor and another <span class="code">Viewer</span> that visualizes them in another flavor. If you for example are tracing a text based protocol like <span class="code">HTML</span> (or <span class="code">Megaco/H.248</span>) it would be useful to be able to display the <span class="code">Events</span> as plain text as well as the internal representation of the message. The architecture does also allow you to implement your own <span class="code">Viewer</span> program as long as it complies to the protocol between the <span class="code">Collector/Viewer</span> protocol. Currently two kinds of <span class="code">Viewers</span> exists. That is the old <span class="code">GS</span> based one and the new based on <span class="code">wxWidgets</span>. But if you feel for it you may implement your own <span class="code">Viewer</span>, which for example could display the <span class="code">Events</span> as ASCII art or whatever you feel useful.</p> <p>The <span class="code">Viewer</span> will by default create a <span class="code">Collector</span> for you. With a few options and some configuration settings you can start collecting <span class="code">Events</span>.</p> <p>The <span class="code">Collector</span> API does also allow you to save the collected <span class="code">Events</span> to file and later load them in a later session.</p> <h3><a name="id58113">2.5 The Selector</a></h3> <p>This is perhaps the most central module in the entirety of the <span class="code">et</span> suite. The <span class="code">Collector</span> needs "filters" to convert the <span class="code">Raw Trace Data</span> into "events" that it can display. The <span class="code">et_selector</span> module provides the default <span class="code">Filter</span> and some API calls to manage the <span class="code">Trace Pattern</span>. The <span class="code">Selector</span> provides various functions that achieve the following:</p> <ul> <li><p>Convert <span class="code">Raw Trace Data</span> into an appropriate <span class="code">Event</span></p></li> <li><p>Magically notice traces of the <span class="code">et:trace_me/5</span> function and make appropriate <span class="code">Events</span></p></li> <li><p>Carefully prevent translating the <span class="code">Raw Trace Data</span> twice</p></li> <li><p>Manage a <span class="code">Trace Pattern</span></p></li> </ul> <p>The <span class="code">Trace Pattern</span> is basically a tuple of a <span class="code">module</span> and a <span class="code">detail level</span> (either an integer or the atom max for full detail). In most cases the <span class="code">Trace Pattern</span> <span class="code">{et,max}</span> does suffice. But if you do not want any runtime dependency of <span class="code">et</span> you can implement your own <span class="code">trace_me/5</span> function in some module and refer to that module in the <span class="code">Trace Pattern</span>.</p> <p>The specified module flows from your instantiation of the <span class="code">Viewer</span>, to the <span class="code">Collector</span> that it automatically creates, gets stashed in as the <span class="code">Trace Pattern</span>, and eventually goes down into the bowels of the <span class="code">Selector</span>.</p> <p>The module that you specify gets passed down (eventually) into <span class="code">Selector</span>'s default <span class="code">Filter</span>. The format of the <span class="code">et:trace_me/5</span> function call is hardcoded in that <span class="code">Filter</span>.</p> <h3><a name="id62590">2.6 How To Put It Together</a></h3> <p>The <span class="code">Collector</span> automatically registers itself to listen for trace <span class="code">Events</span>, so all you have to do is enable them.</p> <p>For those people who want to do general tracing, consult the <span class="code">dbg</span> module on how to trace whatever you're interested in and let it work its magic. If you just want <span class="code">et:trace_me/5</span> to work, do the following:</p> <ul> <li><p>Create a <span class="code">Collector</span></p></li> <li><p>Create a <span class="code">Viewer</span> (this can do step #1 for you)</p></li> <li><p>Turn on and pare down debugging</p></li> </ul> <p>The module <span class="code">et/examples/et_trace_demo.erl</span> achieves this.</p> <div class="example"><pre> -module(et_trace_demo). -export([test/0]). test() -> et_viewer:start([ {title,"Coffee Order"}, {trace_global,true}, {trace_pattern,{et,max}}, {max_actors,10} ]), %% dbg:p(all,call), %% dbg:tpl(et, trace_me, 5, []), Drink = {drink,iced_chai_latte}, Size = {size,grande}, Milk = {milk,whole}, Flavor = {flavor,vanilla}, et:trace_me(99,customer,barrista1,place_order,[Drink,Size,Milk,Flavor]), et:trace_me(80,barrista1,register,enter_order,[Drink,Size,Flavor]), et:trace_me(80,register,barrista1,give_total,"$5"), et:trace_me(80,barrista1,barrista1,get_cup,[Drink,Size]), et:trace_me(80,barrista1,barrista2,give_cup,[]), et:trace_me(90,barrista1,customer,request_money,"$5"), et:trace_me(90,customer,barrista1,pay_money,"$5"), et:trace_me(80,barrista2,barrista2,get_chai_mix,[]), et:trace_me(80,barrista2,barrista2,add_flavor,[Flavor]), et:trace_me(80,barrista2,barrista2,add_milk,[Milk]), et:trace_me(80,barrista2,barrista2,add_ice,[]), et:trace_me(80,barrista2,barrista2,swirl,[]), et:trace_me(80,barrista2,customer,give_tasty_beverage,[Drink,Size]), ok.</pre></div> <p>Running through the above, the most important points are:</p> <ul> <li><p>Turn on global tracing</p></li> <li><p>Set a <span class="code">Trace Pattern</span></p></li> <li><p>Tell <span class="code">dbg</span> to trace function Calls</p></li> <li><p>Tell it specifically to trace the <span class="code">et:trace_me/5</span> function</p></li> </ul> <p>When you run the <span class="code">et_trace_demo:test()</span> function above, the <span class="code">Viewer</span> window will look like this screenshot:</p>. <p></p> <img alt="IMAGE MISSING" src="coffee_order.png"><br> <em>Figure 2.2: Screenshot of the <span class="code">Viewer</span> window</em> </div> <div class="footer"> <hr> <p>Copyright © 2002-2012 Ericsson AB. All Rights Reserved.</p> </div> </div> </div></body> </html>