293 lines
9.2 KiB
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() -> 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>
|
||
|
|