Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions apisix/utils/log-util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ local expr = require("resty.expr.v1")
local content_decode = require("apisix.utils.content-decode")
local ngx = ngx
local pairs = pairs
local type = type
local ngx_now = ngx.now
local ngx_header = ngx.header
local os_date = os.date
Expand All @@ -32,6 +33,7 @@ local is_http = ngx.config.subsystem == "http"
local req_get_body_file = ngx.req.get_body_file
local MAX_REQ_BODY = 524288 -- 512 KiB
local MAX_RESP_BODY = 524288 -- 512 KiB
local MAX_LOG_FORMAT_DEPTH = 5
local io = io

local lru_log_format = core.lrucache.new({
Expand Down Expand Up @@ -69,22 +71,35 @@ local function get_request_body(max_bytes)
end


local function gen_log_format(format)
local function do_gen_log_format(format, depth)
local log_format = {}
for k, var_name in pairs(format) do
if var_name:byte(1, 1) == str_byte("$") then
if type(var_name) == "table" then
if depth >= MAX_LOG_FORMAT_DEPTH then
core.log.warn("log_format nesting exceeds max depth ",
MAX_LOG_FORMAT_DEPTH, ", truncating")
log_format[k] = {false, {}}
else
local nested_format = do_gen_log_format(var_name, depth + 1)
log_format[k] = {false, nested_format}
end
elseif type(var_name) == "string" and var_name:byte(1, 1) == str_byte("$") then
log_format[k] = {true, var_name:sub(2)}
else
log_format[k] = {false, var_name}
end
end
return log_format
end

local function gen_log_format(format)
local log_format = do_gen_log_format(format, 1)
core.log.info("log_format: ", core.json.delay_encode(log_format))
return log_format
end


local function get_custom_format_log(ctx, format, max_req_body_bytes)
local log_format = lru_log_format(format or "", nil, gen_log_format, format)
local function build_log_entry(ctx, log_format, max_req_body_bytes)
local entry = core.table.new(0, core.table.nkeys(log_format))
for k, var_attr in pairs(log_format) do
if var_attr[1] then
Expand All @@ -100,10 +115,19 @@ local function get_custom_format_log(ctx, format, max_req_body_bytes)
else
entry[k] = ctx.var[var_attr[2]]
end
elseif type(var_attr[2]) == "table" then
entry[k] = build_log_entry(ctx, var_attr[2], max_req_body_bytes)
else
entry[k] = var_attr[2]
end
end
return entry
end


local function get_custom_format_log(ctx, format, max_req_body_bytes)
local log_format = lru_log_format(format or "", nil, gen_log_format, format)
local entry = build_log_entry(ctx, log_format, max_req_body_bytes)

local matched_route = ctx.matched_route and ctx.matched_route.value
if matched_route then
Expand Down
4 changes: 2 additions & 2 deletions docs/en/latest/plugins/clickhouse-logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The `clickhouse-logger` Plugin is used to push logs to [ClickHouse](https://clic
| timeout | integer | False | 3 | [1,...] | Time to keep the connection alive for after sending a request. |
| name | string | False | "clickhouse logger" | | Unique identifier for the logger. If you use Prometheus to monitor APISIX metrics, the name is exported in `apisix_batch_process_entries`. |
| ssl_verify | boolean | False | true | [true,false] | When set to `true`, verifies SSL. |
| log_format | object | False | | | Log format declared as key value pairs in JSON format. Values only support strings. [APISIX](../apisix-variable.md) or [Nginx](http://nginx.org/en/docs/varindex.html) variables can be used by prefixing the string with `$`. |
| log_format | object | False | | | Log format declared as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX](../apisix-variable.md) or [NGINX](http://nginx.org/en/docs/varindex.html) variables can be referenced by prefixing with `$`. |
| include_req_body | boolean | False | false | [false, true] | When set to `true` includes the request body in the log. If the request body is too big to be kept in the memory, it can't be logged due to Nginx's limitations. |
| include_req_body_expr | array | False | | | Filter for when the `include_req_body` attribute is set to `true`. Request body is only logged when the expression set here evaluates to `true`. See [lua-resty-expr](https://github.com/api7/lua-resty-expr) for more. |
| include_resp_body | boolean | False | false | [false, true] | When set to `true` includes the response body in the log. |
Expand Down Expand Up @@ -103,7 +103,7 @@ You can also set the format of the logs by configuring the Plugin metadata. The

| Name | Type | Required | Default | Description |
| ---------- | ------ | -------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log_format | object | False | | Log format declared as key value pairs in JSON format. Values only support strings. [APISIX](../apisix-variable.md) or [Nginx](http://nginx.org/en/docs/varindex.html) variables can be used by prefixing the string with `$`. |
| log_format | object | False | | Log format declared as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX](../apisix-variable.md) or [NGINX](http://nginx.org/en/docs/varindex.html) variables can be referenced by prefixing with `$`. |
| max_pending_entries | integer | False | | Maximum number of pending entries that can be buffered in batch processor before it starts dropping them. |

:::info IMPORTANT
Expand Down
6 changes: 5 additions & 1 deletion docs/en/latest/plugins/elasticsearch-logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ The `elasticsearch-logger` Plugin pushes request and response logs in batches to
| endpoint_addrs | array[string] | True | | Elasticsearch API endpoint addresses. If multiple endpoints are configured, they will be written randomly. |
| field | object | True | | Elasticsearch `field` configuration. |
| field.index | string | True | | Elasticsearch [_index field](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-index-field.html#mapping-index-field). |
| log_format | object | False | | Custom log format in key-value pairs in JSON format. Support [APISIX](../apisix-variable.md) or [NGINX variables](http://nginx.org/en/docs/varindex.html) in values. |
| log_format | object | False | | Custom log format as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX](../apisix-variable.md) or [NGINX variables](http://nginx.org/en/docs/varindex.html) can be referenced by prefixing with `$`. |
| auth | array | False | | Elasticsearch [authentication](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) configuration. |
| auth.username | string | True | | Elasticsearch [authentication](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) username. |
| auth.password | string | True | | Elasticsearch [authentication](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) password. |
Expand All @@ -61,8 +61,12 @@ This Plugin supports using batch processors to aggregate and process entries (lo

| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
<<<<<<< HEAD
| log_format | object | False | | Custom log format as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX variables](../apisix-variable.md) and [NGINX variables](http://nginx.org/en/docs/varindex.html) can be referenced by prefixing with `$`. |
=======
| log_format | object | False | | Custom log format in key-value pairs in JSON format. Support [APISIX variables](../apisix-variable.md) and [NGINX variables](http://nginx.org/en/docs/varindex.html) in values. |
| max_pending_entries | integer | False | | Maximum number of pending entries that can be buffered in batch processor before it starts dropping them. |
>>>>>>> origin/master

## Examples

Expand Down
17 changes: 12 additions & 5 deletions docs/en/latest/plugins/file-logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The `file-logger` Plugin is used to push log streams to a specific location.
| Name | Type | Required | Description |
| ---- | ------ | -------- | ------------- |
| path | string | True | Log file path. |
| log_format | object | False | Log format declared as key value pairs in JSON format. Values only support strings. [APISIX](../apisix-variable.md) or [Nginx](http://nginx.org/en/docs/varindex.html) variables can be used by prefixing the string with `$`. |
| log_format | object | False | Log format declared as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX](../apisix-variable.md) or [NGINX](http://nginx.org/en/docs/varindex.html) variables can be referenced by prefixing with `$`. |
| include_req_body | boolean | False | When set to `true` includes the request body in the log. If the request body is too big to be kept in the memory, it can't be logged due to Nginx's limitations. |
| include_req_body_expr | array | False | Filter for when the `include_req_body` attribute is set to `true`. Request body is only logged when the expression set here evaluates to `true`. See [lua-resty-expr](https://github.com/api7/lua-resty-expr) for more. |
| include_resp_body | boolean | False | When set to `true` includes the response body in the log file. |
Expand Down Expand Up @@ -103,7 +103,7 @@ You can also set the format of the logs by configuring the Plugin metadata. The

| Name | Type | Required | Default | Description |
| ---------- | ------ | -------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log_format | object | False | | Log format declared as key value pairs in JSON format. Values only support strings. [APISIX](../apisix-variable.md) or [Nginx](http://nginx.org/en/docs/varindex.html) variables can be used by prefixing the string with `$`. |
| log_format | object | False | | Log format declared as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX](../apisix-variable.md) or [NGINX](http://nginx.org/en/docs/varindex.html) variables can be referenced by prefixing with `$`. |

The example below shows how you can configure through the Admin API:

Expand All @@ -122,16 +122,23 @@ curl http://127.0.0.1:9180/apisix/admin/plugin_metadata/file-logger -H "X-API-KE
"log_format": {
"host": "$host",
"@timestamp": "$time_iso8601",
"client_ip": "$remote_addr"
"client_ip": "$remote_addr",
"request": {
"method": "$request_method",
"uri": "$request_uri"
},
"response": {
"status": "$status"
}
}
}'
```

With this configuration, your logs would be formatted as shown below:

```shell
{"host":"localhost","@timestamp":"2020-09-23T19:05:05-04:00","client_ip":"127.0.0.1","route_id":"1"}
{"host":"localhost","@timestamp":"2020-09-23T19:05:05-04:00","client_ip":"127.0.0.1","route_id":"1"}
{"host":"localhost","@timestamp":"2020-09-23T19:05:05-04:00","client_ip":"127.0.0.1","request":{"method":"GET","uri":"/hello"},"response":{"status":200},"route_id":"1"}
{"host":"localhost","@timestamp":"2020-09-23T19:05:05-04:00","client_ip":"127.0.0.1","request":{"method":"GET","uri":"/hello"},"response":{"status":200},"route_id":"1"}
```

## Enable Plugin
Expand Down
10 changes: 6 additions & 4 deletions docs/en/latest/plugins/google-cloud-logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ This plugin also allows to push logs as a batch to your Google Cloud Logging Ser
| ssl_verify | False | true | When set to `true`, enables SSL verification as mentioned in [OpenResty docs](https://github.com/openresty/lua-nginx-module#tcpsocksslhandshake). |
| resource | False | {"type": "global"} | Google monitor resource. See [MonitoredResource](https://cloud.google.com/logging/docs/reference/v2/rest/v2/MonitoredResource) for more details. |
| log_id | False | apisix.apache.org%2Flogs | Google Cloud logging ID. See [LogEntry](https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry) for details. |
| log_format | False | | Log format declared as key value pairs in JSON format. Values only support strings. [APISIX](../apisix-variable.md) or [Nginx](http://nginx.org/en/docs/varindex.html) variables can be used by prefixing the string with `$`. |
| log_format | False | | Log format declared as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX](../apisix-variable.md) or [NGINX](http://nginx.org/en/docs/varindex.html) variables can be referenced by prefixing with `$`. |

NOTE: `encrypt_fields = {"auth_config.private_key"}` is also defined in the schema, which means that the field will be stored encrypted in etcd. See [encrypted storage fields](../plugin-develop.md#encrypted-storage-fields).

Expand Down Expand Up @@ -90,7 +90,7 @@ You can also set the format of the logs by configuring the Plugin metadata. The

| Name | Type | Required | Default | Description |
| ---------- | ------ | -------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log_format | object | False | | Log format declared as key value pairs in JSON format. Values only support strings. [APISIX](../apisix-variable.md) or [Nginx](http://nginx.org/en/docs/varindex.html) variables can be used by prefixing the string with `$`. |
| log_format | object | False | | Log format declared as key-value pairs in JSON. Values support strings and nested objects (up to five levels deep; deeper fields are truncated). Within strings, [APISIX](../apisix-variable.md) or [NGINX](http://nginx.org/en/docs/varindex.html) variables can be referenced by prefixing with `$`. |
| max_pending_entries | integer | False | | Maximum number of pending entries that can be buffered in batch processor before it starts dropping them. |

:::info IMPORTANT
Expand All @@ -116,15 +116,17 @@ curl http://127.0.0.1:9180/apisix/admin/plugin_metadata/google-cloud-logging -H
"log_format": {
"host": "$host",
"@timestamp": "$time_iso8601",
"client_ip": "$remote_addr"
"client_ip": "$remote_addr",
"request": { "method": "$request_method", "uri": "$request_uri" },
"response": { "status": "$status" }
}
}'
```

With this configuration, your logs would be formatted as shown below:

```json
{"partialSuccess":false,"entries":[{"jsonPayload":{"client_ip":"127.0.0.1","host":"localhost","@timestamp":"2023-01-09T14:47:25+08:00","route_id":"1"},"resource":{"type":"global"},"insertId":"942e81f60b9157f0d46bc9f5a8f0cc40","logName":"projects/apisix/logs/apisix.apache.org%2Flogs","timestamp":"2023-01-09T14:47:25+08:00","labels":{"source":"apache-apisix-google-cloud-logging"}}]}
{"partialSuccess":false,"entries":[{"jsonPayload":{"host":"localhost","client_ip":"127.0.0.1","@timestamp":"2023-01-09T14:47:25+08:00","request":{"method":"GET","uri":"/hello"},"response":{"status":200},"route_id":"1"},"resource":{"type":"global"},"insertId":"942e81f60b9157f0d46bc9f5a8f0cc40","logName":"projects/apisix/logs/apisix.apache.org%2Flogs","timestamp":"2023-01-09T14:47:25+08:00","labels":{"source":"apache-apisix-google-cloud-logging"}}]}
```

## Enable Plugin
Expand Down
Loading