From 75acf868ef70ce4072f22792905177117655dc6d Mon Sep 17 00:00:00 2001 From: pwspang Date: Mon, 11 Aug 2025 10:45:52 +0800 Subject: [PATCH] Created middleware for logging for endpoint /v1/completions --- analysis/plot_latency_cdf.ipynb | 142 ++++++++++++++++++++++++++ vllm/entrypoints/openai/api_server.py | 17 +++ 2 files changed, 159 insertions(+) create mode 100644 analysis/plot_latency_cdf.ipynb diff --git a/analysis/plot_latency_cdf.ipynb b/analysis/plot_latency_cdf.ipynb new file mode 100644 index 000000000000..7952d79088b3 --- /dev/null +++ b/analysis/plot_latency_cdf.ipynb @@ -0,0 +1,142 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 7, + "id": "3f00e8da", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd \n", + "import seaborn as sns\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "729ab2ff", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
latency
00.131365
10.295574
20.150925
30.042054
40.043637
\n", + "
" + ], + "text/plain": [ + " latency\n", + "0 0.131365\n", + "1 0.295574\n", + "2 0.150925\n", + "3 0.042054\n", + "4 0.043637" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv(\"latency.csv\")\n", + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "b3edfe10", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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jdNSMiq9/Jt5DRERkfk4ciMTLv8mIiKqGkxuZMLl30REZG2KioqwYsUKAEBsbCycnZ1ljsg0TG6sAJd/ExGRNRBCIDc3V7ptq1hzYwW4/JuIiMhymNwQERGRXWFyQ0RERHaFyQ0RERHZFSY3REREZFe4WoqIiIgAPNxywcvLS7ptq5jcEBEREYCH2y/ExsbKHYbZmNxUMyEE7hdp9LZdICIiIsthclONuOUCERFR1WNyU41Kb7kAcNsFIiKyHkVFRVizZg0AYPz48dx+gYxzfFYE3JSOcHXm1YmJiMg6CCGQk5Mj3bZVTG4sTFdTY0jJOhs3pSPclPz1ExERWRq/XS2INTVERETy40X8LMhQTY0hrLMhIiKqOhy5qSK6mhpDWGdDRERUdZjcVBHW1BAREcmD375EREQE4OGWC56entJtW8XkhoiIiAA83H4hPj5e7jDMxoJiIiIisitMboiIiMiucFqKiIiIADzcfmHDhg0AgJiYGG6/QERERLZNCIE///xTum2rOC1FREREdoXJDREREdkVJjdERERkV5jcEBERkV1hckNERER2hauliIiISOLm5iZ3CGZjckNEREQAAKVSibfeekvuMMzGaSkLsuFLAhAREdkNJjcWIoTAwNXpcodBRERU43FaykLuF2lw5noeACDIzx2uzo4yR0RERGScoqIibN68GQAwfPhwbr9Af0uZGAaFQiF3GEREREYRQiAzM1O6bas4LVUFmNcQERHJh8kNERER2RUmN0RERGRXmNwQERGRXWFyQ0RERHaFq6WIiIhIYqvLv0tickNEREQAHm6/MHPmTLnDMBunpYiIiMiuMLkhIiIiu8JpKSIiIgIAFBcXY9u2bQCAwYMHw8nJNtME24yaiIiILE6r1eLChQvSbVvFaSkiIiKyK1aR3KxYsQIBAQFwcXFBaGgojh49WmH7lJQUtG7dGi4uLmjfvj327NlTTZESERGRtZM9udm2bRsSEhKQmJiIn376CR06dEBkZCRu3LhhsP2RI0cwdOhQjBkzBidPnkRUVBSioqLw66+/VnPkREREZI1kT26WLVuGcePGISYmBkFBQVi9ejXc3Nywfv16g+2XL1+OZ555BlOnTkWbNm2wYMECPPHEE/jwww+rOXIiIiKyRrImN2q1GidOnEBERIR0zMHBAREREUhPTzd4Tnp6ul57AIiMjCy3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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "p99 = np.percentile(df['latency'], 99)\n", + "\n", + "sns.ecdfplot(data=df, x='latency')\n", + "\n", + "plt.axvline(p99, color='black', linestyle='--', alpha=0.5)\n", + "plt.axhline(0.99, color='black', linestyle=':', alpha=0.5)\n", + "plt.scatter(p99, 0.99, color='red', zorder=5)\n", + "\n", + "plt.title(\"CDF plot e2e latency of requests\")\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/vllm/entrypoints/openai/api_server.py b/vllm/entrypoints/openai/api_server.py index e7503b965583..4af841a8d4d6 100644 --- a/vllm/entrypoints/openai/api_server.py +++ b/vllm/entrypoints/openai/api_server.py @@ -30,7 +30,10 @@ from vllm.logger import init_logger from vllm.usage.usage_lib import UsageContext +import time + TIMEOUT_KEEP_ALIVE = 5 # seconds +LATENCY_DATA_FILE = 'latency.csv' openai_serving_chat: OpenAIServingChat openai_serving_completion: OpenAIServingCompletion @@ -59,6 +62,20 @@ async def _force_log(): app = fastapi.FastAPI(lifespan=lifespan) +@app.middleware('http') +async def log_latency(request: Request, call_next): + if request.url.path == "/v1/completions" and request.method == "POST": + start_time = time.time() + response = await call_next(request) + latency = time.time() - start_time + logger.info(f"POST /v1/completions latency: {latency:.4f} seconds") + + with open(LATENCY_DATA_FILE, 'a') as file: + file.write(f'{latency}\n') + + return response + else: + return await call_next(request) def parse_args(): parser = make_arg_parser()