Store是日志服务中日志数据的采集、存储和查询单元。针对不同的数据类型,日志服务提供日志库(Logstore)、时序库(MetricStore)和事件库(EventStore),本文介绍不同Store的基本概念。
日志库(Logstore)
每个Logstore隶属于一个Project,每个Project中可创建多个Logstore。例如您可以创建一个名为app-a
的Project,并在该Project下创建名为operation_log
、application_log
和access_log
的Logstore,分别存储App A所涉及的操作日志、应用程序日志和访问日志。
您在执行写入日志、查询和分析日志、加工日志、消费日志、投递日志等操作时,都需要指定Logstore。具体说明如下:
以Logstore为采集单元,采集日志。
以Logstore为存储单元,存储日志以及执行加工、消费、投递等操作。
在Logstore中建立索引,用于查询和分析日志。
日志(Log)格式
文本日志(LogFile)、事件(Event)、数据库日志(BinLog)、时序数据(Metric)等数据都是日志的不同载体。日志服务采用半结构化的数据模式定义一条日志,包含日志主题、日志时间、日志内容、日志来源和日志标签五个数据域。日志服务对各个数据域的格式要求不同,详细说明如下表所示。
数据域 | 说明 | 格式 |
日志主题 | 日志服务保留字段( | 包括空字符串在内的任意字符串,大小为0~128字节。 该字段值为空字符串时,表示未设置日志主题。 |
日志时间 | 日志服务保留字段( | Unix时间戳。 |
日志内容 | 日志的具体内容,由一个或多个内容项组成,内容项为 您通过Logtail极简模式(单行或多行)采集日志时,Logtail不会对日志内容进行解析。整条原始日志将被上传到content字段中。 |
|
日志来源 | 日志服务保留字段( | 任意字符串,大小为0~128字节。 |
日志标签 | 日志标签。包括:
| 字典格式,Key和Value均为字符串类型。在日志中以__tag__:为前缀进行展示。 |
日志主题(Topic)
Topic可用于区分不同服务、用户或实例产生的日志。例如,系统A包含前端HTTP请求处理、缓存、逻辑处理、存储等模块时,可分别为其日志设置Topic(如http_module、cache_module、logic_module、store_module)。日志采集至同一Logstore后,可通过Topic快速区分来源。日志主题(Topic)需在采集配置的全局配置中设置。
如果不需要区分Logstore中的日志,则在采集日志时设置Topic为空-不生成Topic即可。空字符串是一个有效的Topic,即Topic的值为空字符串。
Logstore、Topic、Shard之间的关系如下:
日志组(LogGroup)
日志组(LogGroup)是一组日志的集合,是写入与读取日志的基本单元。一个日志组中的数据包含相同Meta(IP地址、Source等信息)。写入日志到日志服务或从日志服务读取日志时,多条日志被打包为一个日志组,以日志组为单元进行写入与读取。该方式可减少读写次数,提高业务效率。每个日志组最大长度为5 MB。
日志服务的基本数据模型请参见Logstore数据模型。
示例
以下以一条网站访问日志为例,说明原始日志与日志服务中数据模型的映射关系。
原始日志
127.0.0.1 - - [01/Mar/2021:12:36:49 0800] "GET /index.html HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
通过极简模式采集到日志服务后的日志
整条原始日志将被上传到content字段中。
通过完整正则模式采集到日志服务后的日志
Logtail将日志内容结构化,即根据您所设置的正则表达式将日志内容提取为多个键值对。
时序库(MetricStore)
每个MetricStore隶属于一个Project,每个Project中可创建多个MetricStore。例如您可以创建一个名为demo-monitor
的Project,然后在该Project下创建名为host-metrics
、cloud-service-metrics
和app-metrics
的MetricStore,用于分类存储基础主机监控数据、云服务监控数据和业务应用监控数据。
您在执行写入、查询和分析、消费时序数据时,都需要指定MetricStore。具体说明如下:
以MetricStore为采集单元,采集时序数据。
以MetricStore为存储单元,存储时序数据以及执行消费操作。
查询和分析时序数据,支持PromQL语法、SQL92语法和SQL+PromQL语法。
时序数据(Metric)
时序数据由时序标识和数据点组成,相同时序标识的数据组成时间线。
时序标识
每条时间线都有一个唯一的时序标识,由Metric name和Labels组成。
Metric name是一个字符串类型的标识符,用于标识指标类型。Metric name需遵循正则表达式[a-zA-Z_:][a-zA-Z0-9_:]* 。例如http_request_total表示接收到的HTTP请求的总数。
Labels由一组组键值对组成,各组键值对之间使用竖线(|)分割,用于标识指标的相关属性。Key需遵循正则表达式 [a-zA-Z_][a-zA-Z0-9_]* ,Value不能包含竖线( | ),其它不做限制。例如method为POST, URL为/api/v1/get 。
数据点
数据点代表时间线在具体某个时间点的值,每个数据点由时间戳和值组成。其中时间戳精度为纳秒,值的类型为double。
数据结构
日志服务的时序数据类型遵循Prometheus的定义规范,在时序库中所有的数据都按照时序类型存储。时序数据的写入协议和日志写入协议一致,使用Protobuf的数据编码方式。时序标识和数据点都在content字段中,具体表示方式如下所示。
字段 | 说明 | 示例 |
__name__ | Metric名称。 | nginx_ingress_controller_response_size |
__labels__ | Label信息,格式为 说明
| app#$#ingress-nginx|controller_class#$#nginx|controller_namespace#$#kube-system|controller_pod#$#nginx-ingress-controller-589877c6b7-hw9cj |
__time_nano__ | 时间戳,单位为纳秒。 | 1585727297293000000 |
__value__ | 值。 | 36.0 |
示例
查询process_resident_memory_bytes指标在指定时间区间内的所有原始时序数据。
* | select * from "sls-mall-k8s-metrics.prom" where __name__ = 'process_resident_memory_bytes' limit all
事件库(EventStore)
每个EventStore隶属于一个Project,每个Project中可创建多个EventStore。您可以根据实际需求为某个项目创建多个EventStore,一般是为不同类型的事件数据创建不同的EventStore。例如您可以根据基础设施异常事件、业务应用事件、自定义事件等进行分类,通过不同的EventStore来进行存储和分析。
您在执行写入、查询和分析、消费事件数据时,都需要指定EventStore。具体说明如下:
以EventStore为采集单元,采集事件数据。
以EventStore为存储单元,存储事件数据以及执行消费操作。
事件数据(Event)格式
日志服务的事件数据遵循CloudEvents协议规范,具体说明如下表所示。
字段类型 | 字段名 | 是否必选 | 数据格式 | 说明 |
协议字段 |
| 是 | String | 根据CloudEvents协议规范,默认使用 |
| 是 | String | 事件ID,您可以根据 | |
| 是 | String | 通常用来标识事件发生的上下文信息,例如事件来源、发布事件的实例等。 | |
| 是 | String | 事件类型,例如 | |
| 否 | String | 事件主题,是对 | |
| 否 | String | 事件类型,默认取值为 | |
| 否 | URI |
| |
| 否 | JSON | 具体的事件内容。不同来源和类型的事件格式会有差异。 | |
| 是 | Timestamp | 事件时间,具体格式,请参见RFC 3339。例如 | |
扩展字段 |
| 是 | String | 事件标题。 |
| 是 | String | 事件描述。 | |
| 是 | String | 事件状态。取值:
|
示例
例如一个告警事件,示例数据如下:
{
"specversion": "1.0",
"id": "af****6c",
"source": "acs:sls",
"type": "sls.alert",
"subject": "https://sls.console.aliyun.com/lognext/project/demo-alert-chengdu/logsearch/nginx-access-log?encode=base64&endTime=1684312259&queryString=c3RhdHVzID49IDQwMCB8IHNlbGVjdCByZXF1ZXN0X21ldGhvZCwgY291bnQoKikgYXMgY250IGdyb3VwIGJ5IHJlcXVlc3RfbWV0aG9kIA%3D%3D&queryTimeType=99&startTime=1684311959",
"datacontenttype": "application/cloudevents+json",
"data": {
"aliuid": "16****50",
"region": "cn-chengdu",
"project": "demo-alert-chengdu",
"alert_id": "alert-16****96-247190",
"alert_name": "Nginx访问错误",
"alert_instance_id": "77****e4-1aad9f7",
"alert_type": "sls_alert",
"next_eval_interval": 300,
"fire_time": 1684299959,
"alert_time": 1684312259,
"resolve_time": 0,
"status": "firing",
"severity": 10,
"labels": {
"request_method": "GET"
},
"annotations": {
"__count__": "1",
"cnt": "49",
"desc": "Nginx最近五分钟内GET请求错误49次",
"title": "Nginx访问错误告警触发"
},
"results": [
{
"region": "cn-chengdu",
"project": "demo-alert-chengdu",
"store": "nginx-access-log",
"store_type": "log",
"role_arn": "",
"query": "status >= 400 | select request_method, count(*) as cnt group by request_method ",
"start_time": 1684311959,
"end_time": 1684312259,
"fire_result": {
"cnt": "49",
"request_method": "GET"
},
"raw_results": [
{
"cnt": "49",
"request_method": "GET"
},
{
"cnt": "3",
"request_method": "DELETE"
},
{
"cnt": "7",
"request_method": "POST"
},
{
"cnt": "6",
"request_method": "PUT"
}
],
"raw_result_count": 4,
"truncated": false,
"dashboard_id": "",
"chart_title": "",
"is_complete": true,
"power_sql_mode": "auto"
}
],
"fire_results": [
{
"cnt": "49",
"request_method": "GET"
}
],
"fire_results_count": 1,
"condition": "Count:[1] > 0; Condition:[49] > 20",
"raw_condition": "Count:__count__ > 0; Condition:cnt > 20"
},
"time": "2023-05-17T08:30:59Z",
"title": "Nginx访问错误告警触发",
"message": "Nginx最近五分钟内GET请求错误49次",
"status": "error"
}