跳至主要内容

指标

Prisma Client 指标提供有关 Prisma Client 如何与数据库交互的详细见解。你可以使用此见解来帮助诊断应用程序的性能问题。

info

如果你想要更深入地了解 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_queries_total,因为某些 Prisma Client 操作会创建多个查询。
    • 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 数据中的直方图

每个直方图“桶”有两个值。第一个是桶的上限,第二个是计数(落在该桶中的数据值数量)。在以下示例中,有两个值介于 11 和 20 之间,五个值介于 21 和 30 之间

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

将 Prisma Client 指标与 StatsD 一起使用

你可以将 JSON 格式的指标发送到 StatsD 以可视化指标数据如何随时间变化。

info

注意:你必须将计数器指标作为一系列从先前检索的指标递增或递减的值提供给 StatsD。但是,Prisma Client 的计数器指标返回绝对值。因此,你必须将计数器指标转换为一系列递增和递减的值,并将它们作为仪表盘数据发送到 StatsD。在下面的代码示例中,我们在 diffHistograms 中将计数器指标转换为递增和递减的仪表盘数据。

在以下示例中,我们将指标每 10 秒发送到 StatsD。此计时与 StatsD 的默认 10 秒刷新率一致。

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

let diffMetrics = (metrics: any) => {
return metrics.map((metric: any) => {
let prev = 0
let diffBuckets = metric.value.buckets.map((values: any) => {
let [bucket, value] = values
let diff = value - prev
prev = value
return [bucket, diff]
})
metric.value.buckets = diffBuckets
return metric
})
}

let previousHistograms: any = null
let statsdSender = async () => {
let 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 === null) {
previousHistograms = diffMetrics(metrics.histograms)
return
}

let diffHistograms = diffMetrics(metrics.histograms)

diffHistograms.forEach((diffHistograms: any, histogramIndex: any) => {
diffHistograms.value.buckets.forEach((values: any, bucketIndex: any) => {
let [bucket, count] = values
let [_, prev] =
previousHistograms[histogramIndex].value.buckets[bucketIndex]
let 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 格式中公开了三种不同的值类别

  1. 用于观察桶的多个累积计数器。这些计数器以 _bucket{le="<上界(包含)>"} 为后缀。例如,prisma_datasource_queries_duration_histogram_ms 具有一个作为 prisma_datasource_queries_duration_histogram_ms_bucket{le="1"} 公开的计数器

    当观察到的值小于或等于桶的上界(包含)时,Prisma Client 指标会将该桶递增 1。假设你具有上界(包含)分别为 0、1、5、10 和 50 的桶。如果观察到的值为 5,则 Prisma Client 指标会将第三个桶及其后的桶递增 1,因为该值大于 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 文档。

将 Prisma Client 指标与 Prometheus 指标系统一起使用

在大多数情况下,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}`)
})

以下示例显示如何将 Prisma Client 指标与其他 Prometheus 客户端库结合使用,这些库也与 Express.js 结合使用 REST API 端点提供服务

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": [
...
]
}