Re: Undefined переменная при логировании

Maxim Dounin mdounin на mdounin.ru
Пн Ноя 9 13:38:33 UTC 2015


Hello!

On Mon, Nov 09, 2015 at 04:38:36PM +0600, Максим wrote:

> Есть вот такой вот набор (в реальности всё разумеется сложнее, но свелось к
> этому компактному конфигу):
> 
> error_log  /bla/error.log warn;
> 
> http {
>     uninitialized_variable_warn on;
>     log_format  combinedvhost  '$host_short $remote_addr - $remote_user
> [$time_local] '
>                           '"$request" $status $body_bytes_sent '
>                           '"$http_referer" "$http_user_agent"';
> 
>     access_log /bla/access_log combinedvhost;
> 
>     server {
>         set $host_short "MYSTRING";
> 
>         listen       blah:80;
>         server_name  all;
> 
>         .....
>     }
> 
> Всё логируется замечательно, но иногда приходит некий (некорректный,
> видимо) запрос, и с переменной $host_short творится странное:
> 
> в error_log:
> 2015/11/09 13:16:45 [warn] 58369#0: *41 using uninitialized "host_short"
> variable while logging request, client: 109.196.xxx.xx, server: all
> 
> в access_log:
>  109.196.xxx.xx - - [09/Nov/2015:13:16:45 +0300] "-" 400 0 "-" "-"
> 
> Как видно из первого лога, мы попали в правильный блок server{}
> Но как видно из обоих логов, в нём не обработалась директива set.

Потому что до обработки директивы set дело не дошло - запрос 
клиента некорректен, ему вернули ошибку 400 ещё до того, как 
началась какая-либо обаботкабез всякой обработки.

(В данном случае, видимо, запроса вообще не было, и nginx старый.  
В nginx 1.3.15 просто открытие соединения больше как 400 ошибка не 
логгируется.  Впрочем, это не важно.)

> Видимо, в nginx есть какая-то оптимизация внутри для некорректного запроса,
> и исполнение инструкций внутри server{} отбрасывается. Прав ли я в этом?

Почти.  Это не оптимизация, просто оно так устроено - в случае 
возникновения ошибки обработка запроса прекращается.  В данном 
случае обработка прекратилась ещё до того, как началась.

> А самое главное, как решить проблему порчи логов? set на уровне http
> очевидно невозможен.

Если совсем просто, то так:

    uninitialized_variable_warn off;

Подробнее - http://nginx.org/r/uninitialized_variable_warn.

Ну или можно подумать подробнее над конфигурацией, и, скажем, 
переделать всё на использование map, http://nginx.org/r/map. 

> Будет ли полноценным решением воспользоваться функционалом из nginx 1.7.0
> по условному логгированию?
> как-то так, чтоли: access_log /path/to/access.log combined_vhost
> if=($status != 400);
> 
> Или это тоже не будет работать?

Работать, возможно, и будет, но это выглядит как плохая идея.

-- 
Maxim Dounin
http://nginx.org/



Подробная информация о списке рассылки nginx-ru