通过在 Logtail 采集配置中开启纳秒精度支持并配置时间解析插件,可以采集和存储毫秒、微秒、纳秒级的高精度时间戳。采集后的时间将拆分为秒级时间戳 __time__ 和纳秒偏移量 __time_ns_part__ 两个字段进行存储,以实现高精度的日志排序与分析。
业务场景说明
在分布式追踪、高频交易、性能剖析或对日志严格保序等场景中,秒级的时间精度无法满足业务需求。这些场景的业务日志中通常会记录毫秒、微秒甚至纳秒级的时间戳。本方案旨在指导如何配置 Logtail,以完整地采集、存储和分析这些高精度时间信息,确保日志分析的准确性和时序性。
方案架构
LoongCollector(Logtail)采集纳秒精度时间戳的核心机制是在标准秒级时间戳之外,额外存储一个纳秒级的偏移量。此设计旨在兼容现有以秒为单位的时间系统,同时提供高精度排序能力。
核心工作流程如下:
-
开启纳秒支持:在 Logtail 采集配置的高级参数中,通过
{ "EnableTimestampNanosecond": true }激活高精度时间处理能力。此功能仅适用于 Logtail 1.8.0 及以上版本的 Linux 环境。 -
日志解析:使用分隔符、JSON 或正则表达式等插件从原始日志中提取包含高精度时间戳的字符串。
-
时间转换:时间解析插件将时间字符串转换为标准时间格式。
-
时间存储:日志服务将时间拆分为两个字段进行存储:
-
__time__:标准的 Unix 时间戳(长整型),单位为秒。 -
__time_ns_part__:纳秒部分(长整型),取值范围为 0 到 999,999,999。
-
-
查询与分析:在查询分析时,通过对
__time__和__time_ns_part__两个字段组合排序,可以实现严格的日志时序分析。
实施步骤
本节将以一个包含纳秒级时间戳的JSON 日志为例,提供一个从日志采集、解析、索引配置到最终查询分析的完整端到端操作流程。
步骤一:创建Project和LogStore
采集日志前,需规划并创建用于管理与存储日志的Project和LogStore。
-
Project:日志服务的资源管理单元,用于隔离和管理不同项目或业务的日志。
-
LogStore:日志存储单元,用于存储日志。
如果已提前创建,可跳过本步骤,直接进入配置机器组(安装LoongCollector)。
-
登录日志服务控制台。
-
单击创建Project,并配置:
-
所属地域:根据日志来源选择,创建后不可修改。
-
Project名称:阿里云内全局唯一,创建后不可修改。
-
其他配置保持默认,单击创建。如需了解其他参数,请参见管理Project。
-
-
单击Project名称,进入目标Project。
-
在左侧导航栏,选择
,单击+。 -
在创建LogStore页面,完成以下核心配置:
-
Logstore名称:设置一个在Project内唯一的名称,创建后不可修改。
-
Logstore类型:根据规格对比选择标准型或查询型。
-
计费模式:
-
按使用功能计费:按存储、索引、读写次数等各项资源独立计,适合小规模或功能使用不确定的场景。
-
按写入数据量计费:仅按原始写入数据量计费,并提供30天的免费存储周期及免费的数据加工、投递等功能。成本模型简单,适合存储周期接近30天或数据处理链路复杂的场景。
-
-
数据保存时间:设置日志的保留天数,取值范围为1~3650天(3650天表示永久保存)。默认为30天。
-
其他配置保持默认,单击确定。如需了解其他参数,请参考管理LogStore。
-
步骤二: 配置机器组(安装LoongCollector)
在成功创建Project和LogStore后,为服务器安装LoongCollector并将其加入机器组。本文以ECS实例安装LoongCollector(ECS与日志服务Project属于同一阿里云账号和地域)为例,若ECS实例与Project不属于同一账号或地域,或为自建服务器请参考安装采集器手动安装。
此功能仅支持 Linux 系统的LoongCollector( Logtail),在 Windows 系统上配置不生效,Logtail版本为1.8.0及以上。
|
单击目标Project,在日志库(LogStore)
所有文本日志接入模板仅在解析插件上有所差异,其余配置流程一致,后续均可修改。 |
|
配置步骤:
-
在机器组配置页面,配置如下参数:
-
使用场景:主机场景
-
安装环境:ECS
-
-
配置机器组:根据目标服务器的LoongCollector安装情况与机器组配置状态,选择对应操作:
-
已安装LoongCollector且已加入某个机器组,可直接在源机器组列表中勾选,将其添加至应用机器组列表,无需重复创建。
-
未安装LoongCollector,单击创建机器组:
以下步骤将引导您完成LoongCollector的自动安装并创建新机器组。
-
系统会自动列出与 Project 同地域的 ECS 实例,勾选需要采集日志的一台或多台实例。
-
单击安装并创建为机器组,系统将自动在所选ECS实例上安装LoongCollector。
-
配置机器组名称并单击确定。
说明如果安装失败或一直处于等待中,请检查ECS地域是否与Project相同。
-
-
如需将已安装LoongCollector的服务器加入已有机器组,请参考常见问题如何将服务器加入到已有机器组?
-
步骤三:创建采集配置
通过控制台配置
完成LoongCollector安装和机器组配置后,进入Logtail配置页面,开始定义日志采集和处理规则。
1. 开启纳秒精度支持
定义日志的采集源、采集规则,并开启纳秒精度支持。
全局配置:
-
配置名称:设置一个在Project内唯一的名称。创建成功后,无法修改。
-
:开启高级参数开关,并输入以下 JSON 内容以开启纳秒精度支持:
{ "EnableTimestampNanosecond": true }
输入配置:
-
类型:文本日志采集。
-
文件路径:日志采集的路径。
-
Linux:以“/”开头,如
/data/mylogs/**/*.log,表示/data/mylogs目录下所有后缀名为.Log的文件。 -
Windows:以盘符开头,如
C:\Program Files\Intel\**\*.Log。
-
-
最大目录监控深度:文件路径中通配符
**匹配的最大目录深度。默认为0(仅监控本层目录)。
2. 配置处理插件
由于源日志为 JSON 格式,在处理配置区域,添加JSON解析插件,从原始日志中分离出包含纳秒时间戳的字符串,并将其存为一个独立的字段。
-
添加日志样例
假设日志文件中的日志格式如下,其中
asctime字段包含了纳秒精度的时间戳。{ "asctime": "2023-10-25 23:51:10,199999999", "filename": "generate_data.py", "levelname": "INFO", "lineno": 51, "module": "generate_data", "message": "{\"no\": 14, \"inner_loop\": 166, \"loop\": 27451, \"uuid\": \"9be98c29-22c7-40a1-b7ed-29ae6c8367af\"}", "threadName": "MainThread" } -
添加JSON解析插件
单击添加处理插件,选择,单击确认。
-
添加时间解析插件
将上一步提取的时间字符串(
asctime字段)转换为标准的纳秒时间戳,并将其作为该条日志的事件时间。插件名称
核心功能
适用场景
时间解析
基础时间解析
简单场景,格式固定。
提取日志时间 (strptime时间格式)
灵活,支持丰富的
strptime格式推荐使用。功能全面,与业界标准兼容。
提取日志时间 (Go语言时间格式)
使用 Go 语言标准库格式
熟悉 Go 语言或日志格式与 Go 标准库匹配的场景。
时间解析
单击添加处理插件,选择,进行如下配置:
-
原始字段:解析日志前,用于存放时间的原始字段,本示例为
asctime。 -
时间格式:根据日志的时间字段内容设置对应的时间格式,本示例为
%Y-%m-%d %H:%M:%S,%f。其中%f为秒的小数部分,精度最高支持为纳秒。时间格式字符串必须与原始日志中的时间格式(包括秒和纳秒之间的分隔符,如
,或.)完全一致,否则无法正确解析。 -
时区:选择日志时间字段所在的时区,默认使用机器时区。
提取日志时间(strptime时间格式)
单击添加处理插件,选择,进行如下配置:
-
原始字段:解析日志前,用于存放时间的原始字段,本示例为
asctime。 -
原始时间格式:根据日志的时间字段内容设置对应的时间格式,本示例为
%Y-%m-%d %H:%M:%S,%f。其中%f为秒的小数部分,精度最高支持为纳秒。时间格式字符串必须与原始日志中的时间格式(包括秒和纳秒之间的分隔符,如
,或.)完全一致,否则无法正确解析。
提取日志时间(Go语言时间格式)
单击添加处理插件,选择,进行如下配置:
-
原始时间字段:解析日志前,用于存放时间的原始字段,本示例为
asctime。 -
原始时间格式:根据原始日志的时间字段设置对应的时间格式,需要按照Golang的时间格式规范来编写。格式化时间模板为Go语言的诞生时间
2006-01-02 15:04:05 -0700 MST。本示例对应的时间格式为2006-01-02 15:04:05,999999999。时间格式字符串必须与原始日志中的时间格式(包括秒和纳秒之间的分隔符,如
,或.)完全一致,否则无法正确解析。 -
结果时间字段:解析日志后,用于存放时间的目标字段,本示例为
result_asctime。 -
结果时间格式:解析日志后的时间格式,按照Golang的时间格式规范编写。本示例为
2006-01-02 15:04:05,999999999Z07:00。
-
3. 配置索引
完成Logtail配置后,单击下一步。进入查询分析配置页面:
配置完成后,单击下一步,完成整个采集流程的设置。
通过CRD配置(Kubernetes 场景)
在 ACK 或自建 Kubernetes 集群中,可以通过 AliyunLog CRD 来配置纳秒精度时间戳的采集。以下是三种不同插件的配置样例。
时间解析
apiVersion: telemetry.alibabacloud.com/v1alpha1
kind: ClusterAliyunPipelineConfig
metadata:
name: ${your-config-name}
spec:
config:
aggregators: []
global:
EnableTimestampNanosecond: true
inputs:
- Type: input_file
FilePaths:
- /test/sls/json_nano.log
MaxDirSearchDepth: 0
FileEncoding: utf8
EnableContainerDiscovery: true
processors:
- Type: processor_parse_json_native
SourceKey: content
- Type: processor_parse_timestamp_native
SourceKey: asctime
SourceFormat: '%Y-%m-%d %H:%M:%S,%f'
flushers:
- Type: flusher_sls
Logstore: ${your-logstore-name}
sample: |-
{
"asctime": "2025-11-03 15:39:14,229939478",
"filename": "log_generator.sh",
"levelname": "INFO",
"lineno": 204,
"module": "log_generator",
"message": "{"no": 45, "inner_loop": 15, "loop": 1697, "uuid": "80366fca-a57d-b65a-be07-2ac1173505d9"}",
"threadName": "MainThread"
}
project:
name: ${your-project-name}
logstores:
- name: ${your-logstore-name}
提取日志时间(strptime时间格式)
apiVersion: telemetry.alibabacloud.com/v1alpha1
kind: ClusterAliyunPipelineConfig
metadata:
name: ${your-config-name}
spec:
config:
aggregators: []
global:
EnableTimestampNanosecond: true
inputs:
- Type: input_file
FilePaths:
- /test/sls/json_nano.log
MaxDirSearchDepth: 0
FileEncoding: utf8
EnableContainerDiscovery: true
processors:
- Type: processor_parse_json_native
SourceKey: content
- Type: processor_strptime
SourceKey: asctime
Format: '%Y-%m-%d %H:%M:%S,%f'
KeepSource: true
AlarmIfFail: true
AdjustUTCOffset: false
flushers:
- Type: flusher_sls
Logstore: ${your-logstore-name}
sample: |-
{
"asctime": "2025-11-03 15:39:14,229939478",
"filename": "log_generator.sh",
"levelname": "INFO",
"lineno": 204,
"module": "log_generator",
"message": "{"no": 45, "inner_loop": 15, "loop": 1697, "uuid": "80366fca-a57d-b65a-be07-2ac1173505d9"}",
"threadName": "MainThread"
}
project:
name: ${your-project-name}
logstores:
- name: ${your-logstore-name}
提取日志时间(Go语言时间格式)
apiVersion: telemetry.alibabacloud.com/v1alpha1
kind: ClusterAliyunPipelineConfig
metadata:
name: ${your-config-name}
spec:
config:
aggregators: []
global:
EnableTimestampNanosecond: true
inputs:
- Type: input_file
FilePaths:
- /test/sls/json_nano.log
MaxDirSearchDepth: 0
FileEncoding: utf8
EnableContainerDiscovery: true
processors:
- Type: processor_parse_json_native
SourceKey: content
- Type: processor_gotime
SourceKey: asctime
SourceFormat: '2006-01-02 15:04:05,999999999'
DestKey: result_asctime
DestFormat: '2006-01-02 15:04:05,999999999Z07:00'
SetTime: true
KeepSource: true
NoKeyError: true
AlarmIfFail: true
flushers:
- Type: flusher_sls
Logstore: ${your-logstore-name}
sample: |-
{
"asctime": "2025-11-03 15:39:14,229939478",
"filename": "log_generator.sh",
"levelname": "INFO",
"lineno": 204,
"module": "log_generator",
"message": "{"no": 45, "inner_loop": 15, "loop": 1697, "uuid": "80366fca-a57d-b65a-be07-2ac1173505d9"}",
"threadName": "MainThread"
}
project:
name: ${your-project-name}
logstores:
- name: ${your-logstore-name}
步骤四:结果验证
配置完成后,等待片刻,新的日志数据将被采集到LogStore中。
在日志服务的查询分析页面,查看采集日志,控制台会根据高精度的时间信息,自动进行显示优化,显示成毫秒、微秒、纳秒的形式。

常见问题
采集日志无法正常解析纳秒时间戳
配置采集后,发现高精度时间并未正常提取。

-
错误原因
插件模式支持%f,但是时间格式需要与源时间内容保持一致。
-
解决方法
-
登录LoongCollector(Logtail)机器,查看日志,发现大量STRPTIME_PARSE_ALARM异常日志。
tail -f /usr/local/ilogtail/logtail_plugin.LOG 2023-10-26 00:30:39 [WRN] [strptime.go:164] [processLog] [##1.0##xxxx,xxx] AlarmType:STRPTIME_PARSE_ALARM strptime(2023-10-26 00:30:10,199999999, %Y-%m-%d %H:%M:%S %f) failed: 0001-01-01 00:00:00 +0000 UTC, <nil> -
修改插件日志解析格式。
原始日志时间为
2023-10-26 00:30:10,199999999,秒与高精度时间(这里是毫秒)之间分隔符为半角逗号(,),解析格式为%Y-%m-%d %H:%M:%S %f,秒与高精度时间之间分隔符为空格 。修改采集配置中时间转换格式为%Y-%m-%d %H:%M:%S,%f即可。
-
成本与限制说明
-
成本影响:
__time_ns_part__字段会作为日志内容的一部分被存储,略微增加原始日志的存储量。 -
环境限制:此功能仅支持 Linux 系统的 Logtail 1.8.0 及以上版本,在 Windows 系统上配置不生效。
相关文档
附录一:常见日志时间格式
Linux服务器中,Logtail支持strftime函数提供的所有时间格式。即能被strftime函数格式化的日志时间字符串都能被Logtail解析并使用。
|
时间格式 |
说明 |
示例 |
|
%a |
星期的缩写。 |
Fri |
|
%A |
星期的全称。 |
Friday |
|
%b |
月份的缩写。 |
Jan |
|
%B |
月份的全称。 |
January |
|
%d |
每月第几天,十进制,范围为01~31。 |
07, 31 |
|
%f |
秒的小数部分(毫秒、微秒或纳秒) |
123 |
|
%h |
月份的缩写,等同于%b。 |
Jan |
|
%H |
小时,24小时制。 |
22 |
|
%I |
小时,12小时制。 |
11 |
|
%m |
月份,十进制,范围为01~12。 |
08 |
|
%M |
分钟,十进制,范围为00~59。 |
59 |
|
%n |
换行符。 |
换行符 |
|
%p |
AM或PM。 |
AM、PM |
|
%r |
12小时制的时间组合,等同于%I:%M:%S %p。 |
11:59:59 AM |
|
%R |
小时和分钟组合,等同于%H:%M。 |
23:59 |
|
%S |
秒数,十进制,范围为00~59。 |
59 |
|
%t |
Tab符号,制表符。 |
无 |
|
%y |
年份,十进制,不带世纪,范围为00~99。 |
04、98 |
|
%Y |
年份,十进制。 |
2004、1998 |
|
%C |
世纪,十进制,范围为00~99。 |
16 |
|
%e |
每月第几天,十进制,范围为1~31。 如果是个位数字,前面需要加空格。 |
7、31 |
|
%j |
一年中的天数,十进制,范围为001~366。 |
365 |
|
%u |
星期几,十进制,范围为1~7,1表示周一。 |
2 |
|
%U |
每年的第几周,星期天是一周的开始,范围为00~53。 |
23 |
|
%V |
每年的第几周,星期一是一周的开始,范围为01~53。 如果一月份刚开始的一周>=4天,则认为是第1周,否则认为下一个星期是第1周。 |
24 |
|
%w |
星期几,十进制,范围为0~6,0代表周日。 |
5 |
|
%W |
每年的第几周,星期一是一周的开始,范围为00~53。 |
23 |
|
%c |
标准的日期和时间。 |
Tue Nov 20 14:12:58 2020 |
|
%x |
标准的日期,不带时间。 |
Tue Nov 20 2020 |
|
%X |
标准的时间,不带日期。 |
11:59:59 |
|
%s |
Unix时间戳。 |
1476187251 |
时间格式示例
常见的时间标准、示例及对应的时间表达式如下所示。
|
示例 |
时间表达式 |
时间标准 |
|
2017-12-11 15:05:07 |
%Y-%m-%d %H:%M:%S |
自定义 |
|
[2017-12-11 15:05:07.012] |
[%Y-%m-%d %H:%M:%S |
自定义 |
|
2017-12-11 15:05:07.123 |
%Y-%m-%d %H:%M:%S.%f |
自定义 |
|
02 Jan 06 15:04 MST |
%d %b %y %H:%M |
RFC822 |
|
02 Jan 06 15:04 -0700 |
%d %b %y %H:%M |
RFC822Z |
|
Monday, 02-Jan-06 15:04:05 MST |
%A, %d-%b-%y %H:%M:%S |
RFC850 |
|
Mon, 02 Jan 2006 15:04:05 MST |
%A, %d %b %Y %H:%M:%S |
RFC1123 |
|
2006-01-02T15:04:05Z07:00 |
%Y-%m-%dT%H:%M:%S |
RFC3339 |
|
2006-01-02T15:04:05.999999999Z07:00 |
%Y-%m-%dT%H:%M:%S |
RFC3339Nano |
|
1637843406 |
%s |
自定义 |
|
1637843406123 |
%s |
自定义(日志服务以秒级精度处理) |
附录二:Golang时间格式
以下为Golang官方的时间格式示例:
const (
Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
ANSIC = "Mon Jan _2 15:04:05 2006"
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"// Handy time stamps.
Stamp = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano = "Jan _2 15:04:05.000000000"
)
