Mercurial > hg > nginx-site
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 Tue Oct 02 13:49:39 2012 +0000 +++ b/xml/en/GNUmakefile Tue Oct 02 15:04:30 2012 +0000 @@ -17,6 +17,7 @@ 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 Tue Oct 02 13:49:39 2012 +0000 +++ b/xml/en/docs/index.xml Tue Oct 02 15:04:30 2012 +0000 @@ -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>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml/en/docs/nginx_dtrace_pid_provider.xml Tue Oct 02 15:04:30 2012 +0000 @@ -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>