NGINX日志过滤器$upstream_response_time JSON ELK“-”解析失败

4

我将NGINX日志格式化为JSON:

log_format le_json '{ "@timestamp": "$time_iso8601", '
                   '"remote_addr": "$remote_addr", '
                   '"remote_user": "$remote_user", '
                   '"body_bytes_sent": "$body_bytes_sent", '
                   '"status": $status, '
                   '"request": "$request", '
                   '"request_method": "$request_method", '
                   '"response_time": $upstream_response_time, '
                   '"http_referrer": "$http_referer", '
                   '"http_user_agent": "$http_user_agent" }';

我的日志被Filebeat捕获并发送到以下配置的Logstash:
input {
  beats {
    port => 5044
    codec => "json"
  }
}
filter {
    geoip {
      database => "C:/GeoLiteCity.dat" 
      source => "[remote_addr]"
          }
}
output {
  elasticsearch {
    template => "C:/ELK/logstash-2.2.2/templates/elasticsearch-template.json"
    template_overwrite => true
    hosts => ["127.0.0.1"]
    index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}"
    document_type => "%{[@metadata][type]}"
  }
}

我遇到的问题是$upstream_response_time。当没有响应时间时,NGINX在此位置放置“-”。正如您所看到的,我没有在$upstream_response_time周围放置"",因为我希望它作为数字,以便我可以在Kibana中执行计算并显示。当发送“ - ”时,由于它不是数字, Logstash中出现jsonparsefailure。
我想将所有“ - ”设置为0。最好的方法是什么?我尝试在nginx-config中进行过滤,但并没有成功。我认为需要在被传送到Logstash之前完成这个操作,因为那里发生了解析失败。
有什么想法吗?

作为一种解决方法,您可以在其后面加上一个零。这样它就变成了 0.1230-0,两者都是完全有效的数字 :) - Alexey Ten
或者使用 map 指令。 - Alexey Ten
在正则表达式中,您不需要斜杠,甚至根本不需要正则表达式。 - Alexey Ten
2个回答

5

试试这个:

map $upstream_response_time $temprt {
  default $upstream_response_time;
  ""      0;
}

$upstream_response_time 可以是一个数字或未设置。Nginx 会将未设置的变量记录为破折号 (-),但 map 将它们视为空字符串。


这个可行:map $upstream_response_time $temprt { default $upstream_response_time; "" 0; }看起来它是空的,如果是这样,那么某些地方的背景被设置为“-”。 - Jesper Persson
谢谢,问题已修复。 - Alexey Ten
@JesperPersson nginx在日志模块中用破折号替换未设置的变量。https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_log_module.c#L957-L960 - Alexey Ten

0
一个来自@AlexeyTen的充分例子,使用空值(null)代替0来区分实际值,因为我不确定如何使用映射变量。
map $upstream_response_time $temprt {
  default $upstream_response_time;
  ""      null;
}

log_format le_json '{ "@timestamp": "$time_iso8601", '
               '"remote_addr": "$remote_addr", '
               '"remote_user": "$remote_user", '
               '"body_bytes_sent": "$body_bytes_sent", '
               '"status": $status, '
               '"request": "$request", '
               '"request_method": "$request_method", '
               '"response_time": $temprt, '
               '"http_referrer": "$http_referer", '
               '"http_user_agent": "$http_user_agent" }';

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接