菜单
文档breadcrumb arrow Grafana Pyroscopebreadcrumb arrow 参考:服务器 HTTP API
开源

服务器 HTTP API

Grafana Pyroscope 暴露了一个 HTTP API,用于查询性能剖析数据以及从其他源摄入性能剖析数据。

认证

Pyroscope 不包含认证层。操作者应使用认证反向代理以确保安全。

在多租户模式下,Pyroscope 要求将 X-Scope-OrgID HTTP 请求头设置为标识租户的字符串。认证反向代理负责处理此任务。有关更多信息,请参阅多租户文档

摄入

有一个主要端点:POST /ingest。它接受请求体中的性能剖析数据以及查询参数中的元数据。

接受以下查询参数

名称描述备注
name应用名称必需
from性能剖析开始时的 UNIX 时间必需
until性能剖析停止时的 UNIX 时间必需
format性能剖析数据的格式可选(默认为 folded
sampleRate使用的采样率(单位:赫兹)可选(默认为 100 赫兹)
spyName使用的 spy 名称可选
units性能剖析数据单位名称可选(默认为 samples
aggregrationType用于合并性能剖析的聚合类型可选(默认为 sum

name 指定应用名称。例如

my.awesome.app.cpu{env=staging,region=us-west-1}

请求体包含性能剖析数据,并可与格式一起使用 Content-Type 请求头来确定数据格式。

某些查询参数取决于性能剖析数据的格式。Pyroscope 当前支持三种主要的摄入格式。

文本格式

这些格式处理简单的性能剖析数据摄入,例如 cpu samples,并且通常不支持格式内的元数据(例如标签)。所有必需的元数据都从查询参数中获取,并且格式由 format 查询参数指定。

支持的格式

  • Folded:也称为 collapsed,这是默认格式。每一行包含一个堆栈追踪,后跟该堆栈追踪的采样计数。例如
foo;bar 100
foo;baz 200
  • Lines:类似于 folded,但它将每个采样表示为单独一行,而不是按堆栈追踪聚合采样。例如
foo;bar
foo;bar
foo;baz
foo;bar

pprof 格式

pprof 格式是一种广泛使用的二进制性能剖析数据格式,在 Go 生态系统中尤为常见。

使用此格式时,某些查询参数具有特定行为

  • format:应设置为 pprof
  • name:此参数包含应用名称的*前缀*。由于单个请求可能包含多个性能剖析类型,完整的应用名称由此前缀与性能剖析类型连接而成。例如,如果您发送 CPU 性能剖析数据并将 name 设置为 my-app{},它在 Pyroscope 中将显示为 my-app.cpu{}
  • unitsaggregationTypesampleRate:这些参数将被忽略。实际值根据数据中存在的性能剖析类型确定(有关更多详细信息,请参阅“采样类型配置”部分)。

采样类型配置

Pyroscope 服务器本身支持标准的 Go 性能剖析类型,例如 cpuinuse_objectsinuse_spacealloc_objectsalloc_space。处理生成 pprof 格式数据的软件时,您可能需要提供自定义采样类型配置,以便 Pyroscope 正确解释数据。

有关摄入带有自定义采样类型配置的 pprof 文件的 Python 示例脚本,请参阅 此 Python 脚本

要摄入带有自定义采样类型配置的 pprof 数据,请按如下方式修改您的请求

  • 将 Content-Type 设置为 multipart/form-data
  • 将性能剖析数据作为名为 profile 的表单文件字段上传。
  • 将采样类型配置包含在名为 sample_type_config 的表单文件字段中。

采样类型配置是格式化如下的 JSON 对象

json
{
  "inuse_space": {
    "units": "bytes",
    "aggregation": "average",
    "display-name": "inuse_space_bytes",
    "sampled": false
  },
  "alloc_objects": {
    "units": "objects",
    "aggregation": "sum",
    "display-name": "alloc_objects_count",
    "sampled": true
  },
  "cpu": {
    "units": "samples",
    "aggregation": "sum",
    "display-name": "cpu_samples",
    "sampled": true
  },
  // pprof supports multiple profiles types in one file,
  //   so there can be multiple of these objects
}

采样类型配置字段说明

  • units
    • 支持的值:samplesobjectsbytes
    • 描述:更改前端显示的单位。samples = CPU 采样,objects = RAM 中的对象,bytes = RAM 中的字节。
  • display-name
    • 支持的值:任意字符串。
    • 描述:这成为应用名称的后缀,例如 my-app.inuse_space_bytes
  • aggregation
    • 支持的值:sumaverage
    • 描述:改变数据在前端的聚合方式。对于随时间累加的数据(例如 CPU 采样、内存分配)使用 sum,对于随时间平均的数据(例如内存占用对象)使用 average
  • sampled
    • 支持的值:truefalse
    • 描述:确定是否考虑采样率(在 pprof 文件中指定)。对于采样事件(例如 CPU 采样)设置为 true,对于内存性能剖析设置为 false

此配置允许在 Pyroscope 中对各种性能剖析类型进行自定义可视化和分析。

JFR 格式

这是 Java Flight Recorder 格式,通常由基于 JVM 的性能剖析工具使用,我们的 Java 集成也支持此格式。

使用此格式时,某些查询参数的行为略有不同

  • format 应设置为 jfr
  • name 包含应用名称的前缀。由于单个请求可能包含多个性能剖析类型,最终的应用名称由此前缀与性能剖析类型连接而成。例如,如果您发送 cpu 性能剖析数据并将 name 设置为 my-app{},它在 pyroscope 中将显示为 my-app.cpu{}
  • units 被忽略,实际单位取决于数据中可用的性能剖析类型。
  • aggregationType 被忽略,实际聚合类型取决于数据中可用的性能剖析类型。

JFR 摄入支持使用性能剖析元数据来确定包含哪些性能剖析类型,这取决于正在进行的性能剖析的种类。目前支持的性能剖析类型包括

  • cpu 采样,仅包含来自可运行线程的性能剖析数据。
  • itimer 采样,类似于 cpu 性能剖析。
  • wall 采样,包含来自任意线程的采样,与其状态无关。
  • alloc_in_new_tlab_objects,表示创建的新 TLAB 对象数量。
  • alloc_in_new_tlab_bytes,表示创建的新 TLAB 对象的字节大小。
  • alloc_outside_tlab_objects,表示在任何 TLAB 之外分配的新对象数量。
  • alloc_outside_tlab_bytes,表示在任何 TLAB 之外分配的新对象的字节大小。

带标签的 JFR

为了摄入带有动态标签的 JFR 数据,您需要对您的请求进行以下更改

  • 使用 HTTP 表单(multipart/form-data)Content-Type。
  • 将 JFR 数据作为名为 jfr 的表单文件字段发送。
  • LabelsSnapshot protobuf 消息作为名为 labels 的表单文件字段发送。
protobuf
message Context {
    // string_id -> string_id
    map<int64, int64> labels = 1;
}
message LabelsSnapshot {
  // context_id -> Context
  map<int64, Context> contexts = 1;
  // string_id -> string
  map<int64, string> strings = 2;
}

其中 context_id 是在 async-profiler 中设置的参数

示例

这是一个向 pyroscope 上传非常简单性能剖析数据的示例代码

curl
printf "foo;bar 100\n foo;baz 200" | curl \
-X POST \
--data-binary @- \
'https://:4040/ingest?name=curl-test-app&from=1615709120&until=1615709130'
python
import requests
import urllib.parse
from datetime import datetime

now = round(datetime.now().timestamp()) / 10 * 10
params = {'from': f'{now - 10}', 'name': 'python.example{foo=bar}'}

url = f'https://:4040/ingest?{urllib.parse.urlencode(params)}'
data = "foo;bar 100\n" \
"foo;baz 200"

requests.post(url, data = data)

这是一个向 pyroscope 上传带标签 JFR 性能剖析数据的示例代码

curl
curl -X POST \
  -F jfr=@profile.jfr \
  -F labels=@labels.pb  \
  "https://:4040/ingest?name=curl-test-app&units=samples&aggregationType=sum&sampleRate=100&from=1655834200&until=1655834210&spyName=javaspy&format=jfr"

查询性能剖析数据

有一个用于查询性能剖析数据的主要端点:GET /pyroscope/render

搜索输入通过查询参数提供。输出通常是一个 JSON 对象,包含一个或多个时间序列和一个火焰图。

查询参数

以下是接受的查询参数概览

名称描述备注
query包含性能剖析类型和标签选择器必需
from搜索窗口开始的 UNIX 时间必需
until搜索窗口结束的 UNIX 时间可选(默认为 now
format性能剖析数据的格式可选(默认为 json
maxNodes结果火焰图将包含的最大节点数可选(默认为 max_flamegraph_nodes_default
groupBy一个或多个标签名称,用于对时间序列进行分组(不适用于火焰图)可选(默认为不分组)

query

query 参数是唯一必需的搜索输入。它携带性能剖析类型以及我们想要用来缩小输出范围的任何标签。此参数的格式类似于 PromQL 查询,可以定义为

<profile_type>{<label_name>="<label_value>", <label_name>="<label_value>", ...}

这是一个具体示例

process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name="my_application_name"}

在 Kubernetes 环境中,查询也可能看起来像

process_cpu:cpu:nanoseconds:cpu:nanoseconds{namespace="dev", container="my_application_name"}

注意

请参阅

性能剖析类型文档以获取更多信息,以及 profile-metrics.json 获取有效性能剖析类型列表。

from 和 until

fromuntil 参数确定查询的时间段的开始和结束。它们可以以绝对形式和相对形式提供。

绝对时间

此表详细说明了传递绝对值的选项。

选项示例备注
日期20231223格式:YYYYMMDD
Unix 时间(秒)1577836800
Unix 时间(毫秒)1577836800000
Unix 时间(微秒)1577836800000000
Unix 时间(纳秒)1577836800000000000

相对时间

相对值始终表示为与 now 的偏移量。

选项示例
3 小时前now-3h
30 分钟前now-30m
2 天前now-2d
1 周前now-7dnow-1w

请注意,必须提供单个偏移量,诸如 now-3h30m 的值将不起作用。

验证

fromuntil 参数受制于与 max_query_lookbackmax_query_length 服务器参数相关的验证规则。您可以在服务器配置文档的limits 部分找到有关这些参数的更多详细信息。

  • 如果配置了 max_query_lookback 并且 fromnow - max_query_lookback 之前,则 from 将被设置为 now - max_query_lookback
  • 如果配置了 max_query_lookback 并且 untilnow - max_query_lookback 之前,则查询将不会执行。
  • 如果配置了 max_query_length 并且查询间隔长于此配置,则查询将不会执行。

format

格式可以是

  • json,在这种情况下响应将包含一个 JSON 对象
  • dot,在这种情况下响应将是包含性能剖析 DOT 表示的文本

有关响应结构的更多信息,请参阅查询输出部分。

maxNodes

maxNodes 参数截断性能剖析响应中的元素数量,以便工具(例如前端)高效地渲染大型性能剖析数据。这通常用于已知具有大型堆栈追踪的性能剖析。

未提供值时,默认值取自 max_flamegraph_nodes_default 配置参数。提供值时,其上限为 max_flamegraph_nodes_max 配置参数。

groupBy

groupBy 参数影响响应的时间序列部分的输出。提供有效标签时,响应将包含与给定标签的标签值数量一样多的序列。

注意

Pyroscope 支持单个标签用于 group by 功能。

查询输出

/pyroscope/render 端点的输出是基于以下 schema 的 JSON 对象

Go
type FlamebearerProfileV1 struct {
	Flamebearer FlamebearerV1                  `json:"flamebearer"`
	Metadata FlamebearerMetadataV1             `json:"metadata"`
	Timeline *FlamebearerTimelineV1            `json:"timeline"`
	Groups   map[string]*FlamebearerTimelineV1 `json:"groups"`
}

flamebearer

flamebearer 字段包含适合渲染火焰图的数据。flamebearer 中的数据组织在单独的数组中,包含性能剖析符号和采样值。

metadata

metadata 字段包含有助于解释 flamebearer 数据的附加信息,例如单位(纳秒、字节)、采样率等。

timeline

timeline 字段表示性能剖析的时间序列。Pyroscope 使用查询间隔(fromuntil)预先计算时间线的步长间隔(分辨率)。最小步长间隔为 10 秒。

原始性能剖析采样数据使用聚合函数下采样到步长间隔(分辨率)。目前仅支持 sum

时间线包含开始时间、采样值列表和步长间隔

json
{
  "timeline": {
    "startTime": 1577836800,
    "samples": [
      100,
      200,
      400
    ],
    "durationDelta": 10
  }
}

groups

groups 字段仅在通过 groupBy 查询参数请求分组时填充。在这种情况下,groups 字段会为查询找到的每个标签值包含一个条目。

此示例按集群分组

json
{
  "groups": {
    "eu-west-2": { "startTime": 1577836800, "samples": [ 200, 300, 500 ] },
    "us-east-1": { "startTime": 1577836800, "samples": [ 100, 200, 400 ] }
  }
}

替代查询输出

format 查询参数为 dot 时,端点响应包含表示所查询性能剖析的 DOT 格式数据。这可用于创建性能剖析的替代可视化。

查询示例

此示例查询本地 Pyroscope 服务器,获取 pyroscope 服务过去一小时的 CPU 性能剖析数据。

curl
curl \
  'https://:4040/pyroscope/render?query=process_cpu%3Acpu%3Ananoseconds%3Acpu%3Ananoseconds%7Bservice_name%3D%22pyroscope%22%7D&from=now-1h'

这是同一查询,使其更具可读性

curl
curl --get \
  --data-urlencode "query=process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name=\"pyroscope\"}" \
  --data-urlencode "from=now-1h" \
  https://:4040/pyroscope/render

这是用 Python 编写的同一示例

python
import requests

application_name = 'my_application_name'
query = f'process_cpu:cpu:nanoseconds:cpu:nanoseconds{{service_name="{application_name}"}}'
query_from = 'now-1h'
url = f'https://:4040/pyroscope/render?query={query}&from={query_from}'

requests.get(url)

有关完整示例,请参阅此 Python 脚本

性能剖析 CLI

profilecli 工具也可用于与 Pyroscope 服务器 API 交互。该工具支持摄入性能剖析、查询现有性能剖析等操作。有关更多信息,请参阅性能剖析 CLI 页面。