changeset 698:5182e655d055

DTrace article added
author Sergey Budnevitch <sb@waeme.net>
date Tue, 02 Oct 2012 15:04:30 +0000
parents 5d939bef335c
children 8205c2fcde2f
files xml/en/GNUmakefile xml/en/docs/index.xml xml/en/docs/nginx_dtrace_pid_provider.xml
diffstat 3 files changed, 180 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/xml/en/GNUmakefile
+++ b/xml/en/GNUmakefile
@@ -17,6 +17,7 @@ DOCS =									\
 		howto_build_on_win32					\
 		freebsd_tuning						\
 		howto_setup_development_environment_on_ec2		\
+		nginx_dtrace_pid_provider				\
 
 DOCS_XML =	$(foreach name, $(DOCS), xml/$(DOC_LANG)/docs/$(name).xml)
 DOCS_HTML =	$(foreach name, $(DOCS), $(OUT)/$(DOC_LANG)/docs/$(name).html)
--- a/xml/en/docs/index.xml
+++ b/xml/en/docs/index.xml
@@ -80,6 +80,10 @@
 <link doc="howto_setup_development_environment_on_ec2.xml"/>
 </listitem>
 
+<listitem>
+<link doc="nginx_dtrace_pid_provider.xml"/>
+</listitem>
+
 </list>
 </para>
 
new file mode 100644
--- /dev/null
+++ b/xml/en/docs/nginx_dtrace_pid_provider.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0"?>
+
+<!--
+  Copyright (C) Nginx, Inc.
+  -->
+
+<!DOCTYPE article SYSTEM "../../../dtd/article.dtd">
+
+
+<article name="Debugging nginx with DTrace pid provider"
+	link="/en/docs/nginx_dtrace_pid_provider.html"
+	lang="en"
+	rev="1"
+	toc="no">
+
+<section>
+
+<para>
+This article assumes the reader has a general knowledge of nginx internals and 
+<link id="see_also">DTrace</link>.
+</para>
+
+<para>
+Although nginx build with <link doc="debugging_log.xml">--with-debug</link> option
+already provides a lot of information about request processing, it is sometimes desirable
+to trace particular parts of code path more thoroughly and at the same time
+omit the rest of debug output. DTrace pid provider (available on Solaris, OS X) is a useful
+tool to explore userland programs internals, since it doesn't require any code changes and
+it can help with the task. E.g. a simple DTrace script to trace and print nginx 
+functions calls may look like:
+
+<programlisting>
+#pragma D option flowindent
+
+pid$target:nginx::entry {
+}
+
+pid$target:nginx::return {
+}
+</programlisting>
+
+</para>
+
+<para>
+DTrace capabilities for function calls tracing provide only a limited amount
+of useful information, though. Real-time inspection of function arguments
+is typically more interesting, but also a bit more complicated. Examples below
+are intended to help the reader become more familiar with DTrace and the
+process of analyzing nginx behavior using DTrace.
+</para>
+
+<para>
+One of the common scenarios for using DTrace with nginx is the following:
+attach to the nginx worker to log request lines and request start times.
+The corresponding function to attach is
+<literal>ngx_http_process_request</literal>, and the argument in question
+is a pointer to <literal>ngx_http_request_t</literal> structure.
+DTrace script for such request logging can be as simple as:
+
+<programlisting>
+
+pid$target::*ngx_http_process_request:entry
+{
+    this->request = (ngx_http_request_t *)copyin(arg0, sizeof(ngx_http_request_t));
+    this->request_line = stringof(copyin((uintptr_t)this->request->request_line.data,
+                                         this->request->request_line.len));
+    printf("request line = %s\n", this->request_line); 
+    printf("request start sec = %d\n", this->request->start_sec);
+}
+
+</programlisting>
+</para>
+
+<para>
+It should be noted that in the example above DTrace requires some knowledge about
+<literal>ngx_http_process_request</literal> structure.
+Unfortunately while it is possible to use a specific <literal>#include</literal>
+directive in the DTrace script and then pass it to a C preprocessor
+(with -C flag), that doesn't really work. Due to a lot of cross dependencies almost
+all nginx header files have to be included. In turn, based on configure script
+settings, nginx headers will include PCRE, OpenSSL and a variety of system header
+files. While in theory all those header files related to a specific nginx build
+might be included in DTrace script preprocessing and compilation, in reality
+DTrace script most probably will fail to compile because of unknown syntax in
+some header files.
+</para>
+
+<para>
+The problem above can be solved by including only the relevant and
+necessary structures and types definitions in the DTrace script. DTrace has to know
+sizes of structures, types, and fields offsets. Thus dependencies can be further
+reduced by manually optimizing structure definitions for use with DTrace.
+</para>
+
+<para>
+Let's use DTrace script example above and see what structure definitions it needs
+to work properly.
+</para>
+
+<para>
+First of all <literal>objs/ngx_auto_config.h</literal> file generated by configure
+should be included, because it defines a number of constants affecting various
+<literal>#ifdef's</literal>. After that there's some basic types and definitions
+like <literal>ngx_str_t</literal>, <literal>ngx_table_elt_t</literal>,
+<literal>ngx_uint_t</literal> etc. should be put at the beginning of DTrace script.
+These definitions are compact, commonly used and unlikely to be frequently changed.
+</para>
+
+<para>
+Then there's the <literal>ngx_http_process_request_t</literal> structure which
+contains a lot of pointers to other structures. Because these pointers are
+really irrelevant to this script, and because they have the same size,
+it is possible to just replace them with void pointers. Instead of changing
+definitions, it is better to add appropriate typedefs, though:
+
+<programlisting>
+typedef ngx_http_upstream_t     void;
+typedef ngx_http_request_body_t void;
+</programlisting>
+
+Last but not least it is necessary to add definitions of two member structures:
+<literal>ngx_http_headers_in_t</literal> and
+<literal>ngx_http_headers_out_t</literal>, callback functions
+declarations and constants definitions.
+</para>
+
+<para>
+Final DTrace script can be downloaded 
+<link url="http://nginx.org/download/trace_process_request.d">here</link>.
+</para>
+
+<para>
+The example below shows the output of the DTrace script:
+
+<programlisting>
+# dtrace -C -I ./objs -s trace_process_request.d -p 4848
+dtrace: script 'trace_process_request.d' matched 1 probe
+CPU     ID                    FUNCTION:NAME
+  1      4 .XAbmO.ngx_http_process_request:entry request line = GET / HTTP/1.1
+request start sec = 1349162898
+
+  0      4 .XAbmO.ngx_http_process_request:entry request line = GET /en/docs/nginx_dtrace_pid_provider.html HTTP/1.1
+request start sec = 1349162899
+</programlisting>
+
+</para>
+
+<para>Using similar techniques the reader should be able to trace other
+nginx functions calls.
+</para>
+
+</section>
+
+<section id="see_also"
+         name="See also">
+
+<para>
+<list type="bullet">
+
+<listitem>
+<link url="http://docs.oracle.com/cd/E19253-01/817-6223/index.html">
+Solaris Dynamic Tracing Guide</link>
+</listitem>
+
+<listitem>
+<link url="http://dtrace.org/blogs/brendan/2011/02/09/dtrace-pid-provider/">
+Introduction article on DTrace pid provider</link>
+</listitem>
+
+</list>
+</para>
+
+</section>
+
+</article>