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)
如果匹配,它将执行其中的代码块。在代码块中,使用正则表达式提取时间的年、月、日、小时、分钟和秒,并将它们赋值给变量 $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 检测的时候我发现 if 语句不能够放在 http 块内,否则会报错
在 Nginx 中,if 语句主要用于在
server或location块内设置条件,以便根据请求的属性来执行不同的配置。if 语句通常应该包含在server或location块内,而不是直接放在http块中
如果将 if 语句放在一个一个 server 块中,这不得累死我(有很多个 server 块),而且后期维护也不方便
所以如何将自定义变量在全局配置中生效则成为了一个问题
map
map 指令是由 ngx_http_map_module 模块提供的,是 Nginx 配置文件中的一种用于创建变量映射的指令
模块链接:Module ngx_http_map_module (nginx.org)
它允许我们将一个或多个输入值映射到一个输出值,类似于字典或哈希表的概念。map 指令通常用于根据特定条件为请求设置自定义变量,或者执行基于请求属性的条件控制
比较常见的 map 用法是通过 map 来实现允许多个域名跨域访问的问题
语法如下:
map $variable $new_variable {
value1 result1;
value2 result2;
...
default default_result;
}
其中:
$variable输入变量,通常是 nginx 的内置变量。$new_variable输出变量,它将根据输入值的映射设置为特定的结果。value1,value2, ... 输入值,可以列出多个值。result1,result2, ... 与相应输入值相关联的输出结果。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 实现时间格式转换的更多相关文章
- SQL Server日期时间格式转换字符串详解 (详询请加qq:2085920154)
在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...
- SQL Server日期时间格式转换字符串
在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...
- MySQL时间戳和时间格式转换函数
MySQL时间戳和时间格式转换函数:unix_timestamp and from_unixtime unix_timestamp将时间转化成时间戳格式.from_unixtime将时间戳转化成时间格 ...
- Sql日期时间格式转换;取年 月 日,函数:DateName()、DATEPART()
一.sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007 ...
- SQL Server日期时间格式转换字符串详解
本文我们主要介绍了SQL Server日期时间格式转换字符串的相关知识,并给出了大量实例对其各个参数进行对比说明,希望能够对您有所帮助. 在SQL Server数据库中,SQL Server日期时间格 ...
- sql 日期时间格式转换
Sql日期时间格式转换 sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, ...
- [php基础]Mysql日期函数:日期时间格式转换函数详解
在PHP网站开发中,Mysql数据库设计中日期时间字段必不可少,由于Mysql日期函数输出的日期格式与PHP日期函数之间的日期格式兼容性不够,这就需要根据网站实际情况使用Mysql或PHP日期转换函数 ...
- lua 特殊时间格式转换
[1]时间格式转换需求 工作中,因业务需要将时间格式进行转换.需求内容如下: 原格式:17:04:49.475 UTC Mon Mar 04 2019 转换格式:2019-03-04 17:04:4 ...
- scala 时间格式转换(String、Long、Date)
1)scala 时间格式转换(String.Long.Date) 1.时间字符类型转Date类型 [java] view plain copy import java.text.SimpleDateF ...
- 问题:Oracle to_date;结果:oracle常用的时间格式转换
oracle常用的时间格式转换 1:取得当前日期是本月的第几周 SQL> select to_char(sysdate,'YYYYMMDD W HH24:MI:SS') from dual; T ...
随机推荐
- element-ui中Select 选择器异步加载下一页
场景 当我们使用 Select 选择器存放大量数据的时候. 会发现存在这么2个问题. 1.接口响应时间较长.(因为数据量较多,一次查询的所有)甚至有可能超时. 2.前端下拉框滑动卡顿. 这个时候们如何 ...
- 记一次BootCDN被黑产挂马导致站点跳转博彩网站的问题
近期发现公司某些站点出现偶尔跳转博彩网站的现象,经过排查发现该现象为供应链投毒攻击,BootCDN上的静态资源无一例外均被污染, 当外站引入BootCDN的静态资源时,如果请求携带的Referer头为 ...
- Python Joblib库使用学习总结
实践环境 python 3.6.2 Joblib 简介 Joblib是一组在Python中提供轻量级流水线的工具.特别是: 函数的透明磁盘缓存和延迟重新计算(记忆模式) 简单易用的并行计算 Jobli ...
- WPF 入门笔记 - 03 - 样式基础及模板
程序的本质 - 数据结构 + 算法 本篇为学习李应保老师所著的<WPF专业编程指南>并搭配WPF开发圣经<WPF编程宝典第4版>以及痕迹大佬<WPF入门基础教程系列> ...
- 手把手教你实战TDD
1. 前言 领域驱动设计,测试驱动开发. 我们在<手把手教你落地DDD>一文中介绍了领域驱动设计(DDD)的落地实战,本文将对测试驱动开发(TDD)进行探讨,主要内容有:TDD基本理解.T ...
- 浏览器输入URL到网页完全呈现的过程
前言 临近计算机网络期末考试, 最近在复习(预习), 写一遍博客讲解加深印象. 浏览器输入URL过程图 浏览器输入 URL 过程: 当用户在网页上输入网址 URL 后, 浏览器会对网址进行 DNS 域 ...
- 搭建私人GPT及域名配置
前几天在掘金看到一个搭建私人ChatGPT的教程,看起来并不难. 我也有OpenAI的API Key,然后前阵子我看到我的账号余额还有很多,我的api key其实就一个机器人在用,没用多少. 还有,就 ...
- 【python基础】函数-值传递
为了更好的认识函数,我们还要研究值传递问题,再研究这个问题之前,我们已经知道了函数之间的值传递,是实参变量值传递给形参变量,然后让形参变量在函数内完成相应的功能.但是因为数据类型的不同,这里的值传递产 ...
- 【Netty】一个RPC实例
Netty实现简易RPC调用 总体流程: 客户端发起rpc调用请求,封装好调用的接口名,函数名,返回类型,函数参数类型,函数参数值等属性,将消息发送给服务器. 服务器的handler解析rpc请求,调 ...
- macOS 系统 Kafka 快速入门
Kafka 的核心功能是高性能的消息发送与高性能的消息消费.以下是 Kafka 的快速入门教程. 下载并解压缩 Kafka 二进制代码压缩文件 打开 Kafka 官网的下载地址,可以看到不同版本的 K ...