Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(error-log-logger): add clickhouse for error-log-logger #6256

Merged
merged 14 commits into from
Feb 28, 2022
67 changes: 66 additions & 1 deletion apisix/plugins/error-log-logger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ local metadata_schema = {
service_instance_name = {type="string", default = "APISIX Service Instance"},
},
},
clickhouse = {
type = "object",
properties = {
endpoint_addr = {schema_def.uri_def, default="http://127.0.0.1:8123"},
user = {type = "string", default = "default"},
password = {type = "string", default = ""},
database = {type = "string", default = ""},
logtable = {type = "string", default = ""},
},
required = {"endpoint_addr", "user", "password", "database", "logtable"}
},
host = {schema_def.host_def, description = "Deprecated, use `tcp.host` instead."},
port = {type = "integer", minimum = 0, description = "Deprecated, use `tcp.port` instead."},
tls = {type = "boolean", default = false,
Expand All @@ -75,6 +86,7 @@ local metadata_schema = {
oneOf = {
{required = {"skywalking"}},
{required = {"tcp"}},
{required = {"clickhouse"}},
-- for compatible with old schema
{required = {"host", "port"}}
}
Expand Down Expand Up @@ -214,6 +226,57 @@ local function send_to_skywalking(log_message)
end


local function send_to_clickhouse(log_message)
local err_msg
local res = true
core.log.info("sending a batch logs to ", config.clickhouse.endpoint_addr)

local httpc = http.new()
httpc:set_timeout(config.timeout * 1000)

local entries = {}
for i = 1, #log_message, 2 do
-- TODO Here save error log as a whole string to clickhouse 'data' column.
-- We will add more columns in the future.
table.insert(entries, core.json.encode({data=log_message[i]}))
end

local httpc_res, httpc_err = httpc:request_uri(
config.clickhouse.endpoint_addr,
{
method = "POST",
body = "INSERT INTO " .. config.clickhouse.logtable .." FORMAT JSONEachRow "
.. table.concat(entries, " "),
keepalive_timeout = config.keepalive * 1000,
headers = {
["Content-Type"] = "application/json",
["X-ClickHouse-User"] = config.clickhouse.user,
["X-ClickHouse-Key"] = config.clickhouse.password,
["X-ClickHouse-Database"] = config.clickhouse.database
}
}
)

if not httpc_res then
return false, "error while sending data to clickhouse["
.. config.clickhouse.endpoint_addr .. "] " .. httpc_err
end

-- some error occurred in the server
if httpc_res.status >= 400 then
res = false
err_msg = string.format(
"server returned status code[%s] clickhouse[%s] body[%s]",
httpc_res.status,
config.clickhouse.endpoint_addr.endpoint_addr,
httpc_res:read_body()
)
end

return res, err_msg
end


local function update_filter(value)
local level = log_level[value.level]
local status, err = errlog.set_filter_level(level)
Expand All @@ -230,6 +293,8 @@ end
local function send(data)
if config.skywalking then
return send_to_skywalking(data)
elseif config.clickhouse then
return send_to_clickhouse(data)
end
return send_to_tcp_server(data)
end
Expand All @@ -247,7 +312,7 @@ local function process()
core.log.warn("set log filter failed for ", err)
return
end
if not (config.tcp or config.skywalking) then
if not (config.tcp or config.skywalking or config.clickhouse) then
config.tcp = {
host = config.host,
port = config.port,
Expand Down
24 changes: 24 additions & 0 deletions docs/en/latest/plugins/error-log-logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ For more info on Batch-Processor in Apache APISIX please refer.
| skywalking.endpoint_addr | string | optional | http://127.0.0.1:12900/v3/logs | | the http endpoint of Skywalking. |
| skywalking.service_name | string | optional | APISIX | | service name for skywalking reporter |
| skywalking.service_instance_name | String | optional | APISIX Instance Name | | Service instance name for skywalking reporter, set it to `$hostname` to get local hostname directly. |
| clickhouse.endpoint_addr | String | optional | http://127.0.0.1:8213 | | clickhouse HTTP endpoint, default http://127.0.0.1:8213 |
| clickhouse.user | String | optional | default | | clickhouse user |
| clickhouse.password | String | optional | | | clickhouse password |
| clickhouse.database | String | optional | | | clickhouse for error log DB name |
| clickhouse.logtable | String | optional | | | clickhouse for error log table name |
| host | string | optional | | | (`Deprecated`, use `tcp.host` instead) IP address or the Hostname of the TCP server. |
| port | integer | optional | | [0,...] | (`Deprecated`, use `tcp.port` instead) Target upstream port. |
| tls | boolean | optional | false | | (`Deprecated`, use `tcp.tls` instead) Control whether to perform SSL verification. |
Expand Down Expand Up @@ -124,3 +129,22 @@ curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/error-log-logger -H 'X-A
"inactive_timeout": 1
}'
```

## How to set the clickhouse

The plugin sends the error log as a string to the `data` field of the clickhouse table.
*TODO Here save error log as a whole string to clickhouse 'data' column. We will add more columns in the future.*
Step: update the attributes of the plugin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this sentence mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's means that the plugins insert error logs to the clickhouse table with data column default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

┌─data──────────────────────────────────────────────────────────────────┬
│  2022/02/16 16:45:07 [error] 4279#4279: *7272 [lua] batch-processor.lua:73: Batch ...                                  │ 
└───────────────────────────────────────────────────────────────────────┴


```shell
curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/error-log-logger -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"clickhouse": {
"user": "default",
"password": "a",
"database": "error_log",
"logtable": "t",
"endpoint_addr": "http://127.0.0.1:8123"
}
}'
```
24 changes: 24 additions & 0 deletions docs/zh/latest/plugins/error-log-logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ title: error-log-logger
| skywalking.endpoint_addr | string | 可选 | http://127.0.0.1:12900/v3/logs | | Skywalking 的 HTTP endpoint 地址,例如:http://127.0.0.1:12800 |
| skywalking.service_name | string | 可选 | APISIX | | skywalking 上报的 service 名称 |
| skywalking.service_instance_name | String | 可选 | APISIX Instance Name | | skywalking 上报的 service 实例名, 如果期望直接获取本机主机名则设置为 `$hostname` |
| clickhouse.endpoint_addr | String | 可选 | http://127.0.0.1:8213 | | clickhouse 的 HTTP endpoint 地址,例如 http://127.0.0.1:8213 |
| clickhouse.user | String | 可选 | default | | clickhouse 的用户名 |
| clickhouse.password | String | 可选 | | | clickhouse 的密码 |
| clickhouse.database | String | 可选 | | | clickhouse 的用于接收 log 的数据库 |
| clickhouse.logtable | String | 可选 | | | clickhouse 的用于接收 log 的表 |
| host | string | 可选 | | | (`弃用`,替换成`tcp.host`) TCP 服务的IP地址或主机名 |
| port | integer | 可选 | | [0,...] | (`弃用`,替换成`tcp.port`) 目标端口 |
| tls | boolean | 可选 | false | | (`弃用`,替换成`tcp.tls`) 用于控制是否执行SSL验证 |
Expand Down Expand Up @@ -122,3 +127,22 @@ curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/error-log-logger -H 'X-A
"inactive_timeout": 1
}'
```

## 如何设置接收日志的 clickhouse 数据库

插件将 error log 作为一个字符串发送到 clickhouse 表的 `data` 字段。
*TODO 将error log 作为一个字符串保持到clickhouse数据库的data字段,未来我们将会增加更多的字段。*
步骤:更新插件属性

```shell
curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/error-log-logger -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"clickhouse": {
"user": "default",
"password": "a",
"database": "error_log",
"logtable": "t",
"endpoint_addr": "http://127.0.0.1:8123"
}
}'
```
Loading