flm01/web/api/webmachine/www/debugging.html

293 lines
9.2 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="author" content="Basho Technologies" />
<meta name="description" content="Webmachine debugging" />
<meta name="keywords" content="webmachine http rest web" />
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="css/style-1c.css" type="text/css" />
<title>Webmachine debugging</title>
</head>
<body>
<div id="content">
<h1><span class="hr"></span><a href="/">webmachine</a></h1>
<ul id="top">
<li><a href="/">Home</a></li>
<li><a href="http://bitbucket.org/justin/webmachine/">Source Code</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
<div id="left">
<h3>Webmachine debugging</h3>
<p>
Having trouble with your webmachine resource? Try debugging it with
the webmachine trace utility!
</p>
<h2>Basic Use</h2>
<p>
To get started, first change your resource's <code>init/1</code>
function to return <code>{trace, Path}</code> instead of
<code>ok</code>. For example:
</p>
<pre>
init(Config) ->
{{trace, "/tmp"}, Config}. %% debugging code
%%{ok, Config}. %% regular code
</pre>
<p>
Rebuild and reload the module, then in your webmachine application's
shell, type:
</p>
<pre>
wmtrace_resource:add_dispatch_rule("wmtrace", "/tmp").
</pre>
<p>
Now issue the HTTP request that you're trying to debug. Once it has
finished, point your browser at <code>http://YOUR_HOST/wmtrace/</code>.
You'll see one or more trace files available for inspection.
Click on one of them to navigate to the trace inspection utility,
which will look something like this:
</p>
<p><img src="images/basic-trace-labeled.png" alt="Basic Trace" title="Basic Trace" /></p>
<p>
The example above is a trace of a resource that responded to a GET of
the root path (as you can see in the <em>Detail Panel</em>), and ran
all the way to a 200 response code (as you can see in the <em>Decision
Graph</em>).
</p>
<p>
The graph starts small, so you can get a quick view of the path your
resource took through it. You can zoom in and out of the <em>Decision
Graph</em> by using the <em>Zoom Controls</em>.
</p>
<p>
The path your resource took through the graph is highlighted with a
dark grey line. Hovering your mouse over the outlined decision points
along that line will pop up a tool tip with the name of the decision,
and the names of the functions in your resource that were called at
that point. Clicking on a decision will flip the <em>Detail
Panel</em> to the <em>Decision Tab</em>, where information about that
decision will be displayed.
</p>
<p>
If your resource traversed the graph all the way to one of the
standard, non-error return codes, the box for that return code will be
outlined. If your resource instead returned a non-standard or error
code, a red circle will be drawn next to the last decision point your
resource reached. Clicking on either of these types of endpoints will
flip the <em>Detail Panel</em> to the <em>Response Tab</em>, where
information about the response will be displayed.
</p>
<p>
The <em>Detail Panel</em> has three tabs: Request (labeled
<em>Q</em>), Response (labeled <em>R</em>), and Decision (labeled
<em>D</em>). Clicking each of these will show information about the
request, response, or current decision, respectively.
</p>
<p><img src="images/basic-trace-request-tab.png" alt="Detail Panel Request Tab" title="Detail Panel Request Tab" /></p>
<p>
The <em>Request Tab</em> shows details about what the client
requested. The method and path are displayed at the top, headers
below that, and body (if available) at the bottom.
</p>
<p><img src="images/basic-trace-response-tab.png" alt="Detail Panel Response Tab" title="Detail Panel Response Tab" /></p>
<p>
The <em>Response Tab</em> shows details about how your resource
responded. The response code is displayed at the top, headers below
that, and body (if available) at the bottom.
</p>
<p><img src="images/basic-trace-decision-tab.png" alt="Detail Panel Decision Tab" title="Detail Panel Decision Tab" /></p>
<p>
The <em>Decision Tab</em> shows details about the currently selected
decision. The decision's name is displayed in a dropdown at the top
(changing this dropdown or clicking on a decision in the graph will
change which decision is displayed). The list of the functions called
in the resource's module is displayed in a dropdown below the
decision. The arguments with which the function was called are
displayed just below the function's name, and the return value of the
function is displayed at the bottom of the panel.
</p>
<p>
The <em>Detail Panel</em> can be resized by clicking and dragging the
tabs or the dark grey border to the left or right. Clicking the
border will toggle the panel's visibility.
</p>
<h2>Configuration Details</h2>
<p>
The Webmachine trace tool is divided into two parts: one produces the
trace logs, while the other produces the visualization.
</p>
<h3>Trace Log Production Configuration</h3>
<p>
You may configure the path under which trace files are stored by
specifying that path as the <code>Path</code> part of your resource
module's <code>init/1</code> return value. Every time a request is
made to that resource, a new trace file will be created in the
specified directory.
</p>
<p>
<strong><em>Warning</em></strong>: Trace files can be large. It is
advised that you do not leave tracing enabled on a
large-content-producing or high-hit-rate resource.
</p>
<p>
The path may be either absolute:
</p>
<pre>
init(Config) ->
{{trace, "/tmp/traces"}, Config}. %% absolute path /tmp/traces
</pre>
<p>or relative to your application's root:</p>
<p>
<pre>
init(Config) ->
{{trace, "traces"}, Config}. %% "traces" directory in application's root
</pre>
</p>
<h3>Trace Viewer Configuration</h3>
<p>
The viewer is configured by its entry in the
<a href="dispatcher.html">dispatch list</a>.
Two functions make modifying that entry easy:
<code>wmtrace_resource:add_dispatch_rule/2</code>
and <code>wmtrace_resource:remove_dispatch_rules/0</code>.
</p>
<p>
Call <code>add_dispatch_rule/2</code> with the HTTP-exported path, and
the path to the trace files. For example, to expose the viewer at
<code>http://YOUR_HOST/dev/wmtrace/</code> and point it at the trace
files in <code>/tmp/traces</code>, type in your application's erlang
shell:
</p>
<pre>
wmtrace_resource:add_dispatch_rule("dev/wmtrace", "/tmp/traces").
</pre>
<p>
If you know that you always want the viewer enabled and configured in
a specific way, you can also add a line like the following to your
application's dispatch list:
</p>
<pre>
{["dev", "wmtrace", '*'], wmtrace_resource, [{trace_dir, "/tmp/traces"}]}
</pre>
<p>
To disable all trace viewer resources at any point, just execute
<code>wmtrace_resource:remove_dispatch_rules/0</code> in your
application's erlang shell.
</p>
<h2>Trace Log Format</h2>
<p>
The trace file is fairly straightforward, if you want to read it with
<code>less</code>:
</p>
<ul><li><code> {decision, X}. </code> indicates that a decision point was reached
</li><li><code> {attempt, Module, Function, Args}. </code> indicates that a call to <code> Module:Function(Args) </code> was made.
</li><li><code> {result, Module, Function, Result}. </code> indicates that the call to <code> Module:Function(Args) </code> returned <code> Result </code>.
</li><li><code> {not_expored, Module, Function, Args}. </code> indicates that <code> Module:Function(Args) </code> would have been called, but it was not exported (or not defined) by the module
</li></ul>
<p>
The format should be such that a <code>file:consult/1</code> will
give you a list of the lines as erlang terms.
</p>
<h2>Special Handling for Funs and Pids</h2>
<p>
Funs and Pids don't roundtrip through file serialization very well
(<code>file:consult/1</code> will blow up on a fun or pid written to a
file with <code>io:format("~p", [FunOrPid])</code>). To deal with
this, the trace logger prints a recognizable tuple translation instead
of the fun or pid.
</p>
<h3>Fun Translation</h3>
<p>
Funs you might see in Erlang source as <code>fun io:format/2</code>
will appear in a trace log as:
</p>
<pre>
{'WMTRACE_ESCAPED_FUN',[{module,io},
{name,format},
{arity,2},
{type,external}]}
</pre>
<p>
Those that would be in Erlang source as <code> fun() -&gt; ok end
</code> will appear in a trace log as:
</p>
<pre>
{'WMTRACE_ESCAPED_FUN',[{module,sampletrace_resource},
{name,'-to_html/2-fun-0-'},
{arity,0},
{type,local}]}
</pre>
<h3>Pid Translation</h3>
<p>
Pids are simply logged in a marked tuple, after being run through
<code>erlang:pid_to_list/1</code>:
</p>
<pre>
{'WMTRACE_ESCAPED_PID',"<0.74.0>"}
</pre>
</div>
<div id="footer">
</div>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-4979965-5");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>