Embedded UI Proxy
は、Python アプリケーションにあたかも Web UI が埋め込まれているかのように、外部の Web UI をプロキシして、単一のポートで API と UI を提供する方法を示すサンプルアプリケーションです。
UI は別途ホスティングされ、Python アプリケーションがそこへのプロキシとして動作します。
この仕組みにより、Python アプリケーションが API サーバーとプロキシサーバーの両方の役割を果たします。
Browser → :8080 → Python App → Proxy → UI Remote URL (Static Page)
↓
/rpc API
デフォルトは http://localhost:5173
ですが、--ui-remote-url
で任意の URL に変更できます。
CLI ツールに Web UI を組み込む際、バイナリに静的ファイルを埋め込んだりするのが嫌だなとおもっていたのですが、 DuckDB UI が HTTP Proxy を利用しているのを見て、マネしてみました。
実際に C++ 製の負荷試験ツールに DuckDB (C API) を組み込み、さらに Boost の Beast を利用して、HTTP Proxy を実装し UI を組み込む事に成功しました。
やってること自体はただのリバースプロキシなので難しい話ではありませんが、この仕組みは DuckDB との相性がとても良くて、DuckDB にメトリクスを保存して、ブラウザから SQL クエリで分析したり、グラフ化したりすることがバイナリデータを埋め込むことなく、実現できます。
- Python や SQL は適当です
- React や TypeScript も適当です
- セキュリティは まったく 考慮していません
- psutil を利用したメトリクス監視ダッシュボード
- DuckDB に時系列データを保存
- React と Tailwind CSS と wouter と uPlot でリアルタイムダッシュボード
- JSON-RPC 2.0 over HTTP/1.1
psutil を使って CPU とメモリの使用率を 1 秒ごとに収集し、DuckDB に保存します。UI は API 経由で最新データを取得してグラフ化します。
- 現在の CPU 使用率をリアルタイムグラフで表示
- メモリ使用率と使用量(MB)をリアルタイムグラフで表示
- 1 秒ごとに最新データを自動取得
- 直近 60 秒間のメトリクス推移を可視化
DuckDB に対して直接 SQL クエリを実行できます。
-- 直近 10 件のメトリクスを取得
SELECT * FROM system_metrics
ORDER BY timestamp DESC
LIMIT 10
-- 平均 CPU 使用率を計算
SELECT AVG(cpu_percent) as avg_cpu
FROM system_metrics
-- 時系列でグループ化
SELECT
DATE_TRUNC('minute', timestamp) as minute,
AVG(cpu_percent) as avg_cpu,
AVG(memory_percent) as avg_memory
FROM system_metrics
GROUP BY minute
ORDER BY minute DESC
SQL クエリの結果をカスタムチャートで可視化します。
Python アプリケーションを起動してください。
uv sync
uv run server
UI 開発サーバーの起動してください。
cd ui
pnpm install
pnpm dev
その後、ブラウザで http://localhost:8080 にアクセスしてください。
/rpc
への API リクエストは Python アプリケーションが処理- その他のリクエストは UI の開発サーバーにプロキシ
# 別の URL にプロキシする例
uv run server --ui-remote-url https://ui.example.com
uv run server [OPTIONS]
オプション:
--ui-remote-url URL UI プロキシ先の URL (デフォルト: http://localhost:5173)
--port PORT サーバーポート (デフォルト: 8080)
--host HOST サーバーホスト (デフォルト: 0.0.0.0)
--db-path PATH DuckDB データベースパス (デフォルト: metrics.duckdb)
Tailscale の IP アドレスを指定して起動することで UI へのアクセスを制限することが出来ます。
uv run server --host 100.x.y.z
Apache License 2.0
Copyright 2025-2025, @voluntas
Licensed 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.