哈喽大家好,我是咸鱼

最近我们需要把 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 语句主要用于在 serverlocation 块内设置条件,以便根据请求的属性来执行不同的配置。if 语句通常应该包含在 serverlocation 块内,而不是直接放在 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 实现时间格式转换的更多相关文章

  1. SQL Server日期时间格式转换字符串详解 (详询请加qq:2085920154)

    在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...

  2. SQL Server日期时间格式转换字符串

    在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...

  3. MySQL时间戳和时间格式转换函数

    MySQL时间戳和时间格式转换函数:unix_timestamp and from_unixtime unix_timestamp将时间转化成时间戳格式.from_unixtime将时间戳转化成时间格 ...

  4. Sql日期时间格式转换;取年 月 日,函数:DateName()、DATEPART()

    一.sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007 ...

  5. SQL Server日期时间格式转换字符串详解

    本文我们主要介绍了SQL Server日期时间格式转换字符串的相关知识,并给出了大量实例对其各个参数进行对比说明,希望能够对您有所帮助. 在SQL Server数据库中,SQL Server日期时间格 ...

  6. sql 日期时间格式转换

    Sql日期时间格式转换   sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, ...

  7. [php基础]Mysql日期函数:日期时间格式转换函数详解

    在PHP网站开发中,Mysql数据库设计中日期时间字段必不可少,由于Mysql日期函数输出的日期格式与PHP日期函数之间的日期格式兼容性不够,这就需要根据网站实际情况使用Mysql或PHP日期转换函数 ...

  8. lua 特殊时间格式转换

    [1]时间格式转换需求 工作中,因业务需要将时间格式进行转换.需求内容如下: 原格式:17:04:49.475  UTC Mon Mar 04 2019 转换格式:2019-03-04 17:04:4 ...

  9. scala 时间格式转换(String、Long、Date)

    1)scala 时间格式转换(String.Long.Date) 1.时间字符类型转Date类型 [java] view plain copy import java.text.SimpleDateF ...

  10. 问题:Oracle to_date;结果:oracle常用的时间格式转换

    oracle常用的时间格式转换 1:取得当前日期是本月的第几周 SQL> select to_char(sysdate,'YYYYMMDD W HH24:MI:SS') from dual; T ...

随机推荐

  1. Linux常用磁盘管理命令详解

    du du命令用于查看文件和目录磁盘的使用空间. 命令语法:du [参数] [文件或目录名称] 参数说明: 参数 说明 -a 列出所有的文件与目录容量. -h 以G.M.K为单位,返回容量. -s 列 ...

  2. OpenOffice4.1.6 linux安装/卸载教程

    以下是centos的安装方法 1.先安装并配置好jdk 2.拷贝 把Apache_OpenOffice_4.1.6_Linux_x86-64_install-rpm_zh-CN.tar.gz拷贝到自己 ...

  3. ensp 链路聚合

    链路聚合(Link Aggregation)   指将多个物理端口汇聚在一起,形成一个逻辑端口,以实现出/入流量吞吐量在各成员端口的负荷分担,链路聚合在增加链路带宽.实现链路传输弹性和工程冗余等方面是 ...

  4. flutter系列之:做一个会飞的菜单

    目录 简介 定义一个菜单项目 让menu动起来 添加菜单内部的动画 总结 简介 flutter中自带了drawer组件,可以实现通用的菜单功能,那么有没有一种可能,我们可以通过自定义动画来实现一个别样 ...

  5. WinUI(WASDK)使用HelixToolkit加载3D模型并进行项目实践

    前言 本人之前开发了一个叫电子脑壳的上位机应用,给稚晖君ElectronBot开源机器人提供一些功能,但是由于是结合硬件才能使用的软件,如果拥有硬件的人员太少,就会导致我的软件没什么人用,于是我就想着 ...

  6. 20230611 再次升级SSD

    家里常用电脑的硬盘又显得捉襟见肘,老规矩,升级SSD.幸亏几年前摸索的方法记录下来了,翻出以前的博客复习一下.为了保险起见,也重新在网上搜了一下,看是不是有新的更方便的方法,答案是没有,只是搜出很多推 ...

  7. 从隐私保护到AI隐私保护:隐私隐私保护的跨隐私保护治理框架实践案例

    目录 标题:<从隐私保护到AI隐私保护:跨隐私保护治理框架实践案例> 背景介绍 随着人工智能技术的广泛应用,隐私保护问题也日益突出.数据隐私泄露.算法歧视等问题引发了公众的担忧和不满.为了 ...

  8. .Net全网最简Redis操作

    支持.Net/.Net Core/.Net Framework,可以部署在Docker, Windows, Linux, Mac. Redis作为一款主流的缓存工具在业内已广受欢迎.本文将会介绍操作R ...

  9. C#使用企业微信群机器人推送生产数据

    在日常的工作生产中,经常会有将将生产数据或者一些信息主动推送给相关的管理人员,我们公司在开发WMS系统时,为了仓库的储存安全,需要在危废品库存达到一定的储量时,自动通知仓管员去处理危废品,所以就需要程 ...

  10. iis7以上 ssl 证书导入

    证书导入 开始 -〉运行 -〉MMC: 启动控制台程序,选择菜单"文件"中的"添加/删除管理单元"-> "添加",从"可用的 ...