Skip to content

Instantly share code, notes, and snippets.

@dylanninin
Last active November 4, 2016 04:09
Show Gist options
  • Save dylanninin/bfc9cfce80a4d8737952440b25d61298 to your computer and use it in GitHub Desktop.
Save dylanninin/bfc9cfce80a4d8737952440b25d61298 to your computer and use it in GitHub Desktop.
ngx-phase-handlers.stp with comments
/*
Dumped by ngx-phase-handlers of openresty-systemtap-tools
- Ubuntu 16.04
- 2016-11-03
*/
/* probe begin event */
probe begin {
/* target() return pid specifed as "stap -x pid ngx-phase-handlers.stp" */
printf("Tracing %d (/usr/local/openresty/nginx/sbin/nginx)...\n", target())
}
/* print phase */
function print_phase(cmcf, phase_num) {
n = @cast(cmcf, "ngx_http_core_main_conf_t", "/usr/local/openresty/nginx/sbin/nginx")->phases[phase_num]->handlers->nelts
handler_addr = @cast(cmcf, "ngx_http_core_main_conf_t", "/usr/local/openresty/nginx/sbin/nginx")->phases[phase_num]->handlers->elts
handler = @cast(handler_addr, "ngx_http_handler_pt", "/usr/local/openresty/nginx/sbin/nginx")
for ( i = 0; i < n; i++ ) {
/* string:usymname(address) returns the symbol name of the specified address */
printf(" %s\n", usymname(handler))
/* next handler address by offset */
handler_addr += &@cast(0, "ngx_int_t", "/usr/local/openresty/nginx/sbin/nginx")[1]
handler = @cast(handler_addr, "ngx_http_handler_pt", "/usr/local/openresty/nginx/sbin/nginx")
}
}
/*
User space event probes prefixed with process
- process("PATH").function("function")
- nm show symbols in a executable binary file
- readelf ELF(Executable and Linkable File format)
Nginx request phases
- 0 post-read
- 1 server-rewrite
- 2 find_config
- 3 rewrite
- 4 post-rewrite
- 5 pre-access
- 6 access
- 7 post-access
- 8 try-files
- 9 content
- 10 log
Reference
- https://sourceware.org/systemtap/SystemTap_Beginners_Guide/userspace-probing.html
- https://github.com/openresty/openresty-systemtap-toolkit/blob/master/ngx-phase-handlers
- http://tengine.taobao.org/book/chapter_12.html#id8
*/
probe process("/usr/local/openresty/nginx/sbin/nginx").function("ngx_http_log_request")
{
if (pid() == target()) {
/* start */
begin = gettimeofday_us()
/*
Target variables
Refernece
- https://www.sourceware.org/systemtap/SystemTap_Beginners_Guide/targetvariables.html
*/
ngx_http_core_module = &@var("ngx_http_core_module")
/* Typecasting ngx_http_core_module as a pointer ot ngx_module_t type, and accessing its ctx_index variable */
ctx_index = @cast(ngx_http_core_module, "ngx_module_t")->ctx_index
/*
Current request
*/
cmcf = $r->main_conf[ctx_index]
/* 3 rewrite phase */
use_rewrite = @cast(cmcf, "ngx_http_core_main_conf_t", "/usr/local/openresty/nginx/sbin/nginx")->phases[3]->handlers->nelts ? 1 : 0
/* 6 access phase */
use_access = @cast(cmcf, "ngx_http_core_main_conf_t", "/usr/local/openresty/nginx/sbin/nginx")->phases[6]->handlers->nelts ? 1 : 0
n = 0
/*
There're total 11 phases, including last `log` phase.
Since `log` is the last executed phase, all previous phases may be executed(including been escaped)
*/
for ( i = 0; i < 10; i++) {
if (i == 2) { /* find_config: find location config via uri */
n++
continue
}
if ( i == 4) { /* post-rewrite: check rewrite result */
if(use_rewrite) {
n++
}
continue
}
if ( i == 7){ /* post-access: execute access result */
if(use_access) {
n++
}
continue
}
if ( i == 8 ){ /* try-files */
if ( @cast(cmcf, "ngx_http_core_main_conf_t", "/usr/local/openresty/nginx/sbin/nginx")->try_files ) {
n++
}
continue
}
/*
Each phase is designed to allow registering handlers (although some phases are actually not, e.g. post-access)
*/
phase_len = @cast(cmcf, "ngx_http_core_main_conf_t", "/usr/local/openresty/nginx/sbin/nginx")->phases[i]->handlers->nelts
if ( phase_len == 0 ){
continue
}
if ( i == 0 ) {
println("post-read phase")
} else if ( i == 1 ) {
println("server-rewrite phase")
} else if ( i == 3 ) {
println("rewrite-phase")
} else if ( i == 5 ) {
println("pre-access phase")
} else if ( i == 6) {
println("access phase")
} else if (i == 9) {
println("content phase")
if ($r->content_handler) {
printf(" %s (request content handler)\n", usymname($r->content_handler))
}
} else {
printf("unknown phase (%d)\n", i)
}
/* Registered handlers in current phase */
for (j = 0; j < phase_len; j++) {
handler = @cast(cmcf, "ngx_http_core_main_conf_t", "/usr/local/openresty/nginx/sbin/nginx")->phase_engine->handlers[n++]->handler
if (handler == 0 ) {
continue
}
printf(" %s\n", usymname(handler))
}
printf("\n")
}
/* log phase */
println("log phase")
print_phase(cmcf, 10)
elapsed = gettimeofday_us() - begin
printf("\n%d microseconds elapsed in the probe handler.\n", elapsed)
exit()
}
}
@dylanninin
Copy link
Author

ngx-phase-handlers

This tool dumps all the handlers registered by all the nginx modules for every nginx running phase in the order they actually run.

This is very useful in debugging Nginx configuration issues caused by misinterpreting the running order of the Nginx configuration directives.

Reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment