| |
| /* |
| * Copyright (C) Igor Sysoev |
| */ |
| |
| |
| #include <ngx_config.h> |
| #include <ngx_core.h> |
| |
| /* |
| * declare Profiler interface here because |
| * <google/profiler.h> is C++ header file |
| */ |
| |
| int ProfilerStart(u_char* fname); |
| void ProfilerStop(void); |
| void ProfilerRegisterThread(void); |
| |
| |
| static void *ngx_google_perftools_create_conf(ngx_cycle_t *cycle); |
| static ngx_int_t ngx_google_perftools_worker(ngx_cycle_t *cycle); |
| |
| |
| typedef struct { |
| ngx_str_t profiles; |
| } ngx_google_perftools_conf_t; |
| |
| |
| static ngx_command_t ngx_google_perftools_commands[] = { |
| |
| { ngx_string("google_perftools_profiles"), |
| NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, |
| ngx_conf_set_str_slot, |
| 0, |
| offsetof(ngx_google_perftools_conf_t, profiles), |
| NULL }, |
| |
| ngx_null_command |
| }; |
| |
| |
| static ngx_core_module_t ngx_google_perftools_module_ctx = { |
| ngx_string("google_perftools"), |
| ngx_google_perftools_create_conf, |
| NULL |
| }; |
| |
| |
| ngx_module_t ngx_google_perftools_module = { |
| NGX_MODULE_V1, |
| &ngx_google_perftools_module_ctx, /* module context */ |
| ngx_google_perftools_commands, /* module directives */ |
| NGX_CORE_MODULE, /* module type */ |
| NULL, /* init master */ |
| NULL, /* init module */ |
| ngx_google_perftools_worker, /* init process */ |
| NULL, /* init thread */ |
| NULL, /* exit thread */ |
| NULL, /* exit process */ |
| NULL, /* exit master */ |
| NGX_MODULE_V1_PADDING |
| }; |
| |
| |
| static void * |
| ngx_google_perftools_create_conf(ngx_cycle_t *cycle) |
| { |
| ngx_google_perftools_conf_t *gptcf; |
| |
| gptcf = ngx_pcalloc(cycle->pool, sizeof(ngx_google_perftools_conf_t)); |
| if (gptcf == NULL) { |
| return NULL; |
| } |
| |
| /* |
| * set by ngx_pcalloc() |
| * |
| * gptcf->profiles = { 0, NULL }; |
| */ |
| |
| return gptcf; |
| } |
| |
| |
| static ngx_int_t |
| ngx_google_perftools_worker(ngx_cycle_t *cycle) |
| { |
| u_char *profile; |
| ngx_google_perftools_conf_t *gptcf; |
| |
| gptcf = (ngx_google_perftools_conf_t *) |
| ngx_get_conf(cycle->conf_ctx, ngx_google_perftools_module); |
| |
| if (gptcf->profiles.len == 0) { |
| return NGX_OK; |
| } |
| |
| profile = ngx_alloc(gptcf->profiles.len + NGX_INT_T_LEN + 2, cycle->log); |
| if (profile == NULL) { |
| return NGX_OK; |
| } |
| |
| if (getenv("CPUPROFILE")) { |
| /* disable inherited Profiler enabled in master process */ |
| ProfilerStop(); |
| } |
| |
| ngx_sprintf(profile, "%V.%d%Z", &gptcf->profiles, ngx_pid); |
| |
| if (ProfilerStart(profile)) { |
| /* start ITIMER_PROF timer */ |
| ProfilerRegisterThread(); |
| |
| } else { |
| ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno, |
| "ProfilerStart(%s) failed", profile); |
| } |
| |
| ngx_free(profile); |
| |
| return NGX_OK; |
| } |
| |
| |
| /* ProfilerStop() is called on Profiler destruction */ |