Skip to content

Commit a26979d

Browse files
committed
OpenTelemetry による計測の追加
1 parent 80ed440 commit a26979d

5 files changed

Lines changed: 148 additions & 5 deletions

File tree

agents/agent-langchain-nextjs/README.md

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
# LangChain.js Agent with Next.js
22

3-
LangChain.js、LangGraph.js、Next.jsを使用したAIエージェントアプリケーションです
3+
LangChain.js、LangGraph.js、Next.js、Vercel AI SDK を使用したAIエージェントアプリケーションです
44

55
## 技術スタック
66

77
- **Next.js 16** - Reactフレームワーク
8-
- **LangChain.js** - LLMアプリケーションフレームワーク
9-
- **LangGraph.js** - エージェントの状態管理
10-
- **AWS Bedrock** - LLMプロバイダー
8+
- **React 19.2.3** - UIライブラリ
9+
- **Vercel AI SDK 6.0.62** - AIアプリケーションフレームワーク
10+
- **LangChain.js 1.2.15** - LLMアプリケーションフレームワーク
11+
- **LangGraph.js 1.1.2** - エージェントの状態管理
12+
- **AWS Bedrock** - LLMプロバイダー(Amazon Novaシリーズ)
1113
- **OpenInference** - OpenTelemetryトレーシング
1214
- **Radix UI** - UIコンポーネント
13-
- **Tailwind CSS** - スタイリング
15+
- **Tailwind CSS 4** - スタイリング
16+
- **TypeScript 5.9.3** - 型定義
1417

1518
## セットアップ
1619

@@ -20,6 +23,14 @@ LangChain.js、LangGraph.js、Next.jsを使用したAIエージェントアプ
2023
pnpm install
2124
```
2225

26+
## 環境変数
27+
28+
AWS 認証情報が必要です。以下のいずれかの方法で設定してください:
29+
30+
1. AWS 認証情報を環境変数として設定
31+
2. AWS 認証情報を `~/.aws/credentials` に配置
32+
3. IAM ロールを使用
33+
2334
## 開発サーバーの起動
2435

2536
```bash
@@ -45,3 +56,40 @@ pnpm start
4556
```bash
4657
pnpm lint
4758
```
59+
60+
## テスト
61+
62+
```bash
63+
pnpm vitest
64+
```
65+
66+
## タイプチェック
67+
68+
```bash
69+
pnpm tsc --noEmit
70+
```
71+
72+
## プロジェクト構造
73+
74+
```
75+
.
76+
├── app/ # Next.js App Router
77+
│ ├── api/chat/ # チャットAPIエンドポイント
78+
│ │ ├── route.ts # メインのAPIルート
79+
│ │ └── instrumentation.ts # OpenTelemetryインストゥルメンテーション
80+
│ ├── layout.tsx # ルートレイアウト
81+
│ └── page.tsx # メインページ
82+
├── components/ # UIコンポーネント
83+
│ └── ai-elements/ # AI SDK用カスタムコンポーネント
84+
├── lib/ # ユーティリティ関数
85+
└── public/ # 静的ファイル
86+
```
87+
88+
## 機能
89+
90+
- Amazon Nova シリーズ(Micro / Lite)に対応したAIエージェント
91+
- ストリーミングレスポンス
92+
- ファイル添付サポート
93+
- ソースURL表示
94+
- 推論プロセスの表示
95+
- OpenTelemetryによるトレーシング
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
const initialize = async () => {
2+
if (process.env.ENABLED_OPENINFERENCE_TELEMETRY === 'true') {
3+
const { registerInstrumentations } = await import('@opentelemetry/instrumentation');
4+
const {
5+
NodeTracerProvider,
6+
SimpleSpanProcessor,
7+
} = await import('@opentelemetry/sdk-trace-node');
8+
const { OTLPTraceExporter } = await import('@opentelemetry/exporter-trace-otlp-proto');
9+
const { ATTR_SERVICE_NAME } = await import('@opentelemetry/semantic-conventions');
10+
const { diag, DiagConsoleLogger, DiagLogLevel } = await import('@opentelemetry/api');
11+
const { LangChainInstrumentation } = await import('@arizeai/openinference-instrumentation-langchain');
12+
const lcCallbackManager = await import('@langchain/core/callbacks/manager');
13+
const { resourceFromAttributes } = await import('@opentelemetry/resources');
14+
const { LoggerProvider, SimpleLogRecordProcessor } = await import('@opentelemetry/sdk-logs');
15+
const { OTLPLogExporter } = await import('@opentelemetry/exporter-logs-otlp-proto');
16+
const api = await import("@opentelemetry/api-logs");
17+
const { MeterProvider, PeriodicExportingMetricReader } = await import('@opentelemetry/sdk-metrics');
18+
const { OTLPMetricExporter } = await import('@opentelemetry/exporter-metrics-otlp-proto');
19+
20+
// For troubleshooting, set the log level to DiagLogLevel.DEBUG
21+
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);
22+
23+
const otlpApiKey = process.env.OTEL_EXPORTER_OTLP_API_KEY;
24+
const headers = otlpApiKey ? {
25+
'x-api-key': otlpApiKey,
26+
'Langsmith-Project': 'default',
27+
} : undefined;
28+
29+
const otlpTracesEndpoint = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? 'http://localhost:6006/v1/traces';
30+
const provider = new NodeTracerProvider({
31+
spanProcessors: [new SimpleSpanProcessor(
32+
new OTLPTraceExporter({
33+
url: otlpTracesEndpoint,
34+
headers,
35+
}),
36+
),
37+
],
38+
resource: resourceFromAttributes({
39+
[ATTR_SERVICE_NAME]: 'chat-service',
40+
}),
41+
});
42+
43+
registerInstrumentations({
44+
instrumentations: [],
45+
});
46+
47+
const otlpLogsEndpoint = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? 'http://localhost:6006/v1/logs';
48+
const logExporter = new OTLPLogExporter({
49+
url: otlpLogsEndpoint, // url is optional and can be omitted - default is http://localhost:4318/v1/logs
50+
headers, //an optional object containing custom headers to be sent with each request will only work with http
51+
});
52+
const loggerProvider = new LoggerProvider({
53+
resource: resourceFromAttributes({ 'service.name': 'testApp' }),
54+
processors: [new SimpleLogRecordProcessor(logExporter)]
55+
});
56+
api.logs.setGlobalLoggerProvider(loggerProvider);
57+
58+
const otlpMetricsEndpoint = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? 'http://localhost:6006/v1/metrics';
59+
const collectorOptions = {
60+
url: otlpMetricsEndpoint, // url is optional and can be omitted - default is http://localhost:4318/v1/metrics
61+
headers,
62+
};
63+
const metricExporter = new OTLPMetricExporter(collectorOptions);
64+
const meterProvider = new MeterProvider({
65+
readers: [
66+
new PeriodicExportingMetricReader({
67+
exporter: metricExporter,
68+
exportIntervalMillis: 1000,
69+
}),
70+
],
71+
});
72+
73+
74+
// LangChain must be manually instrumented as it doesn't have a traditional module structure
75+
const lcInstrumentation = new LangChainInstrumentation();
76+
lcInstrumentation.manuallyInstrument(lcCallbackManager);
77+
78+
provider.register();
79+
80+
console.log('👀 OpenInference initialized');
81+
};
82+
}
83+
84+
export { initialize };

agents/agent-langchain-nextjs/app/api/chat/route.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { initialize } from './instrumentation';
12
import { toBaseMessages, toUIMessageStream } from '@ai-sdk/langchain';
23
import { createAgent } from 'langchain';
34
import { createUIMessageStreamResponse, UIMessage } from 'ai';
@@ -14,6 +15,8 @@ export async function POST(req: Request) {
1415
model: string;
1516
} = await req.json();
1617

18+
await initialize();
19+
1720
const model = new ChatBedrockConverse({ model: modelId === 'nova-lite' ? 'us.amazon.nova-lite-v1:0' : 'us.amazon.nova-micro-v1:0' });
1821
const agent = createAgent({
1922
model,

agents/agent-langchain-nextjs/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
"@langchain/langgraph": "^1.1.2",
2222
"@langchain/mcp-adapters": "^1.1.2",
2323
"@opentelemetry/api": "^1.9.0",
24+
"@opentelemetry/api-logs": "^0.211.0",
2425
"@opentelemetry/exporter-logs-otlp-proto": "^0.211.0",
2526
"@opentelemetry/exporter-metrics-otlp-proto": "^0.211.0",
2627
"@opentelemetry/exporter-trace-otlp-http": "^0.211.0",
2728
"@opentelemetry/exporter-trace-otlp-proto": "^0.211.0",
2829
"@opentelemetry/instrumentation": "^0.211.0",
2930
"@opentelemetry/resources": "^2.5.0",
31+
"@opentelemetry/sdk-logs": "^0.211.0",
3032
"@opentelemetry/sdk-metrics": "^2.5.0",
3133
"@opentelemetry/sdk-node": "^0.211.0",
3234
"@opentelemetry/sdk-trace-base": "^2.5.0",

pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)