はじめに
AWS CloudWatch や Prometheus など、既成のメトリクス を Grafana で可視化した経験はあるけれど、テストカバレッジやプルリクエストのレビュー時間など、自前で生成した JSON データ を時系列として眺めたい —— そんなケースは意外と多いものです。
(※以下は前回の参考記事)
本稿では、Grafana と Loki を Docker Compose でローカル環境に立て、REST‑API 経由で JSON データを Loki へ Push し、Grafana でダッシュボードを作るまでの手順を紹介します。
この記事で得られるもの
- Loki の概要と仕組み
- Grafana + Loki + Promtail を 15 分で構築する Docker Compose テンプレート
curl
だけで Loki に時系列データを登録する具体例- Grafana のパネルで登録データを確認できる。
Loki とは?
Loki は Grafana Labs が開発するログ指向の時系列データベースです。内部構造は Prometheus のメトリクス設計を踏襲しており、
- ラベルベースで高速なフィルタリングが可能
- メッセージ全文はオブジェクトストレージに保存し、インデックスはラベルのみに絞ることで低コスト
- Query Language は Prometheus の LogQL —— メトリクスとログを同一 UI で扱える
といった特徴があります。今回は 「ログ = 任意 JSON」 と捉え、独自データを流し込んでみます。
アーキテクチャ概要
┌──────────────┐ push (REST API) ┌──────────────┐
│ JSON Producer │ ─────────────────────────────▶ │ Loki │
└──────────────┘ └────┬─────────┘
│ pull (HTTP API)
▼
┌────────────────┐
│ Grafana │
└────────────────┘
- JSON Producer … テストツールや CI など、カバレッジレポートを生成する側
-
Loki …
/loki/api/v1/push
へログを受信し、時系列として保存 - Grafana … Loki をデータソース登録し、LogQL でクエリを実行
事前準備
- Docker / Docker Compose v2 以上
# 動作確認済みバージョン
$ docker compose version
Docker Compose version v2.29.2
Docker Compose で環境構築
以下を docker-compose.yml
として保存します。
version: "3.8"
services:
grafana:
image: grafana/grafana-enterprise
container_name: grafana
restart: unless-stopped
ports:
- '3011:3000'
volumes:
- grafana-storage:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
depends_on:
- loki
loki:
image: grafana/loki:2.9.0
container_name: loki
restart: unless-stopped
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
volumes:
- ./loki-config.yaml:/etc/loki/local-config.yaml
- loki-data:/tmp/loki
promtail:
image: grafana/promtail:2.9.0
container_name: promtail
restart: unless-stopped
volumes:
- ./promtail-config.yaml:/etc/promtail/config.yml
- /var/log:/var/log:ro
command: -config.file=/etc/promtail/config.yml
depends_on:
- loki
volumes:
grafana-storage:
driver: local
loki-data:
driver: local
ポイント
- Promtail によるファイル監視も設定していますが、本稿の主題は REST Push なので必須ではありません
Loki・Promtail の設定 (最小構成)
docker-compose.yml
と同じディレクトリ配下に設定ファイルを作成します。
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
instance_addr: 127.0.0.1
path_prefix: /tmp/loki
storage:
filesystem:
chunks_directory: /tmp/loki/chunks
rules_directory: /tmp/loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
ruler:
alertmanager_url: http://localhost:9093
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: systemlogs
__path__: /var/log/*.log
起動:
以下の起動コマンドで起動してください。
$ docker compose up -d
JSON データを Loki に Push する
Loki へは Promtail 経由だけでなく、直接 REST API で送ることもできます。エンドポイントは /loki/api/v1/push
、リクエストボディは以下のような JSON です。
{
"streams": [
{
"stream": {
"label": "value"
},
"values": [
[ "<unix epoch in nanoseconds>", "<log line>" ],
[ "<unix epoch in nanoseconds>", "<log line>" ]
]
}
]
}
cURL 例
以下のようなやり方で、REST-API経由でデータを登録してみましょう。
#!/bin/bash
# Lokiエンドポイント
LOKI_URL="http://localhost:3100"
# 基本的なログ送信
curl -X POST "${LOKI_URL}/loki/api/v1/push" \
-H "Content-Type: application/json" \
-d '{
"streams": [
{
"stream": {
"job": "test-app",
"level": "info"
},
"values": [
["'$(date +%s%N)'", "Hello Loki! This is a test log message"]
]
}
]
}'
echo "ログを送信しました"
Grafana に Loki をデータソース登録
-
http://localhost:3011 にアクセス(初期 ID/PW は
admin
/admin
)。 - 左サイドバー Connections → Data sources を開き 「Add data source」 をクリック。
- Loki を選択し、以下を入力して Save & test。
Field | Value |
---|---|
URL |
http://loki:3100 |
Maximum lines |
5000 (適宜) |
認証設定 | なし (auth_enabled: false にしたため) |
✅
Data source is working
と表示されれば OK です。
ダッシュボードを作成して可視化
パネル例 1: 折れ線グラフ
- Create → Dashboard → Add new panel
- Query に以下を入力し、Run query
{job="test-app"}
クエリ結果として、以下のように先ほど登録したデータを確認できればOKです。
これらのデータを使って可視化をこねくり回していく事ができます。
例えば以下のようなデータを登録していれば、
curl -X POST "http://localhost:3100/loki/api/v1/push" \
-H "Content-Type: application/json" \
-d '{
"streams": [
{
"stream": {
"job": "test-results",
"level": "info",
"test_type": "summary",
"environment": "ci"
},
"values": [
["'$(date +%s%N)'", "{\"event_type\":\"test_summary\",\"timestamp\":1754283180542,\"success\":true,\"total_suites\":23,\"passed_suites\":23,\"failed_suites\":0,\"total_tests\":285,\"passed_tests\":283,\"failed_tests\":0,\"pending_tests\":2,\"duration_ms\":38018,\"start_time\":1754283180542,\"end_time\":1754283218560}"]
]
}
]
}'
以下のようなクエリを投げれば、jsonオブジェクト内のduration_msのみを抽出する、といったこともできます。
{job="test-results"} | json | line_format "{{.duration_ms}}"
まとめ
- Grafana + Loki で “ログ以外” の JSON も時系列グラフにできる
- REST API へ REST-API で登録できるため、CI/CD などからも手軽に自動 Push 可能
業務で独自 KPI を作る際に まずはローカルで動かしてみたい —— という時のお役に立てば幸いです。質問やフィードバックはコメントでぜひ!