EdgeOne Logo
Documentation
请选择
请选择
Overview
Menu

推送实时日志

本文档将指引您如何将日志推送到指定的服务内。

步骤1:选择日志源

1. 登录 边缘安全加速平台控制台,在左侧菜单栏中,单击站点列表,在站点列表内单击需配置的站点,进入站点详情页面。
2. 在站点详情页面,单击日志服务 > 实时日志。
3. 在实时日志页面,单击新建推送任务。
4. 在选择日志源页面,选择需要推送的日志源信息,配置相关参数,单击下一步

日志类型:可选站点加速日志、四层代理日志、速率限制和 CC 攻击防护日志、Web 攻击防护日志、自定义规则日志、Bot 管理日志;
服务区域:选择需要推送的日志区域,EdgeOne 实时日志推送任务可分别推送「中国大陆可用区」或「全球可用区(不包括中国大陆)」的日志,但无法直接推送「全球可用区」的日志。如果您需要推送「全球可用区」的日志,请建立两个推送任务,一个针对「中国大陆可用区」,另一个针对「全球可用区(不包括中国大陆)」。
域名:选择需要推送日志的子域名或四层实例。同一份日志不支持配置多个推送任务,即相同地域下子域名/四层代理实例的日志仅支持配置一个推送任务,例如:www.example.com 的「中国大陆可用区」站点加速日志配置了日志推送任务 A,此时日志推送任务 B 无法选择到 www.example.com

步骤2:选择日志字段

1. 在选择日志字段中,配置需要推送的字段内容,您可以在字段列表中,通过勾选进行选择;相关字段说明请参考:实时日志字段说明
说明:
目前仅 站点加速日志四层代理日志 支持自定义选择需要推送的日志。

2. (可选)如果您需要推送 HTTP 请求头,HTTP 响应头或 Cookie 中的某些元素记录以进行分析时,您可以点击添加自定义字段,配置需要推送的 HTTP 请求头、HTTP 响应头或 Cookie 名称。您可以通过键值对形式将此类信息精确记录在日志中。以 Accept-Language 头为例,其对应的信息可以直接通过日志中的 Accept-Language 字段获取。
说明:
1. 字段默认区分大小写,因此需要与原始字段完成匹配;
2. 目前仅站点加速日志支持添加自定义字段。
3. (可选)如果您的日志量非常大,实时日志推送后仅用于监控及分析,不需要全量的日志数据,您可以点击高级配置,配置采样比例来降低日志推送的数量。配置后,EdgeOne 将按照设定的百分比随机抽取日志,然后将其推送到您指定的目的地。

4. 配置完成日志字段后,点击下一步,进入步骤3。

步骤3:选择推送目的地

选您可以根据需要推送的实时日志目的地,选择推送至腾讯云 CLS、S3 兼容存储桶或者指定的 HTTP 服务器内,参考如下步骤进行配置:
推送至腾讯云 CLS
推送至 S3 兼容存储
推送至指定 HTTP 服务器
如果当前您还未自建数据分析系统,腾讯云提供了日志服务(CLS)可帮助您一站式完成实时日志的采集、推送与检索分析,减少您的开发及维护成本。您可以参考以下步骤将实时日志推送至腾讯云 CLS 服务内:

前提条件

当前已开通先开通 日志服务(CLS) 并授权腾讯云 EdgeOne 以创建日志集。
说明
1. 日志服务(CLS)为付费服务,相关费用请参考:日志服务计费概述
2. 建议您使用主账号启用服务,若为子账号或协作者,您需要为其授权相关权限。

操作步骤

创建推送任务
1. 第 ③ 步 中选择目的地为 腾讯云日志服务(CLS),并点击 下一步
2. 填写相关参数信息,参数说明如下:


地域:选择需要推送的目标地域。
目标集名称:选择目标地域下的日志集。
说明
若此处为空或需要新建日志集,请单击创建,在所选地域下创建日志集。
日志主题名称:可输入1-200个字符,允许的字符为 a-z, A-Z, 0-9, _, -
日志保存时间:请输入1-366间正整数。

相关参考

日志检索
日志检索支持多种类型的检索分析方式及图表分析形式,详细说明可见 日志检索。 EdgeOne 以推送任务为单元进行日志检索。在 实时日志页面,选择您需要检索的推送任务,单击检索,进入日志检索页面。
您可后续通过 日志服务(CLS) 侧管理日志集等模块,如修改日志集名称。
日志集
日志集(Logset)是腾讯云日志服务(CLS)的项目管理单元,用于区分不同项目的日志,一个日志集对应合集。腾讯云 EdgeOne 日志集有以下基本属性信息:
地域:日志集所属 地域
日志集名称:日志集命名。
日志保留时间:当前日志集里数据的保存时间周期。
创建时间:日志集创建时间。
日志主题
日志主题(Topic)是腾讯云日志服务(CLS)的基本管理单元,一个日志集可以包含多个日志主题。一个日志主题对应一类应用或服务,建议将不同机器上的同类日志收集到同一个日志主题中。例如,一个业务项目有三种日志:操作日志、应用程序日志、访问日志,每种类型可以创建对应日志主题。

日志服务系统以日志主题为单位,区分管理用户不同的日志数据,每个日志主题都可以配置不同的数据源、不同的索引规则和投递规则。因此,日志主题是日志服务配置、管理日志数据的基本单元,创建日志主题后需配置相关规则,才能如期有效地进行日志采集,并使用检索分析和投递等功能。

从场景功能上理解,日志主题主要提供:
采集日志到日志主题。
以日志主题为单元存储管理日志。
以日志主题为单元检索分析日志。
以日志主题为单元投递日志到其他平台。
从日志主题下载、消费日志。
说明
以上信息摘自 日志服务(CLS) 产品文档,请以日志服务(CLS)侧的说明为准。
每一个推送到腾讯云日志服务(CLS)的实时日志推送任务会将所选子域名的日志推送到一个对应的日志主题。

如果您当前已有自建的数据源,需要将实时日志推送到兼容 S3 存储桶,您可以参考以下步骤操作继续操作:
说明:
目前仅支持将站点加速日志、四层代理日志推送至兼容 S3 存储桶。
推送日志格式为 JSON Lines

操作步骤

1. 第 ③ 步 中选择目的地为 S3 兼容,并点击 下一步
2. 填写对应的目的地参数:
端点 URL:不包含存储桶名称或路径的 URL,例如:https://storage.googleapis.comhttps://s3.ap-northeast-2.amazonaws.com
存储桶地域:存储桶所在的地域,例如:ap-northeast-2
存储桶:存储桶名称和对应的日志存储路径:例如:your_bucket_name/EO-logs/
文件压缩:是否使用 gzip 压缩日志文件,勾选后,推送的日志文件将使用 gzip 压缩,文件名称将改为 filename.log.gz
SecretId:访问存储桶使用的 Access Key ID。
SecretKey:访问存储桶使用的 secret key。

说明:
1. 存储桶需要兼容 AWS Signature Version 4 鉴权算法,具体兼容情况请参考您的存储桶提供方的说明。
2. 文件名称说明:日志将会在指定存储桶路径下以 UploadTime_Random.log 格式存储,且会以日期(UTC +00:00)为一个文件夹归档日志,例如:logs/20230331/20230331T185917Z_2aadf5ce.log
UploadTime:日志文件上传时间,使用 ISO-8601 格式,UTC+00:00 时区。
Random:随机字符,当日志量较大的情况,可能会出现同一个上传时间有多个日志文件,通过此串随机字符来标识不同的文件。
3. 单击推送,下发实时日志推送任务后,EdgeOne 将推送一个测试文件至目标存储桶路径以校验连通性,例如1699874755_edgeone_push_test.txt,文件内容为固定字符串“test”。
如果您当前已有自建的数据源,EdgeOne 可通过 HTTP POST 请求调用您提供的后端接口地址,将日志在 HTTP body 中传输到您指定的服务器上。
说明:
1. HTTP 是明文传输 ,因此接口地址建议您使用 HTTPS 加密后地址。
2. 为了进一步加强请求来源的安全性验证,我们提供了请求鉴权方案,可在配置推送目的地信息中填写相关鉴权信息,鉴权算法见:鉴权算法参考
3. 推送日志格式为多个 JSON 对象组成的数组,每个 JSON 对象为一条日志。


操作指引

创建推送任务
1. 第 ③ 步 中选择目的地为 HTTP 服务(POST),并点击 下一步
2. 填写相关目的地及参数信息,参数说明如下:
接口地址:填入您的数据源接口地址,例如:https://www.example.com/log
文件压缩:为减少日志文件的大小,节约流量开销,您可以通过勾选 使用 gzip 压缩日志文件 开启文件压缩,EdgeOne 将会使用 gzip 格式压缩日志后再传输日志,并且会增加 HTTP 头部 `content-encoding = gzip 来标明压缩格式。
源站鉴权:选择为加密鉴权时,推送日志时将携带鉴权信息供源站进行验证,保证数据来源身份的安全性。
自定义 HTTP 请求头:添加需要 EdgeOne 发起请求时携带的 HTTP 头部。例如:您需要通过头部识别日志来源的厂商是 EdgeOne,您可以添加一个头部 log-source = EdgeOne 来识别日志是来源。

3. 单击推送,即可下发实时日志推送任务。
4. 实时日志推送任务在配置阶段为了校验接口连通性,将向接口地址发送一个空数据进行验证,数据格式如下所示:
[{
"BotClassAccountTakeOver": "-",
"BotClassAttacker": "-",
"BotClassMaliciousBot": "-",
"BotClassProxy": "-",
"BotClassScanner": "-",
"ClientDeviceType": "-",
"ClientIP": "-",
"ClientISP": "-",
"ClientRegion": "-",
"ClientState": "-",
"EdgeCacheStatus": "-",
"EdgeEndTime": "-",
"EdgeInternalTime": "-",
"EdgeResponseBodyBytes": "-",
"EdgeResponseBytes": "-",
"EdgeResponseStatusCode": "-",
"EdgeResponseTime": "-",
"EdgeServerID": "-",
"EdgeServerIP": "-",
"EdgeSeverRegion": "-",
"LogTime": "-",
"OriginDNSResponseDuration": "-",
"OriginIP": "-",
"OriginRequestHeaderSendDuration": "-",
"OriginResponseHeaderDuration": "-",
"OriginResponseStatusCode": "-",
"OriginSSLProtocol": "-",
"OriginTCPHandshakeDuration": "-",
"OriginTLSHandshakeDuration": "-",
"ParentRequestID": "-",
"RemotePort": "-",
"RequestBytes": "-",
"RequestHost": "-",
"RequestID": "-",
"RequestMethod": "-",
"RequestProtocol": "-",
"RequestRange": "-",
"RequestReferer": "-",
"RequestSSLProtocol": "-",
"RequestTime": "-",
"RequestUA": "-",
"RequestUrl": "-",
"RequestUrlQueryString": "-"
}]

相关参考

请求鉴权算法
如果您在推送目的地信息中,源站鉴权内选择了加密签名,可自定义输入您自定义配置 SecretId 和 SecretKey,EdgeOne 将在请求 URL 中增加签名auth_keyaccess_key,签名算法详情如下:
1. 请求URL构成
如下所示,请求 URL 将在?后携带 auth_keyaccess_key
http://DomainName[:port]/[uri]?auth_key=timestamp-rand-md5hash&access_key=SecretID
参数说明:
timestamp:请求当前时间,使用 Unix 秒级10位时间戳。
rand:随机数
access_key:用于标识接口请求方的身份,即您所自定义配置的 SecretID。
SecretKey:固定长度32,即您所自定义配置的 SecretKey。
uri:资源标识符,例如:/access_log/post
md5hash:md5hash = md5sum(string_to_sign),其中 string_to_sign ="uri-timestamp-rand-SecretKey"。通过md5算法计算出的验证串,数字0-9和小写英文字母 a-z 混合,固定长度32。
2. 计算示例
假定填入参数为: 接口地址:https://www.example.com/access_log/post SecretID = YourID SecretKey = YourKey uri = /access_log/post timestamp = 1571587200 rand = 0
string_to_sign = "/access_log/post-1571587200-0-YourKey"
基于该字符串计算出
md5hash=md5sum("/access_log/post-1571587200-0-YourKey")=1f7ffa7bff8f06bbfbe2ace0f14b7e16
最终推送时的请求 url 为:
https://www.example.com/cdnlog/post?auth_key=1571587200-0-1f7ffa7bff8f06bbfbe2ace0f14b7e16&access_key=YourID

服务端在接收到推送请求后,提取auth_key的值. 对auth_key的值进行拆分,获取timestamprandmd5hash。可先检查 timestamp 是否过期,过期时间建议为300s,并基于上述规则拼装加密字符串,利用 SecretKey 拼装出需加密的字符串,加密后与 auth_key 中的 md5hash 值进行比较, 相同则说明鉴权通过。
3. 服务端解析鉴权请求代码示例
Python
Goland
import hashlib

from flask import Flask, request

app = Flask(__name__)


def get_rsp(msg, result={}, code=0):
return {
"respCode": code,
"respMsg": msg,
"result": result
}


def get_secret_key(access_key):
return "secret_key"


@app.route("/access_log/post", methods=['POST'])
def access_log():
if request.method == 'POST':
if request.content_type.startswith('application/json'):
current_time_ts, rand_num, md5hash = request.args.get("auth_key").split("-")
# 判断请求时间是否是在有效期内
if time.time() - int(current_time_ts) > 300:
return get_rsp(msg="The request is out of time", code=-1)

access_key = request.args.get("access_key")
# 通过access_key(SecretID)获取secret_key
secret_key = get_secret_key(access_key)
raw_str = "%s-%s-%s-%s" % (request.path, current_time_ts, rand_num, secret_key)
auth_md5hash = hashlib.md5(raw_str.encode("utf-8")).hexdigest()
if auth_md5hash == md5hash:
# 认证通过
if request.headers['content-encoding'] == 'gzip':
# 解压数据
pass
# 数据处理
return get_rsp("ok")
return get_rsp(msg="Please use content_type by application/json", code=-1)
return get_rsp(msg="The request method not find, method == %s" % request.method, code=-1)

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8888, debug=True)python

package main

import (
"context"
"crypto/md5"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
)

func main() {
mux := http.NewServeMux()
mux.Handle("/access_log/post", &logHandler{})

server := &http.Server{
Addr: ":5000",
Handler: mux,
}

// 创建系统信号接收器
done := make(chan os.Signal)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-done

if err := server.Shutdown(context.Background()); err != nil {
log.Fatal("Shutdown server:", err)
}
}()

err := server.ListenAndServe()
if err != nil {
if err == http.ErrServerClosed {
log.Print("Server closed under request")
} else {
log.Fatal("Server closed unexpected")
}
}
}

type logHandler struct{}

func (*logHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
query := r.URL.Query()
authKey := query.Get("auth_key")
accessKey := query.Get("access_key")//access_key 即您提供的SecretID
authKeys := strings.Split(authKey, "-")
if len(authKeys) == 3 {
currentTimeTs := authKeys[0]
//进行时间戳有效期判断
RandNum := authKeys[1]
md5Hash := authKeys[2]
secretKey := getSecretKey(accessKey)
authStr := fmt.Sprintf("%s-%s-%s-%s", "/access_log/post", currentTimeTs, RandNum, secretKey)
data := []byte(authStr)
has := md5.Sum(data)
authMd5 := fmt.Sprintf("%x", has) //转换成字符串进行比较
if authMd5 == md5Hash {
// todo 认证成功
if r.Header.Get("Content-Encoding") == "gzip" {
//解压数据
}
//数据处理
}
} else {
//异常处理
}
}
}

// 获取SecretKey
func getSecretKey(accessKey string) string {
if accessKey != "" {
// 通过Access_key(SecretID)获取Secret_Key
return "secret_key"
}
return ""
}