Lloyd R. Prentice
Lloyd R. Prentice

Reputation: 4837

Debugging Erlang Webmachine resource functions

I'm trying to learn how to write Erlang Webmachine resources. One resource throws an error, but I can't tracking it down. The error message in the crash report does not provide enough information.

Is there a way to test these functions in the Erlang shell?

Most of the functions in the resource require request and context parameters. But I don't know how to simulate these parameters in the browser.

Example code below.

Thanks,

LRP

Example code:

I'm thinking specifically of functions like:

content_types_provided(RD, Ctx) ->
   Path = wrq:disp_path(RD),
   {[{webmachine_util:guess_mime(Path), generate_body}],
   RD, Ctx}.

But my current bug is in the init function.

This works...

Dispatch rule:

{["blip"], zzz_resource, []}.

Init:

init([]) -> {ok, undefined}.

to_html(ReqData, State) ->
    % {"<html><bodoy>Hello, new world</body></html>", ReqData, State}.
        {test:test(), ReqData, State}.

But this throws an error:

Dispatch:

{["static"], static_resource,[]}.

Init:

init(_) ->
   DocRoot =
       case init:get_argument(doc_root) of
          {ok, [[DR]]} -> DR;
           error -> "doc_root path error"
       end,
   {ok, #ctx{docroot=DocRoot}}.

=ERROR REPORT==== 4-Aug-2011::10:54:56 ===
webmachine error: path="/static"
{error,function_clause,
   [{filename,join,[[]]},
    {static_resource,resource_exists,2},

Upvotes: 3

Views: 945

Answers (2)

arun_suresh
arun_suresh

Reputation: 2925

In addition to the various techniques David has suggested, you should also learn to use the dbg module. It is incredibly powerful and lets you trace functions and modules in real time.

As an example, for your particular case, suppose you want to trace all the functions in static_resource module :

..
1> dbg:tracer().
{ok,}
2> dbg:p(all,[c]). 
{ok,[{matched,nonode@nohost,25}]} 
3> dbg:tp({static_resource, '_', '_'}, []). 
{ok,[{matched,nonode@nohost,5}]}
...

after which you will see a printout (includs all the function parameters in the function call) whenever static_resource module is invoked anywhere.

A full description of dbg is beyond the scope of this small answer space. I recommend O'rielly's Erlang Programming book. Chaper 17 has a really awesome write up and tutorial on how to use it dbg and its various trace features.

Upvotes: 2

David Weldon
David Weldon

Reputation: 64312

There are a lot of layers to this answer depending on what you want to see and how deep down the rabbit hole you want to go.


Let's start with the easy stuff:

The error you are getting tells me that a call to static_resource:resource_exists/2 resulted in a call to filename:join/1 which failed because it was passed [] as its argument. That should help you track down the issue.

Recommended reading: errors-and-exceptions


A crude way to track down errors in any language is just to add print statements at strategic loctations. In this case you can use io:format/2 or erlang:display/1 to display whatever you want to the console. For example:

...
erlang:display("I'm inside resource_exists!"),
StuffToJoin = ["foo", "bar"],
erlang:display(StuffToJoin),
filename:join(StuffToJoin),
...

Just reload the page you should see the value printed in the console (assuming the appropriate function was called as part of the reload).


If you want to manually test a resource (like in a unit test) you can do something like the following:

Headers = [{"Host", "mydomain.com"}, {"user-agent", "Firefox"}],
Context = [],
Path = "/static",
ReqData = wrq:create('GET', {1,1}, Path, mochiweb_headers:from_list(Headers)),
static_resource:resource_exists(ReqData, Context)

If you want a deep look at how to debug webmachine, you can read this. You can get pretty far with the above, but doing a full trace can be helpful if you need to see the decision graph.

Upvotes: 4

Related Questions