Spanlens について
Spanlensは、モデルへのリクエストやエージェントのワークフローを監視する、開発者向けのオープンソースLLMオブザーバビリティサービスです。プロキシで利用状況とトレースを記録し、付属のMCPサーバーからクライアントがデータを照会できます。Dockerでセルフホストすることもできます。
主な機能
- 01リクエスト、トークン、コスト、レイテンシの記録
- 02複数ステップのエージェントワークフローの追跡
- 03異常と予算しきい値の監視
- 04プロンプトのバージョン管理とA/Bテスト
- 05リクエストとレスポンスのPII・インジェクション検査
活用シーン
- 01高コストまたは低速なLLMリクエストの特定
- 02エージェントワークフローの各ステップの追跡
- 03リリース前のプロンプトバージョン比較
- 04MCPクライアントからのリクエストログ確認
MCP 対応
SpanlensにはMCPサーバーが付属し、CursorやClaude Desktopなどのクライアントからオブザーバビリティデータを照会できます。OTLP/HTTP JSON形式のトレース取り込みにも対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Spanlens
1 行で有効にできる、オープンソースの LLM 可観測性ツールです。 OpenAI、Anthropic、Gemini のクライアントを Spanlens に向けると、すべての呼び出しがコスト、トークン数、レイテンシ、エージェントの詳細なトレースとともに記録されます。SDK の書き換えも、プラットフォームの移行も不要です。11 のプロバイダーに対応し、Vercel AI SDK、LangChain、LlamaIndex とのネイティブ連携も備えています。さらに、同梱の MCP サーバーを通じて、Cursor や Claude Desktop からすべてをクエリできます。Docker コマンド 1 つでセルフホストできます。MIT ライセンスです。
開発した理由。 OpenAI と Gemini を使った LLM アプリをリリースしたところ、行き詰まりました。プロバイダーのダッシュボードで分かるのは合計支出だけで、それ以外は何も分かりません。どの機能が最も多くのトークンを消費したのか、タスクごとにどのモデルが最も安価なのか、各エンドポイントに実際いくらかかっているのかを把握できませんでした。Spanlens は、私が欲しかったレイヤーです。1 行で有効になり、クリティカルパスに影響せず、オープンソースなので、私たちが実際に運用しているコードをそのままセルフホストできます。
⭐ Spanlens が役に立ったら、リポジトリにスターを付けてください。すぐに終わるうえ、ほかの開発者にプロジェクトを見つけてもらうための、何よりの助けになります。
ホスト版: spanlens.io · npm:
@spanlens/sdk· PyPI:spanlens· CLI:@spanlens/cli· MCP:@spanlens/mcp-server· ステータス: status.spanlens.io · 変更履歴: spanlens.io/changelog

ライブデモ(登録不要):spanlens.io/demo/requests


Spanlens を選ぶ理由
- Helicone は買収されており、今後のロードマップは不透明です。
- Langfuse は高機能ですが、セットアップが複雑で、規模を拡大するとコストがかさみます。
- Spanlens は、実際の本番環境のニーズの 80%をカバーする機能の 20%を提供します。リクエストログ、コスト追跡、エージェントのトレース、異常検知、PII スキャン、プロンプトのバージョン管理を、すっきりした UI、2 分で完了するセットアップ、成長しても負担にならない料金で利用できます。
| Spanlens | Langfuse Pro | Helicone | |
|---|---|---|---|
| オープンソース | ✅ MIT | ✅ MIT | ✅ MIT |
| セルフホスト可能 | ✅ Docker のワンライナー | ✅ | ✅ |
| 無料プラン | 50K リクエスト/月 | 50K イベント/月 | 10K リクエスト/月 |
| チームプラン(1M リクエスト/月) | $149/月 | $271/月 | ~$200/月 |
| エージェントのトレース | ✅ | ✅ | ⚠️ 制限あり |
| LLM-as-judge による評価 | ✅ | ✅ | ❌ |
| PII + インジェクションスキャン | ✅ | ❌ | ❌ |
| モデルの推奨 | ✅ | ❌ | ❌ |
| プロンプトの A/B テスト | ✅ | ✅ | ❌ |

予測しやすい請求で、クォータの急な上限はありません。 無料プランでは 50K リクエストで 429 による厳格な制限がかかるため、開発中にループが暴走しても料金は発生しません。有料プランでは、管理者が設定できるハード上限までは、承認済みの超過利用分(Pro:100K あたり +$8、Team:100K あたり +$5)を適用するソフト制限を使用します。これにより、トラフィックが急増してもリクエストを落とすのではなく、適正な料金が請求されます。
シート数:Free 1 · Pro 3 · Team 10 · Enterprise 無制限。シートはメンバーまたは保留中の招待を指し、シートごとの料金はありません。セルフホスト環境にはシート数の上限がありません。すべての有料プランでプロジェクト数は無制限です。
⭐ この取り組みを気に入っていただけましたか?スターを付けると、重厚で買収されたツールが多いこの分野で、軽量なオープンソースの代替手段をより多くの開発者に知ってもらえます。
⚡ 30 秒でクイックスタート
TypeScript / JavaScript(Next.js)
npx @spanlens/cli init
ウィザードでは、次の操作を行います。
- パッケージマネージャー(npm / pnpm / yarn / bun)を使って
@spanlens/sdkをインストールします .env.localにSPANLENS_API_KEYを書き込みます- すべての
new OpenAI({ apiKey, baseURL })をcreateOpenAI()に書き換えます
Spanlens API キーを一度貼り付け、2 つの確認に応答すれば完了です。LLM 呼び出しは Spanlens プロキシ経由で送信され、www.spanlens.io/requests で確認できます。
TypeScript の手動セットアップ
import { createOpenAI } from '@spanlens/sdk/openai'
const openai = createOpenAI() // reads SPANLENS_API_KEY, uses Spanlens proxy baseURL
Python
pip install "spanlens[openai]"
from spanlens.integrations.openai import create_openai
client = create_openai() # reads SPANLENS_API_KEY from env
res = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
Python でのエージェントトレース(複数ステップ、非同期、ツール呼び出し)については、Python SDK README をご覧ください。
フレームワークとの統合
すでにオーケストレーションフレームワークをお使いですか?Spanlens をコールバックとして接続できます。コードを書き換える必要はありません。
Vercel AI SDK(Next.js / エッジ環境に対応)
import { SpanlensClient } from '@spanlens/sdk'
import { createSpanlensTracker } from '@spanlens/sdk/vercel-ai'
const client = new SpanlensClient({ apiKey: process.env.SPANLENS_API_KEY! })
// generateText / generateObject have no onFinish, so pass the awaited result to end()
const tracker = createSpanlensTracker({ client, modelName: 'gpt-4o' })
const result = await generateText({
model: openai('gpt-4o'),
messages,
onStepFinish: tracker.onStepFinish,
}).catch(async (err) => {
await tracker.onError(err) // ends the span as an error
throw err
})
await tracker.end(result) // records the run's total usage
// streamText / streamObject close the span from their callbacks
const streamTracker = createSpanlensTracker({ client, modelName: 'gpt-4o' })
const stream = streamText({
model: openai('gpt-4o'),
messages,
onStepFinish: streamTracker.onStepFinish,
onFinish: streamTracker.onFinish,
onError: streamTracker.onError,
})
各更新はバックグラウンドで送信されるため、トラッカーが Spanlens の応答を待つことはありません。サーバーレスハンドラーでは、関数がフリーズしてもデータが失われないよう、戻る前に await client.flush() を実行してください。
LangChain JS / LangGraph
import { createSpanlensCallbackHandler } from '@spanlens/sdk/langchain'
const handler = createSpanlensCallbackHandler({ client })
await chain.invoke({ input }, { callbacks: [handler] }) // LangChain
await graph.invoke({ input }, { callbacks: [handler] }) // LangGraph
LlamaIndex TS
import { Settings } from 'llamaindex'
import { registerSpanlensCallbacks } from '@spanlens/sdk/llamaindex'
const unregister = registerSpanlensCallbacks(Settings, { client })
// ... run queries ... unregister() on shutdown
Python:LangChain:from spanlens.integrations.langchain import SpanlensCallbackHandler。同じ BaseCallbackHandler コントラクトを使用し、チェーン、LCEL、LangGraph で動作します。
その他の統合:AWS Bedrock、CrewAI、Flowise、Instructor、LlamaIndex、OpenAI Assistants、MCP サーバー。セットアップの詳細な手順は、spanlens.io/docs/integrations をご覧ください。
Ollama(ローカル LLM):Ollama はお使いのマシン上で動作するため、ホスト型プロキシを経由しません。createOllama() で準備済みのクライアントを取得し、各呼び出しを observeOllama() でラップすると、スパンがログに記録され、Ollama としてタグ付けされます。
import { SpanlensClient } from '@spanlens/sdk'
import { createOllama, observeOllama } from '@spanlens/sdk/ollama'
const spanlens = new SpanlensClient({ apiKey: process.env.SPANLENS_API_KEY! })
const ollama = createOllama() // points at http://localhost:11434/v1
const trace = spanlens.startTrace({ name: 'chat' })
const res = await observeOllama(trace, 'chat', (headers) =>
ollama.chat.completions.create(
{ model: 'llama3.1', messages: [{ role: 'user', content: 'Hello' }] },
{ headers },
),
)
await trace.end({ status: 'completed' })
表示される内容

すべてのリクエストが、モデル、プロバイダー、レイテンシ、トークン数、コスト、完全なプロンプトとレスポンス本文とともに記録されます。フィルタリング、検索、エクスポートが可能です。ストリーミングレスポンスは自動的に再構築されます。
利用できる機能
| 機能 | 説明 |
|---|---|
| リクエストログ | すべての LLM 呼び出しについて、モデル、トークン数、コスト、レイテンシー、リクエスト/レスポンスの本文全体を記録します(ストリーミングも再構築して記録します)。 |
| エージェントのトレース | マルチステップのワークフローを、クリティカルパスを強調表示したガント形式のウォーターフォールスパンツリーで可視化します(ファンアウト全体にわたる最長の依存チェーンであり、単一スパンの最遅時間だけではありません)。さらに、LangChain/LangGraph のコールバックトレース用に、ノードとエッジで構成されるグラフトポロジービューも表示します。 |
| コスト追跡 | リクエストごとのコスト内訳、日次の集計、予算アラートを提供します。プロンプトキャッシュのトークン(Anthropic の cache_read/cache_creation、OpenAI の prompt_tokens_details.cached_tokens)は個別に解析され、割引料金で課金されるため、定価だけでなく実際のキャッシュ節約額を確認できます。 |
| エンドユーザーごとの分析 | x-spanlens-user(SDK:withUser()/with_user())で呼び出しにタグを付けると、/users ページにユーザーごとのコスト、トークン数、エラー、モデル、最終確認日時が表示されます。 |
| 異常検知 | 7 日間のベースラインと比較したレイテンシー、コスト、エラー率の 3σ の逸脱を検知し、根本原因のヒント(トークン数の差分、HTTP ステータスの内訳)を提示します。 |
| アラート | 予算、エラー率、p95 レイテンシーのしきい値ルールを設定できます。メール(Resend)、Slack、Discord の Webhook で通知します。15 分間隔の cron で評価し、少なくとも 1 回配信します。 |
| PII とプロンプトインジェクションのスキャン | リクエストとレスポンスの本文を正規表現ベースで検出します。必要に応じてプロジェクト単位でインジェクションをブロック(422)でき、ワークスペースのオーナーには即時にアラートメールを送信します。 |
| 節約額(モデルの推奨) | /savings ダッシュボードに、より安価なモデルのプロファイルに合致する呼び出しを表示します(「gpt-4o の呼び出しは分類タスクのようです。gpt-4o-mini をお試しください」)。推定月間節約額も表示します。月初からのプロンプトキャッシュによる節約額カードには、割引されたキャッシュ読み取りトークンによって支払わずに済んだ金額(USD)が表示されます。 |
| レスポンスキャッシュ | x-spanlens-cache: true(または最大 24 時間の秒単位の TTL。SDK:withCache())でリクエストごとに有効にできます。同じリクエスト本文と完全一致する場合、プロバイダーを呼び出さずに保存済みのレスポンスを返し、コストゼロでログに記録します。API キーごとにスコープが設定されるため、キーをまたいでデータが漏れることはありません。ストリーミングなし、200 のみが対象です。 |
| メールダイジェストと健全性アラート | 週次ワークスペースダイジェスト(リクエスト数、前週比を含むコスト、上位モデル、異常)を毎週月曜日に送信します。また、トラフィックを送信していたワークスペースが 24 時間にわたって突然無通信になると、データ無通信アラートが管理者にメールで通知します。これにより、キーの破損や環境変数の削除を、気付かれないままの顧客離れにつながる前に検出できます。 |
| プロンプトのバージョン管理と A/B テスト | プロンプトテンプレートを登録し、トラフィックを分割した実験を実行できます。レイテンシー/コスト/エラー率についてバージョンを並べて比較し、レイテンシーとコストにはWelch の t 検定、エラー率には z 検定を用いて報告するため、単なる平均値ではなく統計的有意性を確認できます。 |
| プロンプトプレイグラウンド | ダッシュボードで変数を注入して任意のプロンプトバージョンを実行し、リリース前に実際のコストとレスポンスを確認できます。 |
| データセット | 任意のプロンプトバージョンやモデルで再実行できる、再利用可能な(input, expected_output)テストセットです。ダッシュボードから CSV/JSONL ファイルを直接アップロードするか、プログラムから POST できます。オフライン評価とリグレッションチェックに利用できます。 |
| 評価と実験 | 評価基準のアンカーと合格率の信頼区間を備えた、LLM-as-judge 評価器を作成できます(評価基準に対して最も安価、または最適な OpenAI、Anthropic、Gemini のいずれかで判定)。プロンプトを直接比較するペアワイズ A 対 B モード、最終テキストだけでなくトレース全体を採点するエージェント軌跡モード、再実行時の重複した LLM 呼び出しを省く (evaluator, response) キーによる判定結果キャッシュに対応しています。人手によるアノテーションはサンプリング用にキューに登録され、判定結果と人手評価の一致度は、数値の場合はPearson の r、カテゴリの場合はCohen の κで測定します。 |
| OpenAPI 3.0 仕様と Swagger UI | GET /api/v1/openapi.json で機械可読な仕様を、GET /api/v1/docs でインタラクティブなエクスプローラーを利用できます。すべてのルーターのドキュメント化をドリフトテストで徹底しています。 |
| 保存済みフィルター | 頻繁に使うリクエストログのクエリ(モデル、ステータス、コスト範囲、タグ)をピン留めして、ワークスペース内で共有できます。 |
| 送信 Webhook | request.created/trace.completed/alert.triggered イベントを購読できます。ペイロードには X-Spanlens-Signature: sha256=… を使って HMAC 署名するため、受信側で送信元を検証できます。 |
| OpenTelemetry/OTLP 取り込み | POST /v1/traces は、gen_ai.* セマンティック規約を使用する OTLP/HTTP JSON エクスポートを受け付けます。Spanlens 固有のコードを書くことなく、任意の OTel SDK をそのまま導入できます。 |
| プロバイダーキーのセキュリティ | 使われていない期間が 90 日以上のプロバイダーキーについて週次ダイジェストメールを送信し、アクティブなキーを対象に GitGuardian による毎日の漏洩スキャンを実行します。キーごとのスキャン履歴も確認できます。 |
| プライバシー管理 | リクエストごとの x-spanlens-log-body: full | meta | none ヘッダーを使って、リクエスト自体は記録したまま、Spanlens に保存するデータ(本文やエンドユーザー ID)を減らせます。 |
| データエクスポート | リクエスト、トレース、異常、フラグ付きセキュリティイベントを CSV または JSON でダウンロードできます(GET /api/v1/exports/{requests,traces,anomalies,security}?format=csv)。10 万行を超える大規模なエクスポートもサーバー側でストリーミングするため、メモリ不足による OOM を防げます。 |
チームとワークスペース
Spanlens は標準でマルチユーザーに対応しています。チームメイトを招待してロールを割り当て、クライアントごとに別のワークスペースを作成できます。
- ロールは
admin(メンバーと請求を管理)、editor(データと設定を管理)、viewer(読み取り専用)です。最後の admin は降格または削除できないよう保護されています。 - シート数はプランに応じて決まり、メンバーと保留中の招待の合計を数えます。ワークスペースが上限に達している場合、新しい招待には
402とアップグレード方法が返されます。誰かが招待を承諾するときにも再度チェックされ、上限を引き下げても既存のメンバーが削除されることはありません。 - メール招待の有効期限は 7 日間で、トークンは sha256 でハッシュ化されます。
RESEND_API_KEYが設定されている場合は Resend 経由で送信され、設定されていない場合はローカル開発用に承認 URL がコンソールに記録されます。 - 保留中の招待バナーには、受信者がメールを開いていない場合でも、未承認の招待がダッシュボードの上部に表示されます。承諾すると参加してアクティブなワークスペースに自動で切り替わり、辞退すると行が削除されます。
- マルチワークスペース機能では、サイドバーからワークスペースを切り替えられます(
sb-wsCookie とハードリロードによって、ミドルウェアがスコープを再解決します)。複数のクライアントを担当するコンサルタントや、1 つのチームが本番環境とステージング環境を別々のワークスペースで運用する場合に便利です。 - 2 段階のオンボーディングでは、新規登録ユーザーは
/onboardingに移動し、ワークスペース名を入力して任意のアンケートに 2 問回答すれば完了です。招待されたユーザー向けには短縮版が用意されており、承諾するとワークスペースを作成せずに参加できます。 - 監査ログ(Settings → Audit log)には、メンバーシップ、ロール、招待に関するすべてのイベントが、実行者とタイムスタンプとともに記録されます。
モノレポの構成
Spanlens/
├── apps/
│ ├── web/ Next.js 16 dashboard (www.spanlens.io)
│ └── server/ Hono LLM proxy + REST API (api.spanlens.io)
├── packages/
│ ├── sdk/ @spanlens/sdk: TypeScript / JavaScript SDK
│ ├── sdk-python/ spanlens (PyPI): Python SDK
│ ├── cli/ @spanlens/cli: npx wizard for 1-command setup
│ └── mcp-server/ @spanlens/mcp-server: MCP server for Cursor / Claude Desktop / Continue
└── supabase/
├── migrations/ Postgres schema (orgs, projects, keys, prompts, requests; RLS-gated)
└── seeds/ model_prices.sql etc.
データの保存場所
すべてのデータは Supabase Postgres に保存されます。組織、プロジェクト、メンバー、API キーとプロバイダーキー、プロンプト、データセット、アラート、請求情報、監査ログは、すべて通常の RLS で保護されたテーブルです。
requests テーブル(LLM 呼び出しごとに 1 行)は created_at を基準に月単位でパーティション分割されています。そのため、古いログを期限切れにするときは、一括 DELETE を実行する代わりにパーティションを削除できます。読み取りは apps/server/src/lib/requests-query.ts 経由で行われ、ここで organization_id フィルターとプランごとの保持期間(free=14d / pro=90d / team=365d)が適用されます。ログの書き込みに失敗した場合、行は JSON として requests_fallback キューに保留され、5 分ごとに cron が再処理します。再処理は冪等(ON CONFLICT (created_at, id) DO NOTHING)なので、リトライによってクォータに対するリクエスト数が二重にカウントされることはありません。
プロジェクト、統合キー、ヘッダー
- 1 つのワークスペースには複数のプロジェクトを保持できます(例:
dev/staging/prod、またはアプリごとに 1 つ)。各プロジェクトには、独自のクォータ枠、プロバイダーキー、プロンプト名前空間が割り当てられます。 - 統合 API キーを使うと、プロジェクトごとにプロバイダーに依存しない
sl_live_*キーを 1 つ使用できます。Spanlens はリクエストパス(/proxy/openai/*、/proxy/anthropic/*、/proxy/gemini/*、/proxy/mistral/*、/proxy/openrouter/*、/proxy/groq/*、/proxy/deepseek/*、/proxy/xai/*、/proxy/cohere/*、/proxy/azure/*)からプロバイダーを推測するため、複数のモデルベンダーを呼び出す場合でも Spanlens キーは 1 つだけで済みます。 X-Spanlens-*ヘッダー(SDK ヘルパーwithUser()、withSession()、withPromptVersion()、withLogBody()が自動設定):リクエストにエンドユーザー ID やセッション ID を付与したり、プロンプトバージョンの実験に関連付けたり、Spanlens が保存する本文の量を制限したりできます。全項目は/docs/proxyをご覧ください。- ストリーミングの安全対策により、290s でプロキシのレスポンスが正常に終了し、ログに
truncated=trueフラグが記録されるため、長時間のストリームが気付かないうちに消えることはありません。
ローカル開発
前提条件:Node 20+、pnpm 10.33.0+、Docker(ローカル Supabase 用)、Vercel CLI(任意)。
# 1. Clone + install
git clone https://github.com/spanlens/Spanlens.git
cd Spanlens
pnpm install
# 2. Start local Supabase (requires Docker)
supabase start
supabase db push # apply Postgres migrations
supabase gen types --lang typescript --local > supabase/types.ts
# 3. Env vars (see apps/server/.env.example)
cp apps/server/.env.example apps/server/.env
# 4. Run everything (web on :3000, server on :3001)
pnpm dev
テストと lint の実行
pnpm typecheck # TS across all packages
pnpm lint # ESLint
pnpm test # Vitest: server + sdk + cli suites
pnpm build # production build smoke test
アーキテクチャのルールと既知の注意点(ストリーミング、RLS、Paddle の請求、Vercel Edge ランタイム、npm publish)については、CLAUDE.md をご覧ください。
セルフホスト
最も簡単なセルフホスト方法は、付属の docker-compose.yml を使用することです。ダッシュボード(Web) と プロキシ/API サーバー の 2 つのコンテナは、どちらも GHCR からビルド済みのイメージを取得します。ほかに必要なのは Supabase プロジェクトだけで、Supabase Cloud でも独自のセルフホスト Supabase でもかまいません。

1. Supabase のスキーマを適用する(初回のみ)
Supabase プロジェクトを開き、SQL Editor → New query に進んで、supabase/init.sql の内容を貼り付け、Run をクリックします。これで完了です。CLI は必要ありません。
別の方法(psql):
psql "postgresql://postgres:<password>@db.<ref>.supabase.co:5432/postgres" \ -f supabase/init.sql
2. .env ファイルを作成する
# Supabase (cloud or self-hosted)
NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_URL=https://xxxx.supabase.co
SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
# Encryption key (generate with: openssl rand -base64 32)
ENCRYPTION_KEY=<32-byte base64>
# Random secret for cron endpoint
CRON_SECRET=<random string>
# Pooled Postgres connection for the `requests` table (required).
# Supabase Dashboard: Connect > Direct > Transaction pooler, with
# "Use IPv4 connection" switched on. Port 6543, not 5432.
# The dedicated pooler shown by default is IPv6-only, so anything without
# outbound IPv6 (Vercel functions included) fails at DNS. Copy the host from
# that dialog rather than assembling it: the shared pooler hostname carries a
# numbered prefix that the region does not tell you.
# This is a full database credential, so keep it out of logs.
SUPABASE_DB_POOLER_URL=postgresql://postgres.<ref>:<password>@<pooler-host>:6543/postgres
# Optional (for invite emails)
# WEB_URL=https://your-domain.com
# RESEND_API_KEY=re_...
# RESEND_FROM=Spanlens <[email protected]>
# Optional (Paddle billing, only if you sell paid plans on your instance)
# PADDLE_API_KEY=...
# PADDLE_NOTIFICATION_SECRET=...
# PADDLE_ENVIRONMENT=sandbox # or production
3. 起動する
docker compose up -d
- ダッシュボード:
http://localhost:3000 - API / プロキシ:
http://localhost:3001 - ヘルスチェック:
GET /health(稼働状態)およびGET /health/deep(データベースプール、フォールバックキューの深さ、cron の鮮度)
古いリリースからアップグレードしますか? リクエストログは現在 Postgres に保存されます。
requestsテーブルが存在するようにsupabase/init.sqlを再適用し、.envにSUPABASE_DB_POOLER_URLを追加してから、ClickHouse コンテナと 4 つのCLICKHOUSE_*変数を削除してください。ClickHouse にすでにある行は移行されないため、削除する前に、引き続き必要なデータをエクスポートしてください。
Web コンテナは NEXT_PUBLIC_* 変数を ビルド引数 として渡します(Next.js はこれらをクライアントバンドルに埋め込みます)。そのため、docker compose build の前に変数を設定しておく必要があります。
サーバーのみ(ダッシュボードなし)
プロキシ/API のみが必要で、ダッシュボードは別途実行する場合:
docker pull ghcr.io/spanlens/spanlens-server:latest
docker run -p 3001:3001 \
-e SUPABASE_URL=... \
-e SUPABASE_ANON_KEY=... \
-e SUPABASE_SERVICE_ROLE_KEY=... \
-e SUPABASE_DB_POOLER_URL=... \
-e ENCRYPTION_KEY=... \
ghcr.io/spanlens/spanlens-server:latest
SDK の接続先をセルフホスト URL に設定する
const openai = createOpenAI({
baseURL: 'https://your-spanlens.example.com/proxy/openai/v1',
})
お使いの Spanlens インスタンスは、お使いの Supabase と通信します。お客様のデータを当社が見ることはありません。
バックグラウンドジョブ(Vercel Cron / 任意のスケジューラー)
ホスト版には、以下の cron タスクが含まれています(apps/server/vercel.json を参照)。セルフホスト環境では、CRON_SECRET の Bearer トークンを使って、任意のスケジューラーから同じパスにアクセスしてください。
| パス | スケジュール | 目的 |
|---|---|---|
/cron/evaluate-alerts | 15 分ごと | しきい値アラートと異常アラートを評価し、通知を送信 |
/cron/snapshot-anomalies | 毎日 01:00 | 日次の異常ベースラインを生成 |
/cron/replay-fallback | 5 分ごと | requests_fallback キューを requests テーブルに再生 |
/cron/stale-key-reminders | 毎週月曜 09:00 | 使用されていないプロバイダーキーの概要をメール送信 |
/cron/leak-detect-keys | 毎日 04:00 | 有効なプロバイダーキーを GitGuardian でスキャン |
/cron/recommend-savings-alerts | 毎日 09:00 | モデル切り替えによるコスト削減の機会をメール送信 |
/cron/check-past-due-downgrades | 毎日 10:00 | 支払い期限超過のサブスクリプションに対する D-3 / D-1 の警告と自動ダウングレード |
/cron/execute-pending-deletions | 6 時間ごと | 30 日間の論理削除猶予期間を過ぎたアカウントを完全削除 |
/cron/run-background-migrations | 5 分ごと | バックグラウンド移行キューを処理(データのバックフィル) |
/cron/detect-missing-model-prices | 1 時間ごと | リクエストログ内にあり、model_prices に行がない新しいモデル ID を検出 |
/cron/self-monitor | 毎時 :31 | Spanlens 自身を利用して、内部ワークスペースにハートビート評価を送信 |
/cron/detect-orphan-spans | 毎時 :17 | 親トレースが到着していないスパンにフラグを設定 |
/cron/prune-judge-cache | 毎日 03:00 | 古くなった (evaluator, response) ジャッジキャッシュのエントリーを TTL に基づいて削除 |
/cron/purge-proxy-cache | 毎日 03:15 | アクセスが途絶えたキーの期限切れ proxy_response_cache 行を回収 |
/cron/weekly-digest | 毎週月曜 09:00 | 各ワークスペースに週次サマリー(リクエスト数、コストの推移、上位モデル、異常)をメール送信 |
/cron/detect-data-silence | 6 時間ごと | 以前はアクティブだったワークスペースから 24 時間データが送信されていない場合、管理者に通知 |
/cron/keep-warm | 5 分ごと | Vercel 関数をウォーム状態に保つ軽量な ping(Fly.io / Railway など常時稼働のプラットフォームではスキップ) |
コントリビューション
PR と Issue を歓迎します。プロジェクトの構成、ローカル開発環境のセットアップ、コーディング規約、PR で確認する内容については、CONTRIBUTING.md をご覧ください。コミットメッセージは Conventional Commits に準拠しており、PR テンプレートには安全性チェックリストが含まれています。
セキュリティに関する問題は、公開 Issue を作成せず、[email protected] までメールでご連絡ください。SECURITY.md をご覧ください。
ライセンス
MIT です。自由に利用、フォーク、セルフホスト、またはその上に構築できます。Spanlens の実行には、spanlens.io のホステッドサービスを推奨しますが、Docker イメージを取得して、ご自身で実行することもできます(docs/self-host をご覧ください)。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。