Copilot commented on code in PR #13317:
URL: https://github.com/apache/apisix/pull/13317#discussion_r3159259783


##########
t/plugin/ai-proxy-upstream-vars.t:
##########
@@ -0,0 +1,118 @@
+#
+# 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.
+#
+
+=encoding utf-8
+
+Validates that upstream nginx variables ($upstream_status, $upstream_addr,
+$upstream_response_time, $upstream_uri, etc.) are populated when ai-proxy
+sends requests via cosocket transport.
+
+=cut
+
+use t::APISIX 'no_plan';
+
+log_level("info");
+repeat_each(1);
+no_long_string();
+no_root_location();
+
+
+add_block_preprocessor(sub {
+    my ($block) = @_;
+
+    if (!defined $block->request) {
+        $block->set_value("request", "GET /t");
+    }
+});
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: set route with ai-proxy pointing to mock server
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "uri": "/anything",
+                    "plugins": {
+                        "ai-proxy": {
+                            "provider": "openai",
+                            "auth": {
+                                "header": {
+                                    "Authorization": "Bearer test-key"
+                                }
+                            },
+                            "options": {
+                                "model": "gpt-4"
+                            },
+                            "override": {
+                                "endpoint": "http://127.0.0.1:1980";
+                            },
+                            "ssl_verify": false
+                        }
+                    }
+                }]]
+            )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 2: non-streaming request populates upstream variables in access log
+--- request
+POST /anything
+{"model":"gpt-4","messages":[{"role":"user","content":"hello"}]}
+--- more_headers
+X-AI-Fixture: openai/chat-basic.json
+--- error_code: 200
+--- access_log eval
+qr/127\.0\.0\.1:\d+ 200 [\d.]+/
+
+
+
+=== TEST 3: streaming request populates upstream variables in access log
+--- request
+POST /anything
+{"model":"gpt-4","messages":[{"role":"user","content":"hello"}],"stream":true}
+--- more_headers
+X-AI-Fixture: openai/chat-streaming.sse
+--- error_code: 200
+--- access_log eval
+qr/127\.0\.0\.1:\d+ 200 [\d.]+/

Review Comment:
   This new test file is intended to validate population of standard nginx 
upstream variables (eg `$upstream_response_time`, `$upstream_connect_time`, 
`$upstream_header_time`), but the default test `log_format` (from t::APISIX) 
doesn’t log those variables—only `$upstream_addr`, `$upstream_status`, and 
`$apisix_upstream_response_time`. As a result, TEST 2/3 currently can’t 
actually assert that `$upstream_response_time/connect_time/header_time` were 
populated. Consider overriding `access_log_format` in this test (via `--- 
extra_yaml_config`) to include the specific upstream vars you want to validate 
and then assert they are present/non-empty (and numeric).



##########
docs/en/latest/plugins/ai-proxy.md:
##########
@@ -2103,7 +2114,7 @@ Now if you create a Route and send a request following 
the [Proxy to OpenAI exam
 In the gateway's access log, you should see a log entry similar to the 
following:
 
 ```text
-192.168.215.1 - - [21/Mar/2025:04:28:03 +0000] api.openai.com "POST /anything 
HTTP/1.1" 200 804 2.858 "-" "curl/8.6.0" - - - 5765 "http://api.openai.com"; 
"5c5e0b95f8d303cb81e4dc456a4b12d9" "ai_chat" "2858" "gpt-4" "gpt-4" "23" "8"
+192.168.215.1 - - [21/Mar/2025:04:28:03 +0000] api.openai.com "POST /anything 
HTTP/1.1" 200 804 2.858 "-" "curl/8.6.0" api.openai.com:443 200 2.858 
"https://api.openai.com/v1/chat/completions"; "5c5e0b95f8d303cb81e4dc456a4b12d9" 
"ai_chat" "2858" "gpt-4" "gpt-4" "23" "8"
 ```
 
-The access log entry shows the request type is `ai_chat`, Apisix upstream 
response time is `5765` milliseconds, time to first token is `2858` 
milliseconds, Requested LLM model is `gpt-4`. LLM model is `gpt-4`, prompt 
token usage is `23`, and completion token usage is `8`.
+The access log entry shows the upstream address is `api.openai.com:443` with 
status `200`, the request type is `ai_chat`, APISIX upstream response time is 
`2.858` seconds, time to first token is `2858` milliseconds, requested LLM 
model is `gpt-4`, LLM model is `gpt-4`, prompt token usage is `23`, and 
completion token usage is `8`.

Review Comment:
   The access-log example and explanation now imply 
`$apisix_upstream_response_time` is expressed in seconds (showing `2.858`), but 
in the codebase this variable is populated in milliseconds (eg 
`math.floor((ngx.now() - ctx.llm_request_start_time) * 1000)` in the AI 
provider base implementation). This makes the example log line and the 
narrative misleading/confusable with `$request_time` / 
`$upstream_response_time`. Please update the example log entry and the 
accompanying explanation to reflect the correct units/typical value for 
`$apisix_upstream_response_time`, and (optionally) clarify the unit differences 
between `$request_time`, `$upstream_response_time`, and 
`$apisix_upstream_response_time`.



##########
apisix/plugins/ai-transport/http.lua:
##########
@@ -71,20 +72,35 @@ end
 --   {method, scheme, host, port, path, headers, query, body (table),
 --    ssl_verify, ssl_server_name}
 -- @param timeout number Request timeout in milliseconds
--- @return table|nil Response object (with body_reader, headers, status)
+-- @return table|nil Response object (with body_reader, headers, status,
+--   _upstream_addr, _upstream_uri, _connect_time, _header_time, _t0)

Review Comment:
   The request() docstring’s “Response object” field list is out of sync with 
what the code actually attaches to `res`: `_upstream_host` and 
`_upstream_scheme` are also set (and are relied on by ai-proxy/base.lua). 
Please update the return-value comment so it accurately documents all attached 
upstream metadata fields (and their units, if relevant).
   ```suggestion
   --   _upstream_addr, _upstream_host, _upstream_scheme, _upstream_uri,
   --   _connect_time (seconds), _header_time (seconds), _t0)
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to