0.6.4-Orange网关增强divide插件日志输出(打印各环节的性能数据和路由规则)
1、修改divide插件主代码文件:/usr/local/orange/plugins/divide/handler.lua(完整代码,可以直接复制使用)
local ipairs = ipairs
local type = type
local utils = require("orange.utils.utils")
local stringy = require("orange.utils.stringy")
local orange_db = require("orange.store.orange_db")
local judge_util = require("orange.utils.judge")
local extractor_util = require("orange.utils.extractor")
local handle_util = require("orange.utils.handle")
local BasePlugin = require("orange.plugins.base_handler")
local function ensure_end(uri)
if not stringy.endswith(uri, "/") then
uri = uri.."/"
end
return uri
end
local function filter_rules(sid, plugin, ngx_var, ngx_var_uri, ngx_var_host, selector_cache)
local rules = orange_db.get_json(plugin .. ".selector." .. sid .. ".rules")
if not rules or type(rules) ~= "table" or #rules <= 0 then
return false
end
for i, rule in ipairs(rules) do
if rule.enable == true then
-- judge阶段
local pass = judge_util.judge_rule(rule, plugin)
-- extract阶段
local variables = extractor_util.extract_variables(rule.extractor)
-- handle阶段
if pass then
if rule.log == true then
ngx.log(ngx.INFO, "[Divide-Match-Rule] ", rule.name, " host:", ngx_var_host, " uri:", ngx_var_uri)
end
local extractor_type = rule.extractor.type
if rule.upstream_url then
if not rule.upstream_host or rule.upstream_host=="" then -- host默认取请求的host
ngx_var.upstream_host = ngx_var_host
else
ngx_var.upstream_host = handle_util.build_upstream_host(extractor_type, rule.upstream_host, variables, plugin)
end
ngx_var.upstream_url = handle_util.build_upstream_url(extractor_type, rule.upstream_url, variables, plugin)
-- ========== 新增:设置路由信息变量 ==========
-- 获取selector名称
local selector_name = "unknown"
if selector_cache and selector_cache[sid] then
selector_name = selector_cache[sid].name or "unnamed"
end
-- 设置nginx变量用于access.log记录
ngx.var.orange_selector_id = sid
ngx.var.orange_selector_name = selector_name
ngx.var.orange_rule_id = rule.id or "unknown"
ngx.var.orange_rule_name = rule.name or "unnamed"
ngx.var.orange_match_type = extractor_type or "direct"
ngx.var.orange_upstream_url = ngx_var.upstream_url
ngx.var.orange_upstream_host = ngx_var.upstream_host
-- 保存到ngx.ctx供其他插件使用
ngx.ctx.divide_match = {
selector_id = sid,
selector_name = selector_name,
rule_id = rule.id,
rule_name = rule.name,
match_type = extractor_type,
upstream_url = ngx_var.upstream_url,
upstream_host = ngx_var.upstream_host,
original_host = ngx_var_host,
original_uri = ngx_var_uri,
enable = rule.enable,
log = rule.log
}
-- 记录详细的匹配信息到error.log
ngx.log(ngx.INFO, "[DIVIDE_ROUTE_MATCH] ",
"selector_id=", sid,
"|selector_name=", selector_name,
"|rule_id=", (rule.id or "unknown"),
"|rule_name=", rule.name,
"|match_type=", extractor_type,
"|host=", ngx_var_host,
"|uri=", ngx_var_uri,
"|upstream=", ngx_var.upstream_url,
"|upstream_host=", ngx_var.upstream_host)
-- ========== 新增结束 ==========
ngx.log(ngx.INFO, "[Divide-Match-Rule:upstream] ", rule.name, " extractor_type:", extractor_type,
" upstream_host:", ngx_var.upstream_host, " upstream_url:", ngx_var.upstream_url)
else
ngx.log(ngx.INFO, "[Divide-Match-Rule:error] no upstream host or url. ", rule.name, " host:", ngx_var_host, " uri:", ngx_var_uri)
end
return true
else
if rule.log == true then
ngx.log(ngx.INFO, "[Divide-NotMatch-Rule] ", rule.name, " host:", ngx_var_host, " uri:", ngx_var_uri)
end
end
end
end
return false
end
local DivideHandler = BasePlugin:extend()
DivideHandler.PRIORITY = 2000
function DivideHandler:new(store)
DivideHandler.super.new(self, "Divide-plugin")
self.store = store
end
function DivideHandler:access(conf)
DivideHandler.super.access(self)
local enable = orange_db.get("divide.enable")
local meta = orange_db.get_json("divide.meta")
local selectors = orange_db.get_json("divide.selectors")
local ordered_selectors = meta and meta.selectors
-- ========== 新增:缓存selector信息 ==========
-- 缓存selector信息供filter_rules使用
local selector_cache = {}
if selectors then
for sid, selector in pairs(selectors) do
selector_cache[sid] = selector
end
end
-- 保存到ngx.ctx中供filter_rules使用
ngx.ctx.selector_cache = selector_cache
-- ========== 新增结束 ==========
if not enable or enable ~= true or not meta or not ordered_selectors or not selectors then
-- ========== 新增:未匹配时设置默认值 ==========
ngx.var.orange_selector_id = "-"
ngx.var.orange_selector_name = "-"
ngx.var.orange_rule_id = "-"
ngx.var.orange_rule_name = "-"
ngx.var.orange_match_type = "-"
ngx.var.orange_upstream_url = "-"
ngx.var.orange_upstream_host = "-"
ngx.log(ngx.INFO, "[DIVIDE_ROUTE_MATCH] no_route_enabled_or_configured")
-- ========== 新增结束 ==========
return
end
local ngx_var = ngx.var
local ngx_var_uri = ngx_var.uri
local ngx_var_host = ngx_var.host
-- ========== 新增:初始化变量 ==========
-- 设置默认值,如果没有匹配会使用这些值
ngx.var.orange_selector_id = "-"
ngx.var.orange_selector_name = "-"
ngx.var.orange_rule_id = "-"
ngx.var.orange_rule_name = "-"
ngx.var.orange_match_type = "-"
ngx.var.orange_upstream_url = "-"
ngx.var.orange_upstream_host = "-"
-- ========== 新增结束 ==========
for i, sid in ipairs(ordered_selectors) do
ngx.log(ngx.INFO, "==[Divide][PASS THROUGH SELECTOR:", sid, "]")
local selector = selector_cache[sid]
if selector and selector.enable == true then
local selector_pass
if selector.type == 0 then -- 全流量选择器
selector_pass = true
else
selector_pass = judge_util.judge_selector(selector, "divide")-- selector judge
end
if selector_pass then
if selector.handle and selector.handle.log == true then
ngx.log(ngx.INFO, "[Divide][PASS-SELECTOR:", sid, "] ", ngx_var_uri)
end
local stop = filter_rules(sid, "divide", ngx_var, ngx_var_uri, ngx_var_host, selector_cache)
if stop then -- 不再执行此插件其他逻辑
return
end
else
if selector.handle and selector.handle.log == true then
ngx.log(ngx.INFO, "[Divide][NOT-PASS-SELECTOR:", sid, "] ", ngx_var_uri)
end
end
-- if continue or break the loop
if selector.handle and selector.handle.continue == true then
-- continue next selector
else
break
end
end
end
-- ========== 新增:循环结束仍未匹配的日志 ==========
if ngx.var.orange_rule_name == "no_match" then
ngx.log(ngx.INFO, "[DIVIDE_ROUTE_MATCH] no_rule_matched|",
"host=", ngx_var_host,
"|uri=", ngx_var_uri,
"|selectors_tried=", #ordered_selectors)
end
-- ========== 新增结束 ==========
end
return DivideHandler
2、修改nginx.conf配置
http块
log_format main escape=json '{"timestamp": "$time_local", '
'"remote_addr": "$remote_addr", '
'"message": "$request", '
'"status": "$status", '
'"bytes": "$body_bytes_sent", '
'"http_referer": "$http_referer", '
'"host": "$host", '
'"server_addr": "@$server_addr", '
'"http_user_agent": "$http_user_agent", '
'"request_time": "$request_time", '
'"orange_latency_ms": "$orange_proxy_latency", '
'"upstream_latency_ms": "$upstream_response_time", '
'"ssl_protocol": "$ssl_protocol", '
'"ssl_cipher": "$ssl_cipher", '
'"http_x_forwarded_for": "$http_x_forwarded_for", '
'"up_addr": "$upstream_addr", '
'"upstream_status": "$upstream_status", '
'"upstream_response_length": "$upstream_response_length", '
'"selector_id": "$orange_selector_id", '
'"selector_name": "$orange_selector_name", '
'"rule_id": "$orange_rule_id", '
'"rule_name": "$orange_rule_name"'
'}';
server块
注意:有多个server块的每个都要加,不然会出现请求443端口打印路由信息,80端口不打印路由信息,注意配置顺序,最好和我的一样!
server {
listen 443 ssl;
server_name localhost;
location = /favicon.ico {
log_not_found off;
access_log off;
}
#新增开始
set $orange_selector_id "-";
set $orange_rule_name "-";
set $orange_upstream_host "-";
set $orange_matched_uri "-";
set $orange_selector_name "-";
set $orange_rule_id "-";
set $orange_upstream_url "-";
set $orange_match_type "-";
set $orange_selector_name "-";
set $orange_proxy_latency "0";
set $orange_upstream_latency "0";
set $orange_total_latency "0";
#新增结束
location / {
access_log ./logs/access_443.log main;
error_log ./logs/error_443.log error;
set $upstream_host $host;
set $upstream_url 'http://default_upstream';
rewrite_by_lua_block {
local orange = context.orange
orange.redirect()
orange.rewrite()
}
access_by_lua_block {
local orange = context.orange
orange.access()
}
#旧的注释或删除
header_filter_by_lua_block {
local orange = context.orange
orange.body_filter()
}
#旧的注释或删除
# 新增header_filter用来捕获性能指标
header_filter_by_lua_block {
local orange = context.orange
orange.header_filter()
-- 获取Orange性能头
local proxy_latency = ngx.header["X-Orange-Proxy-Latency"]
local upstream_latency = ngx.header["X-Orange-Upstream-Latency"]
if proxy_latency then
ngx.var.orange_proxy_latency = proxy_latency
end
if upstream_latency then
ngx.var.orange_upstream_latency = upstream_latency
ngx.header["X-Orange-Upstream-Latency"] = nil
end
-- 计算总延迟(毫秒)
local total_ms = 0
if proxy_latency then
total_ms = total_ms + (tonumber(proxy_latency) or 0)
end
if upstream_latency then
total_ms = total_ms + (tonumber(upstream_latency) or 0)
end
ngx.var.orange_total_latency = tostring(total_ms)
}
# 新增结束
# proxy
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header Host $upstream_host;
proxy_pass $upstream_url;
body_filter_by_lua_block {
local orange = context.orange
orange.body_filter()
}
log_by_lua_block {
local orange = context.orange
orange.log()
}
location /robots.txt {
return 200 'User-agent: *\nDisallow: /';
}
}
日志打印效果:
{
"timestamp": "14/Jan/2026:10:42:52 +0800",
"remote_addr": "192.168.2.2",
"message": "GET /abc HTTP/1.1",
"status": "200",
"bytes": "51",
"http_referer": "",
"host": "192.168.1.99",
"server_addr": "@192.168.1.99",
"http_user_agent": "curl/7.29.0",
"request_time": "0.036",
"orange_latency_ms": "0",
"upstream_latency_ms": "0.029",
"ssl_protocol": "",
"ssl_cipher": "",
"http_x_forwarded_for": "",
"up_addr": "192.168.1.100:80",
"upstream_status": "200",
"upstream_response_length": "51",
"selector_id": "ed5a964a-aa61-4b9a-9e7b-fe9ce2685c17",
"selector_name": "选择器123",
"rule_id": "d76bef81-6b36-450e-85a0-5341b4ecd2e5",
"rule_name": "规则666"
}

浙公网安备 33010602011771号