日志服务 采集概述

日志服务(Cloud Log Service,CLS)支持通过 LogListener、API、SDK、Kafka 协议、OpenTelemetry 协议、云产品日志接入及数据导入等方式接入日志数据,适用于主机、容器、客户端、应用程序、消息队列、云产品及对象存储等多种数据源场景。

相关产品
日志服务 产品页,含版本规格、价格与购买入口。

一、功能特性

·采集方案

CLS 支持多种日志接入方式。你可以根据日志来源、现有采集链路及数据存储位置,选择对应的采集或数据导入方案。

数据源类型 日志来源 接入场景 相关文档
主机日志 Linux/Unix 主机文件日志 使用 LogListener 采集应用及系统文件日志,适用于腾讯云服务器、自建 IDC 及其他云厂商服务器。 LogListener 安装指南(Linux 版)
 Windows 主机文件日志 使用 LogListener Windows 版采集文本日志。 LogListener 安装指南(Windows 版)
 Windows 事件日志 使用 LogListener Windows 版采集 Application、System、Security 等事件通道日志。 采集 Windows 事件日志
 网络设备及服务器 Syslog 使用 LogListener 监听 TCP 或 UDP 端口,采集并解析 Syslog 日志。 采集 Syslog
容器日志 腾讯云 TKE 集群 采集容器标准输出、容器文件及节点文件日志,并关联 Pod、Namespace、Container 等元数据。 采集 TKE K8s 集群日志
 自建或其他云 Kubernetes 集群 在集群中部署 LogListener,采集容器标准输出及容器文件日志。 采集自建 K8s 集群日志
客户端日志 Android、iOS、HarmonyOS、Flutter 使用对应客户端 SDK 采集并上传应用日志。 使用 SDK 上传日志
 Web 页面、微信小程序 使用浏览器或小程序 JavaScript SDK 上传日志;免鉴权场景可使用匿名日志上传。 使用 SDK 上传日志匿名日志上传
应用日志 应用程序生成的结构化日志 使用 CLS SDK 或 API 将结构化日志直接上传至 CLS。 使用 SDK 上传日志使用 API 上传日志
 Java Logback、Log4j 日志 使用 Appender 直接上传日志,支持异步发送、缓存和失败重试。 使用 Logback Appender 上传日志使用 Log4j Appender 上传日志
 OpenTelemetry Log 使用标准 OTLP/HTTP Exporter 将日志上报至 CLS,无需引入 CLS 专属 SDK。 OpenTelemetry SDK 接入 CLS
开源采集组件 Filebeat、Winlogbeat、Logstash、Fluentd、Fluent Bit 修改现有组件的输出配置,通过 Kafka 协议将日志上传至 CLS。 使用 Kafka 协议上传日志
消息队列 应用使用 Kafka Producer 直接上报 将 CLS 配置为 Kafka Producer 的目标端,通过 Kafka 协议上传日志。 使用 Kafka 协议上传日志
 自建 Kafka 或腾讯云 CKafka 中的已有日志 由 CLS 主动订阅并消费指定 Kafka Topic,无需修改现有生产端。 使用 Kafka 数据订阅采集日志
专用数据源 Nginx 访问日志 使用预置 Nginx 采集及解析方案接入访问日志。 采集 Nginx 访问日志
 MySQL BinLog 使用 LogListener 采集 MySQL 二进制日志,适用于数据变更查询、分析及审计。 采集 MySQL BinLog
云产品日志 腾讯云产品日志 通过云产品控制台或 CLS 云产品日志接入能力完成原生接入。 采集云产品日志
数据导入 腾讯云 COS 将 COS 中的日志文件导入 CLS,支持一次性导入或持续分批导入。 导入 COS 数据
 AWS S3 将 AWS S3 存储桶中的日志文件导入 CLS。 通过 AWS S3 导入数据
 Elasticsearch 支持导入 Elasticsearch 中的历史数据,也支持持续导入新增数据。 从 Elasticsearch 导入数据

·日志结构化解析

日志的结构化指你的日志数据将以 key-value 的形式存储在 CLS 平台上。结构化后的日志数据可以根据指定的键值进行日志检索、日志分析及日志投递。日志服务允许直接上报结构化的数据,详见以下说明:

例如,一条本地原始日志为:

10.20.20.10;[Tue Jan 22 14:49:45 CST 2019 +0800];GET /online/sample HTTP/1.1;127.0.0.1;200;647;35;http://127.0.0.1/

指定日志的解析方式为分隔符方式,以;分号作为分隔符,可以将该条日志解析为多个字段组,每个字段组按 key-value 键值对的方式进行组织,为每个 key 定义一个键名称,如下所示:

IP: 10.20.20.10time: [Tue Jan 22 14:49:45 CST 2019 +0800]request: GET /online/sample HTTP/1.1host: 127.0.0.1status: 200length: 647bytes: 35referer: http://127.0.0.1/

LogListener 提供多种解析方式,如下表所示:

单行全文格式多行全文格式单行-完全正则格式多行-完全正则格式JSON 格式分隔符组合解析Nginx 日志模板单行全文日志是指一行日志内容为一条完整的日志。日志服务在采集的时候,将使用换行符 \\n 来作为一条日志的结束符。为了统一结构化管理,每条日志都会存在一个默认的键值__CONTENT__,但日志数据本身不再进行日志结构化处理,也不会提取日志字段,日志属性的时间项由日志采集的时间决定。假设一条日志原始数据为:Tue Jan 22 12:08:15 CST 2019 Installed: libjpeg-turbo-static-1.2.90-6.el7.x86_64采集到日志服务的数据为:__CONTENT__:Tue Jan 22 12:08:15 CST 2019 Installed: libjpeg-turbo-static-1.2.90-6.el7.x86_64多行全文日志是指一条完整的日志数据可能跨占多行(例如 Java stacktrace)。在这种情况下,以换行符 \\n 为日志的结束标识符就显得有些不合理,为了能让日志系统明确区分开每条日志,采用首行正则的方式进行匹配,当某行日志匹配上预先设置的正则表达式,就认为是一条日志的开头,而下一个行首出现作为该条日志的结束标识符。多行全文也会设置一个默认的键值__CONTENT__,但日志数据本身不再进行日志结构化处理,也不会提取日志字段,日志属性的时间项由日志采集的时间决定。假设一条多行日志原始数据为:2019-12-15 17:13:06,043 [main] ERROR com.test.logging.FooFactory:java.lang.NullPointerException at com.test.logging.FooFactory.createFoo(FooFactory.java:15) at com.test.logging.FooFactoryTest.test(FooFactoryTest.java:11)首行正则表达式为如下:\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2},\\d{3}\\s.+采集到日志服务的数据为:__CONTENT__:2019-12-15 17:13:06,043 [main] ERROR com.test.logging.FooFactory:\\njava.lang.NullPointerException\\n at com.test.logging.FooFactory.createFoo(FooFactory.java:15)\\n at com.test.logging.FooFactoryTest.test(FooFactoryTest.java:11)单行完全正则格式通常用来处理结构化的日志,指将一条完整日志按正则方式提取多个 key-value 的日志解析模式。假设一条日志原始数据为:10.135.46.111 – – [22/Jan/2019:19:19:30 +0800] "GET /my/course/1 HTTP/1.1" 127.0.0.1 200 782 9703 "http://127.0.0.1/course/explore?filter%5Btype%5D=all&filter%5Bprice%5D=all&filter%5BcurrentLevelId%5D=all&orderBy=studentNum" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0" 0.354 0.354配置的正则表达式为如下:(\\S+)[^\\[]+(\\[[^:]+:\\d+:\\d+:\\d+\\s\\S+)\\s"(\\w+)\\s(\\S+)\\s([^"]+)"\\s(\\S+)\\s(\\d+)\\s(\\d+)\\s(\\d+)\\s"([^"]+)"\\s"([^"]+)"\\s+(\\S+)\\s(\\S+).*采集到日志服务的数据为:body_bytes_sent: 9703http_host: 127.0.0.1http_protocol: HTTP/1.1http_referer: http://127.0.0.1/course/explore?filter%5Btype%5D=all&filter%5Bprice%5D=all&filter%5BcurrentLevelId%5D=all&orderBy=studentNumhttp_user_agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0remote_addr: 10.135.46.111request_length: 782request_method: GETrequest_time: 0.354request_url: /my/course/1status: 200time_local: [22/Jan/2019:19:19:30 +0800]upstream_response_time: 0.354假设你的一条日志原始数据为:[2018-10-01T10:30:01,000] [INFO] java.lang.Exception: exception happened at TestPrintStackTrace.f(TestPrintStackTrace.java:3) at TestPrintStackTrace.g(TestPrintStackTrace.java:7) at TestPrintStackTrace.main(TestPrintStackTrace.java:16)行首正则表达式为:\\[\\d+-\\d+-\\w+:\\d+:\\d+,\\d+]\\s\\[\\w+]\\s.*配置的自定义正则表达式为:\\[(\\d+-\\d+-\\w+:\\d+:\\d+,\\d+)\\]\\s\\[(\\w+)\\]\\s(.*)系统根据()捕获组提取对应的 key-value 后,你可以自定义每组的 key 名称如下所示:time: 2018-10-01T10:30:01,000level: INFOmsg: java.lang.Exception: exception happened at TestPrintStackTrace.f(TestPrintStackTrace.java:3) at TestPrintStackTrace.g(TestPrintStackTrace.java:7) at TestPrintStackTrace.main(TestPrintStackTrace.java:16)假设你的一条 JSON 日志原始数据为:{"remote_ip":"10.135.46.111","time_local":"22/Jan/2019:19:19:34 +0800","body_sent":23,"responsetime":0.232,"upstreamtime":"0.232","upstreamhost":"unix:/tmp/php-cgi.sock","http_host":"127.0.0.1","method":"POST","url":"/event/dispatch","request":"POST /event/dispatch HTTP/1.1","xff":"-","referer":"http://127.0.0.1/my/course/4","agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0","response_code":"200"}经过日志服务结构化处理后,该条日志将变为如下:agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0body_sent: 23http_host: 127.0.0.1method: POSTreferer: http://127.0.0.1/my/course/4remote_ip: 10.135.46.111request: POST /event/dispatch HTTP/1.1response_code: 200responsetime: 0.232time_local: 22/Jan/2019:19:19:34 +0800upstreamhost: unix:/tmp/php-cgi.sockupstreamtime: 0.232url: /event/dispatchxff: -假设你的一条日志原始数据为:10.20.20.10 – ::: [Tue Jan 22 14:49:45 CST 2019 +0800] ::: GET /online/sample HTTP/1.1 ::: 127.0.0.1 ::: 200 ::: 647 ::: 35 ::: http://127.0.0.1/当日志解析的分隔符指定为:::,该条日志会被分割成八个字段,并为这八个字段定义唯一的 key,如下所示:IP: 10.20.20.10 -bytes: 35host: 127.0.0.1length: 647referer: http://127.0.0.1/request: GET /online/sample HTTP/1.1status: 200time: [Tue Jan 22 14:49:45 CST 2019 +0800]假设你的一条日志的原始数据为:1571394459,http://127.0.0.1/my/course/4|10.135.46.111|200,status:DEAD,自定义插件内容如下:{ "processors": [ { "type": "processor_split_delimiter", "detail": { "Delimiter": ",", "ExtractKeys": [ "time", "msg1","msg2"] }, "processors": [ { "type": "processor_timeformat", "detail": { "KeepSource": true, "TimeFormat": "%s", "SourceKey": "time" } }, { "type": "processor_split_delimiter", "detail": { "KeepSource": false, "Delimiter": "|", "SourceKey": "msg1", "ExtractKeys": [ "submsg1","submsg2","submsg3"] }, "processors": [] }, { "type": "processor_split_key_value", "detail": { "KeepSource": false, "Delimiter": ":", "SourceKey": "msg2" } } ] } ]}经过日志服务结构化处理后,该条日志将变为如下:time: 1571394459submsg1: http://127.0.0.1/my/course/4submsg2: 10.135.46.111submsg3: 200status: DEAD假设你的一条日志的原始数据为:111.121.0.1 – – [06/Aug/2019:12:12:19 +0800] "GET /nginx-logo.png HTTP/1.1" 200 368 "http://119.x.x.x/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-"Nginx 日志配置内容如下:log_format main '$remote_addr – $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';经过 Nginx 日志配置处理后,生成如下正则表达式:(\\S+)\\s*-\\s*(\\S+)\\s*\\[(\\d+\\S+\\d+:\\d+:\\d+:\\d+)\\s+\\S+\\]\\s*\\"(\\S+)\\s+(\\S+)\\s+\\S+\\"\\s*(\\S+)\\s*(\\S+)\\s*\\"([^"]*)\\"\\s*\\"([^"]*)\\".*采集到日志服务的数据为:remote_addr: 111.121.0.1remote_user: -time_local: 06/Aug/2019:12:12:19request_method: GETrequest_uri: /nginx-logo.pngstatus: 200body_bytes_sent: 368http_referer: http://119.x.x.x/http_user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36

二、费用说明

日志采集会产生相关日志写入流量费用,更多信息,请你参见 计费概述。

三、规格限制

日志采集的规格限制,请你参见:

·LogListener 限制说明

·Kafka 数据订阅

·API/SDK 日志上传限制说明

·COS 数据导入规格限制

赞 (0)
上一篇 4天前
下一篇 4天前