Fragments of verbose memory

冗長な記憶の断片 - Web技術のメモをほぼ毎日更新

Mar 13, 2025 - 日記

Grafana Loki MCP: CursorでログをAI分析する完全ガイド

local-grafana-loki-mcp-cursor cover image

ソフトウェア開発において、効率的なデバッグとトラブルシューティングは生産性に大きく影響します。特に複雑なアプリケーションを開発する際、ログの管理と分析は重要な要素となります。

この記事では、以下のツールを組み合わせて、ローカル開発環境でのログ管理と問題解決を効率化する方法を紹介します:

over all of grafana loki mcp cursor

  1. local-logs - ローカル環境に簡単にGrafana Lokiスタックを構築するツール
  2. grafana-loki-mcp - CursorのMCP(Model Control Protocol)にGrafana Lokiを統合するプラグイン
  3. Cursor - AIを活用したコーディング支援IDE

これらを組み合わせることで、開発中のアプリケーションのログをリアルタイムで収集・分析し、CursorのAIエージェントがログデータを基に問題解決を支援する環境を構築できます。

構築する環境の全体像

以下のコンポーネントを組み合わせて、AIによるログ分析環境を構築します:

コンポーネント役割URL
Grafana Lokiログ集約・保存http://localhost:9020/loki
Grafana UIログ可視化http://localhost:9020
grafana-loki-mcpCursor⇔Loki連携MCP Protocol
Cursor IDEAI支援開発環境-

local-logsでGrafana Lokiスタックをローカルに構築する

Grafana Lokiとは

Grafana Loki は、Grafanaが開発したログ集約システムです。Prometheusのラベルベースのアプローチを採用しており、ログデータの効率的な保存と検索を可能にします。

local-logsの導入

local-logs は、Docker Composeを使用してGrafana Lokiスタックをローカル環境に簡単にデプロイするためのツールです。以下の手順で導入できます:

# リポジトリのクローン
git clone https://github.com/tumf/local-logs.git
cd local-logs

# Docker Composeでサービスを起動
docker-compose up -d

これにより、以下のコンポーネントがローカル環境で起動します:

  • Grafana: http://localhost:9020 (デフォルトユーザー名/パスワード: admin/admin)
  • Loki: http://localhost:9020/loki

設定の確認

Grafanaにログインすると、Lokiデータソースが既に設定されており、ログの閲覧が可能な状態になっています。

開発中のアプリケーションからログをLokiに送信する

アプリケーションからLokiにログを送信する方法はいくつかありますが、ここでは一般的な方法を紹介します。

Node.jsアプリケーションの場合

Node.jsアプリケーションでは、winston-loki などのライブラリを使用できます:

const winston = require('winston');
const LokiTransport = require('winston-loki');

const logger = winston.createLogger({
    transports: [
        new LokiTransport({
            host: "http://localhost:9020/loki",
            labels: {
                app: "my-app"
            },
            json: true,
            batching: true,
            interval: 5
        })
    ]
});

// ログの出力
logger.info('Hello, Loki!');

Pythonアプリケーションの場合

Pythonでは、python-logging-loki を使用できます:

import logging
import logging_loki

handler = logging_loki.LokiHandler(
    url="http://localhost:9020/loki/loki/api/v1/push",
    tags={"application": "my-python-app"},
    version="1",
)

logger = logging.getLogger("my-python-app")
logger.addHandler(handler)
logger.setLevel(logging.INFO)

# ログの出力
logger.info("Hello, Loki!")

ブラウザから (next.js)の場合

WebSocketを使って接続すると、DeveloperConsoleに接続ログが残らないのでおすすめです。

// Lokiサーバーの設定
const LOKI_URL = process.env.NEXT_PUBLIC_LOKI_URL || '';
const isWebSocket = LOKI_URL && (LOKI_URL.startsWith('ws://') || LOKI_URL.startsWith('wss://'));
const isHttpApi = LOKI_URL && (LOKI_URL.startsWith('http://') || LOKI_URL.startsWith('https://'));
const isLoggingEnabled = !!LOKI_URL && (isWebSocket || isHttpApi);

// Lokiのペイロード型定義
interface LokiPayload {
  streams: Array<{
    stream: Record<string, string>;
    values: Array<[string, string]>;
  }>;
}

// ログをLokiサーバーに送信する関数
const sendLogToLoki = async (
  level: string,
  message: string,
  meta: Record<string, unknown> = {}
) => {
  if (!isLoggingEnabled) return;
  
  try {
    // Lokiに送信するためのペイロードを作成
    const timestamp = Date.now() * 1000000; // ナノ秒単位のタイムスタンプ
    const payload: LokiPayload = {
      streams: [
        {
          stream: {
            environment: process.env.NODE_ENV || 'development',
            application: process.env.NEXT_PUBLIC_LOKI_APPLICATION || 'unknown',
            level,
            source: 'browser',
            category: (meta.category as string) || 'client',
          },
          values: [
            [
              `${timestamp}`,
              JSON.stringify({
                message,
                ...meta,
                client: true,
                userAgent: navigator.userAgent,
                url: window.location.href,
                timestamp: new Date().toISOString(),
              }),
            ],
          ],
        },
      ],
    };

    // WebSocketが有効な場合はWebSocketで送信
    if (isWebSocket) {
      sendLogViaWebSocket(payload);
      return;
    }

    // HTTP APIが有効な場合はHTTP APIで送信
    if (isHttpApi) {
      fetch(LOKI_URL, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
        keepalive: true,
      }).catch(() => {
        // サーバーへのログ送信に失敗した場合は無視
      });
    }
  } catch {
    // エラーが発生した場合は無視
  }
};

Dockerコンテナのログ

Dockerコンテナのログを直接Lokiに送信するには、Docker Composeファイルに以下の設定を追加します:

services:
  my-app:
    image: my-app-image
    logging:
      driver: loki
      options:
        loki-url: "http://localhost:9020/loki/loki/api/v1/push"
        loki-batch-size: "400"
        loki-retries: "5"
        loki-timeout: "1s"
        labels: "job=my-app"

grafana-loki-mcpでCursorとLokiを連携させる

Model Control Protocol (MCP)とは

CursorのMCP(Model Control Protocol)は、AIモデルに外部データソースへのアクセスを提供するためのプロトコルです。これにより、AIエージェントは開発環境の様々なコンテキスト情報を活用できるようになります。

CursorでのMCP設定

grafana-loki-mcp は、CursorのMCPにGrafana Lokiを統合するプラグインです。以下の手順で設定します:

Cursorより Cursor Settings > MCP より

Cursor MCP setting

  • Name: Grafana
  • Type: Command
  • Command: には以下の文字列を入力してください
uvx grafana-loki-mcp -u http://localhost:9020 -k {Grafana API Key}

http://localhost:9020 は GrafanaのURLです。

Grafana APIキーは、Grafana UIの「Configuration > API Keys」から生成できます。

Cursorを起動し、設定画面からMCPの設定を行います:

  1. 設定(Settings)を開く
  2. 「Model Control Protocol」セクションを探す
  3. 「Enable MCP」をオンにする
  4. 「MCP URL」に http://localhost:3200 を入力
  5. 保存して再起動

開発プロセスの改善

これらのツールを組み合わせることで、以下のような開発プロセスの改善が期待できます:

AIによる問題解決支援

CursorのAIエージェントは、grafana-loki-mcpを通じてログデータにアクセスできるようになります。これにより:

  1. エラーの原因特定が迅速になる
  2. 類似の問題に対する解決策を提案してくれる
  3. ログパターンから潜在的な問題を予測できる

実際の使用例

例えば、アプリケーションで例外が発生した場合:

  1. 例外のスタックトレースがLokiに記録される
  2. Cursorでコードを編集中に、AIエージェントに問題について質問する
  3. AIエージェントはMCPを通じてLokiからログを取得し、問題の文脈を理解する
  4. 具体的な解決策を提案してくれる

Agent sample

ユーザー: このAPIエンドポイントが500エラーを返す原因は何ですか?

AI: Lokiのログを確認したところ、データベース接続のタイムアウトが発生しているようです。
以下のログエントリが見つかりました:

[ERROR] Connection to database timed out after 30000ms

接続プールの設定を見直すか、クエリの最適化が必要かもしれません。

よくある質問

Grafana Loki MCPとは?

Grafana Loki MCPは、CursorのModel Control Protocol(MCP)を使ってAIエージェントがGrafana Lokiのログデータにアクセスできるようにするプラグインです。これにより、AIがログを読み取って問題解決を支援します。

local-logsは本番環境でも使える?

local-logsは開発・テスト環境専用です。本番環境では、適切なセキュリティ設定とスケーラビリティを持つ構成が必要です。

Cursor以外のIDEでも使える?

grafana-loki-mcpは、MCP(Model Control Protocol)をサポートする任意のツールで使用可能です。ただし、現時点ではCursorが主な対象です。

ログデータはどこに保存される?

local-logsを使用する場合、ログデータはDockerボリュームとしてローカルマシンに保存されます。デフォルトでは永続化されますが、docker-compose down -vで削除されます。

MCP設定でGrafana APIキーが必要な理由は?

APIキーは、grafana-loki-mcpがGrafana APIを通じてLokiのログデータにアクセスするために必要です。適切な権限(Viewer以上)を持つキーを生成してください。

セキュリティに関する注意事項

APIキーの管理

Grafana APIキーは機密情報です。以下の点に注意してください:

  • Gitリポジトリにコミットしない
  • 環境変数または安全な設定ファイルで管理
  • 定期的にローテーション

ローカル環境のみでの使用

この構成はローカル開発環境専用です。本番環境では以下が必要です:

  • HTTPS通信の有効化
  • 認証・認可の強化
  • ログデータの暗号化
  • アクセス制御の実装

トラブルシューティング

Cursorでログが表示されない

  1. MCP接続の確認: Cursor Settings > MCP で接続状態を確認
  2. Grafana APIキーの確認: キーが有効で、適切な権限があるか確認
  3. Lokiの起動確認: docker psでloki_lokiコンテナが起動しているか確認

ログがLokiに送信されない

  1. アプリケーションの設定確認: Loki URLが正しいか確認(http://localhost:9020/loki
  2. ネットワーク接続: Dockerネットワークで適切に接続されているか確認
  3. Grafanaでクエリ実行: 直接Grafana UIでログが見えるか確認

まとめ

Grafana Loki MCP、local-logs、Cursorを組み合わせることで、ローカル開発環境でのログ管理と問題解決プロセスを大幅に改善できます。

主なメリット:

  1. 可視性の向上: アプリケーションの動作をリアルタイムで把握
  2. コンテキスト理解の深化: AIエージェントがログデータを基に問題の文脈を理解
  3. 効率的なデバッグ: 問題の特定と解決が迅速に
  4. 開発速度の向上: ログ分析の自動化により開発に集中できる

特にマイクロサービスアーキテクチャや複雑な分散システムの開発において、その恩恵は大きいでしょう。

参考リンク