Nginx?map?實現時間格式轉換的方法
最近我們需要把 Nginx 的日志接入到自研的日志采集平臺上,但是這個平臺只支持 JSON 格式,所以需要把 Nginx 日志格式改成 JSON 格式
例如下面這樣的效果
剛開始在主配置文件 nginx.conf
中定義了一個名叫 json
的日志格式字段
驗證的時候其他內容沒啥問題,但是時間是 2023-09-12T13:54:22+08:00
這樣子的,不太符合預期
咸魚想著把 $time_iso8601
變量中的年月日時分秒分別提取出來然后用變量去接受它,如下所示:
我自定義了一個時間格式 $year-$month-$day $hour:$minutes:$seconds:000
,然后接著用了一個 if 語句用于檢查請求的時間是否匹配 ISO8601 時間格式(例如: 2023-09-12T13:54:22+08:00
)
如果匹配,它將執(zhí)行其中的代碼塊。在代碼塊中,使用正則表達式提取時間的年、月、日、小時、分鐘和秒,并將它們賦值給變量 $year
、 $month
、 $day
、 $hour
、 $minutes
和 $seconds
log_format json '{ "SYS_NO":"my_nginx", "OS_TIME":"$year-$month-$day $hour:$minutes:$seconds", "LOG_TYPE":"", "RESULT":"$status", "SPENT_TIME":"$request_time", "CLIENT_IP":"$remote_addr", "SERVER_IP":"$server_addr", "O_CHANNEL":"$http_user_agent", "UID":"$http_host", "VALUE1":$body_bytes_sent, "INFO1":"$http_referer", }'; if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})") { set $year $1; set $month $2; set $day $3; set $hour $4; set $minutes $5; set $seconds $6; }
但是 nginx -t
檢測的時候我發(fā)現 if 語句不能夠放在 http
塊內,否則會報錯
在 Nginx 中,if 語句主要用于在 server
或 location
塊內設置條件,以便根據請求的屬性來執(zhí)行不同的配置。if 語句通常應該包含在 server
或 location
塊內,而不是直接放在 http
塊中
如果將 if 語句放在一個一個 server 塊中,這不得累死我(有很多個 server 塊),而且后期維護也不方便
所以如何將自定義變量在全局配置中生效則成為了一個問題
map
map 指令是由 ngx_http_map_module
模塊提供的,是 Nginx 配置文件中的一種用于創(chuàng)建變量映射的指令
模塊鏈接:Module ngx_http_map_module (nginx.org)
它允許我們將一個或多個輸入值映射到一個輸出值,類似于字典或哈希表的概念。 map
指令通常用于根據特定條件為請求設置自定義變量,或者執(zhí)行基于請求屬性的條件控制
比較常見的 map 用法是通過 map 來實現允許多個域名跨域訪問的問題
語法如下:
map $variable $new_variable { value1 result1; value2 result2; ... default default_result; }
其中:
$variable
輸入變量,通常是 nginx 的內置變量。$new_variable
輸出變量,它將根據輸入值的映射設置為特定的結果。value1
,value2
, ... 輸入值,可以列出多個值。result1
,result2
, ... 與相應輸入值相關聯(lián)的輸出結果。default
一個可選項,表示如果沒有匹配的輸入值,將使用默認結果
需要注意的是,map 只能放在 http 塊中
有了 map,我們就可以輕易的把 $time_iso8601
變量中的 ISO 8601 格式的時間戳轉換為指定的時間格式,然后存儲到自定義變量 $log_time
中
# nginx.conf map $time_iso8601 $log_time { default ""; "~^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hour>\d{2}):(?<minutes>\d{2}):(?<seconds>\d{2})" "${year}-${month}-${day} ${hour}:${minutes}:${seconds}"; }
我們可以看到:
- 輸入變量為
$time_iso8601
,輸出變量為$log_time
; default ""
:如果沒有匹配任何條件,將使用空字符串作為$log_time
的值"~^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hour>\d{2}):(?<minutes>\d{2}):(?<seconds>\d{2})"
:這是一個正則表達式條件,它用于匹配 ISO 8601 格式的時間戳。該正則表達式包含了多個捕獲組(使用?<name>
語法),用于從時間戳中提取年、月、日、小時、分鐘和秒的值"${year}-${month}-${day} ${hour}:${minutes}:${seconds}"
:這是與正則表達式條件匹配時設置的輸出值。當正則表達式條件匹配時,它會將捕獲組中提取的年、月、日、小時、分鐘和秒的值組合成一個自定義的時間格式,然后將該值設置為$log_time
變量的值
例如,如果 $time_iso8601
的值是 "2023-09-09T14:30:00",則 $log_time
將被設置為 "2023-09-09 14:30:00"
然后我們再把 $log_time
放進我們自定義的日志格式里面,完整配置如下
log_format json '{ "SYS_NO":"my_nginx", "OS_TIME":"$log_time", "LOG_TYPE":"", "RESULT":"$status", "SPENT_TIME":"$request_time", "CLIENT_IP":"$remote_addr", "SERVER_IP":"$server_addr", "O_CHANNEL":"$http_user_agent", "UID":"$http_host", "VALUE1":$body_bytes_sent, "INFO1":"$http_referer", }'; map $time_iso8601 $log_time { default ""; "~^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hour>\d{2}):(?<minutes>\d{2}):(?<seconds>\d{2})" "${year}-${month}-${day} ${hour}:${minutes}:${seconds}"; }
最后我們驗證一下
到此這篇關于Nginx map 實現時間格式轉換的文章就介紹到這了,更多相關Nginx map 實現時間格式轉換內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Nginx隱藏index.php和Pathinfo模式配置例子
這篇文章主要介紹了Nginx隱藏index.php和Pathinfo模式配置例子,需要的朋友可以參考下2014-04-04