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"
}

  

posted @ 2026-01-14 11:23  吃吃吃大王  阅读(7)  评论(0)    收藏  举报