-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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: server info #2926
feat: server info #2926
Changes from 14 commits
c66232a
b47597b
a2fa893
f2f3e39
c84ad97
4bd7a3e
61d2695
921b660
f67fdc8
acd5726
3dd0086
fc11d3d
02093a2
803d75b
48bb247
3561437
e57628d
2b65de4
8ac598f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
-- | ||
-- Licensed to the Apache Software Foundation (ASF) under one or more | ||
-- contributor license agreements. See the NOTICE file distributed with | ||
-- this work for additional information regarding copyright ownership. | ||
-- The ASF licenses this file to You under the Apache License, Version 2.0 | ||
-- (the "License"); you may not use this file except in compliance with | ||
-- the License. You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
-- Unless required by applicable law or agreed to in writing, software | ||
-- distributed under the License is distributed on an "AS IS" BASIS, | ||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
-- See the License for the specific language governing permissions and | ||
-- limitations under the License. | ||
-- | ||
local require = require | ||
local core = require("apisix.core") | ||
local timers = require("apisix.timers") | ||
|
||
local ngx_time = ngx.time | ||
local ngx_timer_at = ngx.timer.at | ||
local type = type | ||
local ceil = math.ceil | ||
|
||
local boot_time = os.time() | ||
local plugin_name = "server-info" | ||
local schema = { | ||
type = "object", | ||
additionalProperties = false, | ||
} | ||
local attr_schema = { | ||
type = "object", | ||
properties = { | ||
report_interval = { | ||
type = "integer", | ||
description = "server info reporting interval (unit: second)", | ||
default = 60, | ||
minimum = 60, | ||
tokers marked this conversation as resolved.
Show resolved
Hide resolved
|
||
maximum = 3600, | ||
}, | ||
report_ttl = { | ||
type = "integer", | ||
description = "live time for server info in etcd", | ||
default = 7200, | ||
minimum = 3600, | ||
maximum = 86400, | ||
} | ||
} | ||
} | ||
|
||
local internal_status = ngx.shared.internal_status | ||
if not internal_status then | ||
error("lua_shared_dict \"internal_status\" not configured") | ||
end | ||
|
||
|
||
local _M = { | ||
version = 0.1, | ||
priority = 990, | ||
name = plugin_name, | ||
schema = schema, | ||
} | ||
|
||
|
||
local function uninitialized_server_info() | ||
return { | ||
etcd_version = "unknown", | ||
hostname = core.utils.gethostname(), | ||
id = core.id.get(), | ||
version = core.version.VERSION, | ||
up_time = ngx_time() - boot_time, | ||
last_report_time = -1, | ||
} | ||
end | ||
|
||
|
||
-- server information will be saved into shared memory only if the key | ||
-- "server_info" not exist if excl is true. | ||
local function save(data, excl) | ||
local handler = excl and internal_status.add or internal_status.set | ||
|
||
local ok, err = handler(internal_status, "server_info", data) | ||
if not ok then | ||
if excl and err == "exists" then | ||
return true | ||
end | ||
|
||
return nil, err | ||
end | ||
|
||
return true | ||
end | ||
|
||
|
||
local function encode_and_save(server_info, excl) | ||
local data, err = core.json.encode(server_info) | ||
if not data then | ||
return nil, err | ||
end | ||
|
||
return save(data, excl) | ||
end | ||
|
||
|
||
local function get() | ||
local data, err = internal_status:get("server_info") | ||
if err ~= nil then | ||
return nil, err | ||
end | ||
|
||
if not data then | ||
return uninitialized_server_info() | ||
end | ||
|
||
local server_info, err = core.json.decode(data) | ||
if not server_info then | ||
return nil, err | ||
end | ||
|
||
server_info.up_time = ngx_time() - boot_time | ||
return server_info | ||
end | ||
|
||
|
||
local function report(premature, report_ttl) | ||
if premature then | ||
return | ||
end | ||
|
||
local server_info, err = get() | ||
if not server_info then | ||
core.log.error("failed to get server_info: ", err) | ||
return | ||
end | ||
|
||
if server_info.etcd_version == "unknown" then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if APISIX runs under standalone mode? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since now server-info plugin only reports the basic info to etcd, when APISIX runs under standalone mode, we don't need to launch the timer. |
||
local res, err = core.etcd.server_version() | ||
if not res then | ||
core.log.error("failed to fetch etcd version: ", err) | ||
return | ||
|
||
elseif type(res.body) ~= "table" then | ||
core.log.error("failed to fetch etcd version: bad version info") | ||
return | ||
|
||
else | ||
server_info.etcd_version = res.body.etcdcluster | ||
end | ||
end | ||
|
||
server_info.last_report_time = ngx_time() | ||
|
||
local data, err = core.json.encode(server_info) | ||
if not data then | ||
core.log.error("failed to encode server_info: ", err) | ||
return | ||
end | ||
|
||
local key = "/data_plane/server_info/" .. server_info.id | ||
local ok, err = core.etcd.set(key, data, report_ttl) | ||
if not ok then | ||
core.log.error("failed to report server info to etcd: ", err) | ||
return | ||
end | ||
|
||
local ok, err = save(data, false) | ||
if not ok then | ||
core.log.error("failed to encode and save server info: ", err) | ||
return | ||
end | ||
end | ||
|
||
|
||
function _M.check_schema(conf) | ||
local ok, err = core.schema.check(schema, conf) | ||
if not ok then | ||
return false, err | ||
end | ||
|
||
return true | ||
end | ||
|
||
|
||
function _M.init() | ||
local ok, err = encode_and_save(uninitialized_server_info(), true) | ||
spacewander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if not ok then | ||
core.log.error("failed to encode and save server info: ", err) | ||
end | ||
|
||
if core.config ~= require("apisix.core.config_etcd") then | ||
-- we don't need to report server info if etcd is not in use. | ||
return | ||
end | ||
|
||
local local_conf = core.config.local_conf() | ||
local attr = core.table.try_read_attr(local_conf, "plugin_attr", | ||
plugin_name) | ||
spacewander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
local ok, err = core.schema.check(attr_schema, attr) | ||
if not ok then | ||
core.log.error("failed to check plugin_attr: ", err) | ||
return | ||
end | ||
|
||
local threshold = ceil(attr.report_interval / timers.check_interval()) | ||
local report_ttl = attr.report_ttl | ||
local count = 0 | ||
|
||
local fn = function() | ||
count = count + 1 | ||
if count == threshold then | ||
report(nil, report_ttl) | ||
spacewander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
count = 0 | ||
end | ||
end | ||
|
||
local ok, err = ngx_timer_at(0, report, report_ttl) | ||
if not ok then | ||
core.log.error("failed to create initial timer to report server info: ", err) | ||
return | ||
end | ||
|
||
timers.register_timer("plugin#server-info", fn, true) | ||
|
||
core.log.info("timer created to report server info, interval: ", | ||
attr.report_interval) | ||
end | ||
|
||
|
||
function _M.destory() | ||
timers.unregister_timer("plugin#server-info", true) | ||
end | ||
|
||
|
||
return _M |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -238,6 +238,7 @@ plugins: # plugin list (sorted in alphabetical order) | |
- uri-blocker | ||
- wolf-rbac | ||
- zipkin | ||
- server-info | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should disable this plugin by default There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason for disabling this plugin by default? Users are no feeling about the behavior of server-info. |
||
|
||
stream_plugins: | ||
- mqtt-proxy | ||
|
@@ -252,3 +253,6 @@ plugin_attr: | |
endpoint_addr: http://127.0.0.1:12800 | ||
prometheus: | ||
export_uri: /apisix/prometheus/metrics | ||
server-info: | ||
report_interval: 60 # server info report interval (unit: second) | ||
report_ttl: 3600 # live time for server info in etcd (unit: second) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make a try:
use
io.popen("/bin/hostname")
to fetch the host nameThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That'd be concise, i will try it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.