Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: add elasticsearch-logger #7643

Merged
merged 57 commits into from
Aug 31, 2022

Conversation

ccxhwmy
Copy link
Contributor

@ccxhwmy ccxhwmy commented Aug 10, 2022

Description

Fixes #7636

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

@tzssangglass tzssangglass changed the title add elasticsearch-logging base function feat: add elasticsearch-logging[WIP] Aug 10, 2022
@ccxhwmy ccxhwmy marked this pull request as ready for review August 14, 2022 07:31
@ccxhwmy ccxhwmy changed the title feat: add elasticsearch-logging[WIP] feat: add elasticsearch-logging Aug 14, 2022
@spacewander
Copy link
Member

@ccxhwmy
Could you fix the message so we can close the issue when this PR is merged?


local DEFAULT_ELASTICSEARCH_SOURCE = "apache-apisix-elasticsearch-logging"

local plugin_name = "elasticsearch-logging"
Copy link
Member

Choose a reason for hiding this comment

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

We should call it elasticsearch-logger like the kafka-logger plugin?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should call it elasticsearch-logger like the kafka-logger plugin?

OK, do I need to change all ealsticsearch-logging to elasticsearch-logger? Including the file name?



local function get_logger_entry(conf)
local entry = log_util.get_full_log(ngx, conf)
Copy link
Member

Choose a reason for hiding this comment

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

Please also support the custom log format.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please also support the custom log format.

How about the reference kafka-logger plugin?

local entry
    if conf.meta_format == "origin" then
        entry = log_util.get_req_original(ctx, conf)
        -- core.log.info("origin entry: ", entry)

    else
        local metadata = plugin.plugin_metadata(plugin_name)
        core.log.info("metadata: ", core.json.delay_encode(metadata))
        if metadata and metadata.value.log_format
          and core.table.nkeys(metadata.value.log_format) > 0
        then
            entry = log_util.get_custom_format_log(ctx, metadata.value.log_format)
            core.log.info("custom log format entry: ", core.json.delay_encode(entry))
        else
            entry = log_util.get_full_log(ngx, conf)
            core.log.info("full log entry: ", core.json.delay_encode(entry))
        end
    end

Copy link
Member

Choose a reason for hiding this comment

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

We do not reference the code of another plugin in one plugin. Unless we pull some generic code into a common module.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We do not reference the code of another plugin in one plugin. Unless we pull some generic code into a common module.

Please also support the custom log format.

Is the custom log format like:
https://github.com/apache/apisix/blob/master/docs/en/latest/plugins/kafka-logger.md#metadata

Copy link
Member

Choose a reason for hiding this comment

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

yes

local schema = {
type = "object",
properties = {
endpoint = {
Copy link
Member

Choose a reason for hiding this comment

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

Why do we wrap all the fields in an extra endpoint field?

}) .. "\n" ..
core.json.encode({
time = ngx_now(),
host = entry.server.hostname,
Copy link
Member

Choose a reason for hiding this comment

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

Why should we invent a format structure for a specific plugin?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why should we invent a format structure for a specific plugin?

I refer to splunk-hec-logging:

local function get_logger_entry(conf)

How about core.json.encode(entry) directly?

Copy link
Member

Choose a reason for hiding this comment

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

we just need to use log_util.get_req_original(ctx, conf) to get entry, This is a json, and ES supports this format.

Copy link
Member

Choose a reason for hiding this comment

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

Remember that when we update the entry, we also need to update the png image.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we just need to use log_util.get_req_original(ctx, conf) to get entry, This is a json, and ES supports this format.

I found that log_util.get_req_original(ctx, conf) will return a string instead of json:

function _M.get_req_original(ctx, conf)
local headers = {
ctx.var.request, "\r\n"
}
for k, v in pairs(ngx.req.get_headers()) do
core.table.insert_tail(headers, k, ": ", v, "\r\n")
end
-- core.log.error("headers: ", core.table.concat(headers, ""))
core.table.insert(headers, "\r\n")
if conf.include_req_body then
core.table.insert(headers, ctx.var.request_body)
end
return core.table.concat(headers, "")
end

Copy link
Member

Choose a reason for hiding this comment

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

my mistake. json string is ok. we can follow this.

end

local uri = conf.endpoint.uri ..
(str_sub(conf.endpoint.uri, -1) == "/" and "_bulk" or "/_bulk")
Copy link
Member

Choose a reason for hiding this comment

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

Use string.byte would be better

-- limitations under the License.
--

local ngx = ngx
Copy link
Member

Choose a reason for hiding this comment

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

We should move the localized variable after require ...

--- request
GET /hello
--- wait: 2
--- response_body
Copy link
Member

Choose a reason for hiding this comment

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

We should check the data sent to the elasticsearch, via injecting like: #7593 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should check the data sent to the elasticsearch, via injecting like: #7593 (comment)

Does you mean I should hook the function httpc:request_uri and mock it with my own mock_request_uri, and check the request body with the mock_request_uri?
If so, I am not quite understand the nessary to check request body.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should check the data sent to the elasticsearch, via injecting like: #7593 (comment)

Does you mean I should hook the function httpc:request_uri and mock it with my own mock_request_uri, and check the request body with the mock_request_uri? If so, I am not quite understand the nessary to check request body.

@spacewander
Please pay attention to this question when you are free, Thank you.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry for missing this. Yes, you are right.

uri = core.schema.uri_def,
index = { type = "string"},
type = { type = "string"},
username = { type = "string"},
Copy link
Member

Choose a reason for hiding this comment

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

We can store username & password in an additional field like


So that we can require them easily.

@ccxhwmy
Copy link
Contributor Author

ccxhwmy commented Aug 14, 2022

@ccxhwmy Could you fix the message so we can close the issue when this PR is merged?

I tryed to do it, but failed, it seems that I don't have permission.
image

@tzssangglass
Copy link
Member

I tryed to do it, but failed, it seems that I don't have permission.

like:

Fixes #7636

@ccxhwmy
Copy link
Contributor Author

ccxhwmy commented Aug 15, 2022

I tryed to do it, but failed, it seems that I don't have permission.

like:

Fixes #7636

I get, Thank you

headers["Authorization"] = authorization
end

core.log.info("uri: ", uri, ", body: ", body, ", headers: ", core.json.encode(headers))
Copy link
Member

Choose a reason for hiding this comment

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

This headers may contain username and passowrd in base64 format, which we should not output in the log for security reasons.

Comment on lines 1 to 3
---
title: elasticsearch-logging
---
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add some keywords and description?

Copy link
Contributor

Choose a reason for hiding this comment

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

docs/zh/latest/plugins/elasticsearch-logging.md Outdated Show resolved Hide resolved
docs/zh/latest/plugins/elasticsearch-logging.md Outdated Show resolved Hide resolved
docs/zh/latest/plugins/elasticsearch-logging.md Outdated Show resolved Hide resolved
docs/zh/latest/plugins/elasticsearch-logging.md Outdated Show resolved Hide resolved
Comment on lines 32 to 41
| 名称 | 是否必需 | 默认值 | 描述 |
| ------------------- | -------- | -------------------- | ------------------------------------------------------------ |
| endpoint | 必选 | | Elasticsearch 端点配置信息 |
| endpoint.uri | 必选 | | Elasticsearch API |
| endpoint.index | 必选 | | Elasticsearch [_index field](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-index-field.html#mapping-index-field) |
| endpoint.type | 可选 | Elasticsearch 默认值 | Elasticsearch [_type field](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/mapping-type-field.html#mapping-type-field) |
| endpoint.username | 可选 | | Elasticsearch [authentication](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) username |
| endpoint.password | 可选 | | Elasticsearch [authentication](https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-up-authentication.html) password |
| endpoint.ssl_verify | 可选 | true | 当设置为 `true` 则允许 SSL 验证,参考 [OpenResty docs](https://github.com/openresty/lua-nginx-module#tcpsocksslhandshake) |
| endpoint.timeout | 可选 | 10 | 发送给 Elasticsearch 请求超时时间 |
Copy link
Contributor

Choose a reason for hiding this comment

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

Please refer to http-logger modification.

docs/en/latest/plugins/elasticsearch-logging.md Outdated Show resolved Hide resolved
docs/en/latest/plugins/elasticsearch-logging.md Outdated Show resolved Hide resolved
docs/en/latest/plugins/elasticsearch-logging.md Outdated Show resolved Hide resolved
docs/en/latest/plugins/elasticsearch-logging.md Outdated Show resolved Hide resolved
@guitu168
Copy link
Contributor

great work! 👍

@ccxhwmy ccxhwmy changed the title feat: add elasticsearch-logging feat: add elasticsearch-logger Aug 15, 2022
ccxhwmy and others added 6 commits August 15, 2022 21:10
Co-authored-by: tzssangglass <tzssangglass@gmail.com>
Co-authored-by: tzssangglass <tzssangglass@gmail.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
@tzssangglass
Copy link
Member

LGTM(left two comments about indent)

ccxhwmy and others added 3 commits August 24, 2022 11:17
Co-authored-by: tzssangglass <tzssangglass@gmail.com>
Co-authored-by: tzssangglass <tzssangglass@gmail.com>
check endpoint_addr must not end with "/"
@ccxhwmy ccxhwmy requested a review from guitu168 August 24, 2022 14:05
Copy link
Contributor

@guitu168 guitu168 left a comment

Choose a reason for hiding this comment

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

other LGTM 👍

docs/zh/latest/plugins/elasticsearch-logger.md Outdated Show resolved Hide resolved
docs/zh/latest/plugins/elasticsearch-logger.md Outdated Show resolved Hide resolved
docs/zh/latest/plugins/elasticsearch-logger.md Outdated Show resolved Hide resolved
docs/zh/latest/plugins/elasticsearch-logger.md Outdated Show resolved Hide resolved
docs/en/latest/plugins/elasticsearch-logger.md Outdated Show resolved Hide resolved
ccxhwmy and others added 5 commits August 24, 2022 23:22
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
@ccxhwmy
Copy link
Contributor Author

ccxhwmy commented Aug 25, 2022

Need we re-run the ci?

tzssangglass
tzssangglass previously approved these changes Aug 28, 2022
local schema = {
type = "object",
properties = {
meta_format = {
Copy link
Member

Choose a reason for hiding this comment

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

Where do we use this field?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Where do we use this field?

My mistake, I forgot to remove it.


local uri = conf.endpoint_addr .. "/_bulk"
local body = core.table.concat(entries, "")
local headers = {["Content-Type"] = "application/json"}
Copy link
Member

Choose a reason for hiding this comment

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

Would be better to use application/x-ndjson?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would be better to use application/x-ndjson?

I learned about ndjson, I think it is more suitable than json here. Thank you.

### 完整配置示例

```shell
curl http://127.0.0.1:9080/apisix/admin/routes/1 \
Copy link
Member

Choose a reason for hiding this comment

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

Would you update the port number to 9180 like the PR: #7806?

1. remove useless code
2. replace application/json with application/x-ndjson
3. modify cp port from 9080 to 9180
@ccxhwmy
Copy link
Contributor Author

ccxhwmy commented Aug 30, 2022

Need we re-run the ci?

@tzssangglass
Copy link
Member

Need we re-run the ci?

done

@ccxhwmy
Copy link
Contributor Author

ccxhwmy commented Aug 30, 2022

Need we re-run the ci?

done

@tzssangglass Please re-run ci again, Thanks.

@spacewander spacewander merged commit fd1411c into apache:master Aug 31, 2022
hongbinhsu pushed a commit to fitphp/apix that referenced this pull request Sep 10, 2022
* upstream/master: (214 commits)
  feat: set constants.apisix_lua_home for used by plugins (apache#7893)
  fix: response-rewrite plugin might cause Apache AIPSIX hanging (apache#7836)
  test: sleep 1 second in t/cli/test_upstream_mtls.sh (apache#7889)
  fix: reload once when log rotate (apache#7869)
  change: move etcd conf under deployment (apache#7860)
  fix: plugin metadata missing v3 adapter call (apache#7877)
  docs: add ClickHouse and Elasticsearch loggers. (apache#7848)
  docs(plugin): refactor limit-conn.md (apache#7857)
  feat: call `destroy` method when Nginx exits (apache#7866)
  feat: Add ability to inject headers via prefix to otel traces (apache#7822)
  docs(plugin): refactor proxy-cache.md (apache#7858)
  fix: don't enable passive healthcheck by default (apache#7850)
  feat: add openfunction plugin (apache#7634)
  fix(zipkin): send trace IDs with a reject sampling decision (apache#7833)
  fix: Change opentelemetry's span kind to server (apache#7830)
  docs(hmac-auth): additional details for generating signing_string (apache#7816)
  docs: correct the test-nginx description (apache#7818)
  docs: add docs of workflow plugin (apache#7813)
  docs(FAQ): add how to detect APISIX alive status (apache#7812)
  feat: add elasticsearch-logger (apache#7643)
  ...
Liu-Junlin pushed a commit to Liu-Junlin/apisix that referenced this pull request Nov 4, 2022
Co-authored-by: tzssangglass <tzssangglass@gmail.com>
Co-authored-by: Fei Han <97138894+hf400159@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants