本文主要介绍日志服务支持通过高精度时间戳(精确到纳秒)进行数据的全局排序,给您提供更加精准、可靠的时间顺序视图。
SLS 支持全局有序和高精度时间戳
当前 SLS 已经支持高精度时间戳功能,并且直接按照纳秒级别进行全局排序。
相比老的非高精度时间戳的版本,在以下 PB 格式 新增了一个可选的 Time_ns 字段, 在开启高精度时间戳功能的时候,用来存放 日志时间里面的纳秒部分 。之所以新增一个字段,而没有修改 Time 字段的类型主要是为了兼容历史数据。
SLS 会基于 Time 和 Time_ns 组合出来的纳秒时间全局排序,控制台序查询结果如下图所示:
基本原理
日志写入 SLS 的时候可能会落在不同的 Shard 里面,在查询的时候根据查询条件和查询时间范围,通过倒排索引和写入过程中存放的高精度时间信息来将各个 shard 内部满足条件的 log 过滤出来并返回给中间节点做进一步的全局排序处理,中间节点处理后再返回。
-
写入
-
查询
注意事项
-
Logtail
Logtail1.8 及以上版本支持
如何开启全局有序和纳秒高精度时间戳
从有序业务场景章节我们了解了全局有序对业务的重要性,您使用该功能,需要从数据写入和查询两方面入手,其中数据写入主要有两类途径:Logtail 和 SDK。
数据写入
-
Logtail
Logtail 可以帮助您无侵入式从服务器或容器中采集文件和标准输出日志,Logtail 1.8 及以上版本支持纳秒高精度时间戳。 具体操作,请参见 日志采集支持纳秒精度时间戳 。 如何安装和升级 Logtail,请参见 安装 Logtail(Linux 系统) 。
-
安装命令
./logtail.sh install {region} -
升级命令
./logtail.sh upgrade以上命令都可以使用-v 参数指定版本,如
./logtail.sh upgrade -v 1.8.7
-
-
SDK
当前 GO SDK、C++ SDK、Java SDK、Python SDK 支持纳秒时间的日志,其他语言的 SDK,请提交 工单 。
下述代码示例为写入带有纳秒时间的日志。您可以根据具体业务需要,解析日志中正确的纳秒时间部分传入。在查询时,使用秒和纳秒两者拼接的时间进行全局排序。
Python
重要Python SDK 支持纳秒高精度,目前发布在 pyPI 官方源,如果在国内用
pip install -U aliyun-log-python-sdk没有拉取到纳秒版本,可以用pip install -U aliyun-log-python-sdk==0.8.11获取。def put_log_with_nano(): logitemList = [] for i in range(30): contents = [ ('DeviceIP', 11.22.xx.xx) logItem = LogItem() nano_time = time.time_ns() sec_time = int(nano_time / 1000000000); nano_time_part = nano_time % 1000000000; logItem.set_time(sec_time) logItem.set_time_nano_part(nano_time_part) logItem.set_contents(contents) logitemList.append(logItem) request = PutLogsRequest(_project, _logstore, logitems=logitemList) res = client.put_logs(request) res.log_print()Java
重要建议您获取日志服务 Java SDK 的最新版本进行调试,避免报错。日志服务 Java SDK 版本请参见 Aliyun Log Java SDK 。
package com.aliyun.openservices.log; import com.aliyun.openservices.log.common.LogItem; import com.aliyun.openservices.log.exception.LogException; import java.util.ArrayList; import java.util.List; public class ClientDemo { public static void main(String[] args) { Client client = new Client("cn-hangzhou.log.aliyuncs.com", "accessKeyId", "accessKeySecret"); List<LogItem> logItems = new ArrayList<LogItem>(); for (int i = 0; i < 10; i++) { LogItem logItem = new LogItem(); // set time in second logItem.SetTime((int)(System.currentTimeMillis() / 1000)); // set nano time logItem.SetTimeNsPart((int)(System.nanoTime() % 1000000000)); logItem.PushBack("hello", "world"); logItem.PushBack("test", "sls"); logItems.add(logItem); client.PutLogs("test-project", "test-logstore", "test-topic", logItems, "127.0.0.1"); }catch(LogException e) e.printStackTrace(); }Go
import ( "time" sls "github.com/aliyun/aliyun-log-go-sdk" "github.com/golang/protobuf/proto" func main() { client := sls.CreateNormalInterface("cn-hangzhou.log.aliyuncs.com", "accessKeyId", "accessKeySecret", "") lg := &sls.LogGroup{ Logs: []*sls.Log{ // time in seconds Time: proto.Uint32(uint32(time.Now().Unix())), // nano time TimeNs: proto.Uint32(uint32(time.Now().UnixNano() % 1e9)), Contents: []*sls.LogContent{ Key: proto.String("hello"), Value: proto.String("world"), Key: proto.String("test"), Value: proto.String("sls"), err := client.PutLogs("test-project", "test-logstore", lg) if err != nil { panic(err)
数据查询
-
控制台
SLS 控制台,会根据高精度的时间信息,自动进行显示优化,显示成毫秒、微秒、纳秒的形式。
-
微秒形式
-
纳秒形式
-
-
SDK
以
Python 为例, 捞取
[1696743635 s, 1696743635 s +10 ns)
区间内满足
myQuery
查询条件的最多
100
行
log,并以逆序输出返回结果。
新增参数说明:
-
accurate_query 设置为 true 默认走精确查询, 在设置为 false 情况下,只能保证分钟级别有序。
-
from_time_nano_part 和 to_time_nano_part 会分别和 fromTime、toTime 组合成 nano 时间范围去 SLS 查询,SLS 会过滤出在这段纳秒时间范围内的满足查询条件的 log,并以纳秒时间戳粒度有序输出。
def query_log_with_nano(): query = "LEVEL:ERROR" req = GetLogsRequest(_project, _logstore, fromTime=1696743635, toTime=1696743635, query=query, line=100, reverse=True, accurate_query=True, from_time_nano_part=0, to_time_nano_part = 10) res = client.get_logs(req) res.log_print()