メインコンテンツにスキップ

メトリクス

Prisma Clientメトリクスは、Prisma Clientがデータベースとどのように対話しているかについての詳細な洞察を提供します。この洞察を使用して、アプリケーションのパフォーマンスの問題を診断できます。

情報

個々の操作レベルで、Prisma Clientのパフォーマンスに関するさらに詳細な洞察が必要な場合は、トレーシングを参照してください。

メトリクスについて

メトリクスをJSONまたはPrometheus形式でエクスポートし、コンソールログで表示したり、StatsDPrometheusなどの外部メトリクスシステムに統合したりできます。外部メトリクスシステムに統合すると、経時的なメトリクスデータを表示できます。たとえば、メトリクスを使用して、アプリケーションのアイドル状態およびアクティブな接続数の変化を診断するのに役立ちます。

Prisma Clientは、次のメトリクスを提供します

  • カウンター (常に増加)

    • prisma_client_queries_total: 実行されたPrisma Clientクエリの総数。
    • prisma_datasource_queries_total: 実行されたデータソースクエリの総数 (リレーショナルデータベースのSQLクエリ、およびMongoDBのコマンド)。
      • prisma_datasource_queries_totalによって返される値は、一部のPrisma Client操作が複数のクエリを作成するため、prisma_client_queries_totalよりも大きくなる可能性があります。
    • prisma_pool_connections_closed_total: クローズされたプール接続の総数。
    • prisma_pool_connections_opened_total: 現在オープンしているプール接続の数。
  • ゲージ (増加または減少する可能性あり)

    • prisma_client_queries_active: 現在アクティブなPrisma Clientクエリの数。
    • prisma_client_queries_wait: すべての接続が使用中のため、現在接続を待機しているPrisma Clientクエリの数。
    • prisma_pool_connections_busy: 現在ビジー状態のプール接続の数。これらのプール接続は現在、データソースクエリを実行しています。
    • prisma_pool_connections_idle: 現在使用されていないプール接続の数。これらのプール接続は、次に実行するデータソースクエリを待機しています。
    • prisma_pool_connections_open: オープンしているプール接続の数。
  • ヒストグラム (メトリクスデータは値のコレクションに分割されます。コレクション内の各コンテナを「バケット」と呼びます)

    • prisma_client_queries_wait_histogram_ms: すべてのPrisma Clientクエリのプール接続の待機時間 (ミリ秒)。
    • prisma_client_queries_duration_histogram_ms: 実行されたすべてのPrisma Clientクエリの実行時間 (ミリ秒)。これには、すべてのデータベースクエリの実行時間と、データの結合やデータを正しい形式に変換するなど、すべてのデータベースエンジンアクティビティの実行時間が含まれます。
    • prisma_datasource_queries_duration_histogram_ms: 実行されたすべてのデータソースクエリの実行時間 (ミリ秒)。

グローバルラベルをメトリクスデータに追加して、たとえばインフラストラクチャリージョンやサーバーなどでメトリクスをグループ化および分離できます。

前提条件

Prisma Clientメトリクスを使用するには、次の手順を実行する必要があります

  1. 適切な依存関係をインストールする.
  2. Prismaスキーマファイルでmetricsフィーチャーフラグを有効にする.

1. 最新のPrisma ORM依存関係をインストールする

prismaおよび@prisma/client npmパッケージのバージョン3.15.0以降を使用してください。

npm install prisma@latest --save-dev
npm install @prisma/client@latest --save

2. Prismaスキーマファイルでフィーチャーフラグを有効にする

schema.prismaファイルのgeneratorブロックで、metricsフィーチャーフラグを有効にします

generator client {
provider = "prisma-client-js"
previewFeatures = ["metrics"]
}

JSON形式でメトリクスを取得する

JSON形式でメトリクスを取得すると、返された形式で使用したり、StatsDに送信して、時間の経過に伴う変化を視覚化したりできます。

JSON形式でメトリクスを取得するには、アプリケーションコードに次の行を追加します

const metrics = await prisma.$metrics.json()
console.log(metrics)

これにより、メトリクスが次のように返されます

{
"counters": [
{
"key": "prisma_client_queries_total",
"labels": {},
"value": 0,
"description": "Total number of Prisma Client queries executed"
},
{
"key": "prisma_datasource_queries_total",
"labels": {},
"value": 0,
"description": "Total number of Datasource Queries executed"
},
{
"key": "prisma_pool_connections_closed_total",
"labels": {},
"value": 0,
"description": "Total number of Pool Connections closed"
},
{
"key": "prisma_pool_connections_opened_total",
"labels": {},
"value": 1,
"description": "Total number of Pool Connections opened"
}
...
],
"gauges": [
...
],
"histograms": [
...
]
}
展開して完全な出力を表示
{
"counters": [
{
"key": "prisma_client_queries_total",
"labels": {},
"value": 2,
"description": "Total number of Prisma Client queries executed"
},
{
"key": "prisma_datasource_queries_total",
"labels": {},
"value": 5,
"description": "Total number of Datasource Queries executed"
},
{
"key": "prisma_pool_connections_open",
"labels": {},
"value": 1,
"description": "Number of currently open Pool Connections"
}
],
"gauges": [
{
"key": "prisma_client_queries_active",
"labels": {},
"value": 0,
"description": "Number of currently active Prisma Client queries"
},
{
"key": "prisma_client_queries_wait",
"labels": {},
"value": 0,
"description": "Number of Prisma Client queries currently waiting for a connection"
},
{
"key": "prisma_pool_connections_busy",
"labels": {},
"value": 0,
"description": "Number of currently busy Pool Connections (executing a datasource query)"
},
{
"key": "prisma_pool_connections_idle",
"labels": {},
"value": 21,
"description": "Number of currently unused Pool Connections (waiting for the next datasource query to run)"
},
{
"key": "prisma_pool_connections_open",
"labels": {},
"value": 1,
"description": "Number of currently open Pool Connections"
}
],
"histograms": [
{
"key": "prisma_client_queries_duration_histogram_ms",
"labels": {},
"value": {
"buckets": [
[0, 0],
[1, 0],
[5, 0],
[10, 1],
[50, 1],
[100, 0],
[500, 0],
[1000, 0],
[5000, 0],
[50000, 0]
],
"sum": 47.430541000000005,
"count": 2
},
"description": "Histogram of the duration of all executed Prisma Client queries in ms"
},
{
"key": "prisma_client_queries_wait_histogram_ms",
"labels": {},
"value": {
"buckets": [
[0, 0],
[1, 3],
[5, 0],
[10, 0],
[50, 0],
[100, 0],
[500, 0],
[1000, 0],
[5000, 0],
[50000, 0]
],
"sum": 0.0015830000000000002,
"count": 3
},
"description": "Histogram of the wait time of all Prisma Client Queries in ms"
},
{
"key": "prisma_datasource_queries_duration_histogram_ms",
"labels": {},
"value": {
"buckets": [
[0, 0],
[1, 0],
[5, 2],
[10, 2],
[50, 1],
[100, 0],
[500, 0],
[1000, 0],
[5000, 0],
[50000, 0]
],
"sum": 47.134498,
"count": 5
},
"description": "Histogram of the duration of all executed Datasource Queries in ms"
}
]
}

JSONデータのヒストグラム

各ヒストグラム「バケット」には2つの値があります。最初の値はバケットの上限、2番目の値はカウント (そのバケットに該当するデータ値の数) です。次の例では、11〜20の間に2つの値のインスタンスがあり、21〜30の間に5つの値のインスタンスがあります

...
[20, 2],
[30, 5],
...

StatsDでPrisma Clientメトリクスを使用する

JSON形式のメトリクスをStatsDに送信して、時間の経過に伴うメトリクスデータを視覚化できます。

情報

注: カウンターメトリクスは、メトリクスの以前の取得からの増分または減分された一連の値としてStatsDに提供する必要があります。ただし、Prisma Clientのカウンターメトリクスは絶対値を返します。したがって、カウンターメトリクスを増分および減分された一連のゲージデータに変換し、ゲージデータとしてStatsDに送信する必要があります。以下のコード例では、diffHistogramsでカウンターメトリクスを増分および減分されたゲージデータに変換します。

次の例では、10秒ごとにStatsDにメトリクスを送信します。このタイミングは、StatsDのデフォルトの10秒フラッシュレートに合致しています。

import StatsD from 'hot-shots'
let statsd = new StatsD({
port: 8125,
})

const diffMetrics = (metrics: Metric<MetricHistogram>[]) => {
return metrics.map((metric) => {
let prev = 0;

const diffBuckets = metric.value.buckets.map<MetricHistogramBucket>(
(values) => {
const [bucket, value] = values
const diff = value - prev
prev = value
return [bucket, diff]
}
)

metric.value.buckets = diffBuckets
return metric
})
}

let previousHistograms: Metric<MetricHistogram>[] = []


const statsdSender = async () => {
const metrics = await prisma.$metrics.json()

metrics.counters.forEach((counter: any) => {
statsd.gauge('prisma.' + counter.key, counter.value, (...res) => {})
});

metrics.gauges.forEach((counter: any) => {
statsd.gauge('prisma.' + counter.key, counter.value, (...res) => {})
})

if (!previousHistograms.length) {
previousHistograms = diffMetrics(metrics.histograms)

return
}

const diffHistograms = diffMetrics(metrics.histograms);

diffHistograms.forEach((diffHistogram, histogramIndex) => {
diffHistogram.value.buckets.forEach((values, bucketIndex) => {
const [bucket, count] = values
const [_, prev] =
previousHistograms[histogramIndex].value.buckets[bucketIndex]
const change = count - prev

for (let sendTimes = 0; sendTimes < change; sendTimes++) {
statsd.timing('prisma.' + diffHistograms.key, bucket)
}
})
})

previousHistograms = diffHistograms
}

setInterval(async () => await statsdSender(), 10000)

Prometheus形式でメトリクスを取得する

Prometheus形式でPrisma Clientメトリクスを取得すると、返された形式で使用したり、Prometheusメトリクスシステムに送信して、時間の経過に伴う変化を視覚化したりできます。

Prometheus形式でメトリクスを取得するには、アプリケーションコードに次の行を追加します

const metrics = await prisma.$metrics.prometheus()
console.log(metrics)

これにより、メトリクスが次のように返されます

# HELP prisma_client_queries_total Total number of Prisma Client queries executed
# TYPE prisma_client_queries_total counter
prisma_client_queries_total 14

...
# HELP prisma_pool_connections_busy The number of active connections in use.
# TYPE prisma_pool_connections_busy gauge
prisma_pool_connections_busy 0

...
# HELP prisma_client_queries_wait_histogram_ms The wait time for a worker to get a connection.
# TYPE prisma_client_queries_wait_histogram_ms histogram
prisma_client_queries_wait_histogram_ms_bucket{le="0"} 0
prisma_client_queries_wait_histogram_ms_bucket{le="1"} 3
展開して完全な出力を表示
# HELP query_total_operations
# TYPE query_total_operations counter
query_total_operations 2

# HELP prisma_datasource_queries_total
# TYPE prisma_datasource_queries_total counter
prisma_datasource_queries_total 28

# HELP prisma_pool_connections_closed_total Total number of Pool Connections closed
# TYPE prisma_pool_connections_closed_total counter
prisma_pool_connections_closed_total 0

# HELP prisma_pool_connections_opened_total Total number of Pool Connections opened
# TYPE prisma_pool_connections_opened_total counter
prisma_pool_connections_opened_total 0

# HELP prisma_client_queries_active Number of currently active Prisma Client queries
# TYPE prisma_client_queries_active gauge
prisma_client_queries_active 0

# HELP prisma_client_queries_wait Number of queries currently waiting for a connection
# TYPE prisma_client_queries_wait gauge
prisma_client_queries_wait 0

# HELP prisma_pool_connections_busy Number of currently busy Pool Connections (executing a datasource query)
# TYPE prisma_pool_connections_busy gauge
prisma_pool_connections_busy 0

# HELP prisma_pool_connections_idle Number of currently unused Pool Connections (waiting for the next pool query to run)
# TYPE prisma_pool_connections_idle gauge
prisma_pool_connections_idle 21

# HELP prisma_pool_connections_open Number of currently open Pool Connections
# TYPE prisma_pool_connections_open gauge
prisma_pool_connections_open 1

# HELP prisma_pool_connections_open Number of currently open Pool Connections (able to execute a datasource query)
# TYPE prisma_pool_connections_open gauge
prisma_pool_connections_open 0

# HELP prisma_client_queries_wait_histogram_ms The wait time for a worker to get a connection.
# TYPE prisma_client_queries_wait_histogram_ms histogram
prisma_client_queries_wait_histogram_ms_bucket{le="0"} 0
prisma_client_queries_wait_histogram_ms_bucket{le="1"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="5"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="10"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="50"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="100"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="500"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="1000"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="5000"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="50000"} 3
prisma_client_queries_wait_histogram_ms_bucket{le="+Inf"} 3
prisma_client_queries_wait_histogram_ms_sum 0.023208
prisma_client_queries_wait_histogram_ms_count 3

# HELP prisma_client_queries_duration_histogram_ms Histogram of the duration of all executed Prisma Client queries in ms
# TYPE prisma_client_queries_duration_histogram_ms histogram
prisma_client_queries_duration_histogram_ms_bucket{le="0"} 0
prisma_client_queries_duration_histogram_ms_bucket{le="1"} 1
prisma_client_queries_duration_histogram_ms_bucket{le="5"} 2
prisma_client_queries_duration_histogram_ms_bucket{le="10"} 2
prisma_client_queries_duration_histogram_ms_bucket{le="50"} 2
prisma_client_queries_duration_histogram_ms_bucket{le="100"} 2
prisma_client_queries_duration_histogram_ms_bucket{le="500"} 2
prisma_client_queries_duration_histogram_ms_bucket{le="1000"} 2
prisma_client_queries_duration_histogram_ms_bucket{le="5000"} 2
prisma_client_queries_duration_histogram_ms_bucket{le="50000"} 2
prisma_client_queries_duration_histogram_ms_bucket{le="+Inf"} 2
prisma_client_queries_duration_histogram_ms_sum 3.197624
prisma_client_queries_duration_histogram_ms_count 2

# HELP prisma_datasource_queries_duration_histogram_ms Histogram of the duration of all executed Datasource Queries in ms
# TYPE prisma_datasource_queries_duration_histogram_ms histogram
prisma_datasource_queries_duration_histogram_ms_bucket{le="0"} 0
prisma_datasource_queries_duration_histogram_ms_bucket{le="1"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="5"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="10"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="50"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="100"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="500"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="1000"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="5000"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="50000"} 5
prisma_datasource_queries_duration_histogram_ms_bucket{le="+Inf"} 5
prisma_datasource_queries_duration_histogram_ms_sum 1.8407059999999997
prisma_datasource_queries_duration_histogram_ms_count 5

histogram型のメトリクスは、Prometheus形式で3つの異なるクラスの値を公開します

  1. 観測バケットの複数の累積カウンター。これらのカウンターには、_bucket{le="<上限境界 inclusive>"}という接尾辞が付きます。たとえば、prisma_datasource_queries_duration_histogram_msには、prisma_datasource_queries_duration_histogram_ms_bucket{le="1"}として公開されるカウンターがあります

    観測された値がバケットの上限境界 inclusive 以下の場合、Prisma Clientメトリクスはそのバケットを1ずつ増やします。上限境界 inclusive がそれぞれ0、1、5、10、および50のバケットがあるとします。観測された値が5の場合、Prisma Clientメトリクスは3番目のバケット以降を増やします。これは、値が0より大きく、1より大きいが、5、10、および50以下であるためです。

  2. 観測されたすべての値の単一の合計。このカウンターには、_sumという接尾辞が付きます。たとえば、prisma_datasource_queries_duration_histogram_msの合計は、prisma_datasource_queries_duration_histogram_ms_sumとして公開されます。

  3. 観測されたイベントの数のカウント。このカウンターには、_countという接尾辞が付きます。たとえば、prisma_datasource_queries_duration_histogram_msイベントの総数は、prisma_datasource_queries_duration_histogram_ms_countとして公開されます。

詳細については、Prometheusドキュメントのメトリクスタイプをお読みください。

PrometheusメトリクスシステムでPrisma Clientメトリクスを使用する

ほとんどの場合、Prometheusはエンドポイントをスクレイピングしてメトリクスを取得する必要があります。次の例は、Express.jsでデータを送信する方法を示しています

import { PrismaClient } from '@prisma/client'
import express, { Request, Response } from 'express'

const app = express()
const port = 4000
const prisma = new PrismaClient()

app.get('/metrics', async (_req, res: Response) => {
const metrics = await prisma.$metrics.prometheus()
res.end(metrics)
})

app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})

次の例は、Express.jsと組み合わせてREST APIエンドポイントでも提供される他のPrometheusクライアントライブラリとPrisma Clientメトリクスを組み合わせる方法を示しています

import { PrismaClient } from '@prisma/client'
import express, { Request, Response } from 'express'
import prom from 'prom-client'

const app = express()
const port = 4000
const prisma = new PrismaClient()

const register = new prom.Registry()
prom.collectDefaultMetrics({ register })

app.get('/metrics', async (_req, res: Response) => {
const prismaMetrics = await prisma.$metrics.prometheus()
const appMetrics = await register.metrics()
res.end(prismaMetrics + appMetrics)
})

app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})

グローバルラベル

メトリクスにグローバルラベルを追加して、メトリクスをグループ化および分離できます。Prisma Clientの各インスタンスは、生成するメトリクスにこれらのラベルを追加します。たとえば、{ server: us_server1', 'app_version': 'one' }のようなラベルを使用して、インフラストラクチャリージョンまたはサーバーでメトリクスをグループ化できます。

グローバルラベルは、JSONおよびPrometheus形式のメトリクスで機能します。

たとえば、グローバルラベルをJSON形式のメトリクスに追加するには、アプリケーションに次のコードを追加します

const metrics = prisma.$metrics.json({
globalLabels: { server: 'us_server1', app_version: 'one' },
})
console.log(metrics)

これにより、次の形式で情報が返されます

{
"counters": [
{
"key": "query_total_operations",
"labels": { "server": "us_server1", "app_version": "one" },
"value": 0,
"description": "The total number of operations executed"
},
{
"key": "prisma_datasource_queries_total",
"labels": { "server": "us_server1", "app_version": "one" },
"value": 0,
"description": "The total number of queries executed"
},
...
],
"gauges": [
...
],
"histograms": [
...
]
}