菜单
开源 RSS

使用 Grafana Alloy 或 Agent 对 Java 进行性能分析

Grafana Alloy 和 Grafana Agent 在 流模式 下支持 Java 性能分析。

收集器配置文件由用于收集、转换和发送数据的组件组成。Alloy 配置文件使用 Alloy 配置语法。Agent Flow 文件使用 River 语言。

注意

Grafana Alloy 是我们 OTel 收集器发行版的最新名称。Grafana Agent 已被弃用,并将在 2025 年 10 月 31 日之前提供长期支持 (LTS)。Grafana Agent 将于 2025 年 11 月 1 日达到生命周期结束 (EOL)。详细了解我们为何建议迁移到 Grafana Alloy

配置组件

pyroscope.java 组件用于使用 async-profiler 持续分析在本地 Linux OS 上运行的 Java 进程。

river
pyroscope.java "java" {
  profiling_config {
    interval = "15s"
    alloc = "512k"
    cpu = true
    lock = "10ms"
    sample_rate = 100
  }
  forward_to = [pyroscope.write.endpoint.receiver]
  targets = discovery.relabel.java.output
}

使用 targets 参数,您可以指定要分析机器上的哪些进程和容器。targets 可以来自 discovery.process 组件。您可以使用 discovery.process join 参数将进程目标与其他发现(例如 dicovery.kubernetesdiscovery.dockerdiscovery.dockerswarm)连接起来。您可以使用 discovery.relabel 组件重新标记发现的目标并设置您自己的标签。有关更多信息,请参阅 组件

forward_to 参数应指向 pyroscope.write 组件,以将收集的配置文件发送到您的 Pyroscope 服务器或 Grafana Cloud

名称类型描述默认值必需
targetslist(map(string))要分析的 Java 进程目标列表。
forward_tolist(ProfilesReceiver)要将收集的配置文件发送到的接收器列表。
tmp_dirstring用于存储 async-profiler 的临时目录。/tmp

特殊标签 __process_pid__ 必须始终 存在于 targets 的每个目标中,并且对应于要分析的进程的 PID

特殊标签 service_name 是必需的,并且必须始终存在。如果没有指定 service_namepyroscope.java 会尝试从发现元标签中推断出来。如果没有指定 service_name,并且无法推断,则将其设置为 unspecified

profiling_config 块描述了如何调用 async-profiler。

它支持以下参数

名称类型描述默认值必需
间隔持续时间从目标收集配置文件的频率。“60s”
cpubool一个启用 CPU 分析的标志,使用 itimer 异步分析器事件。true
采样率intCPU 分析采样率。它从 Hz 转换为间隔,并作为 -i 参数传递给异步分析器。100
allocstring分配分析采样配置。它作为 --alloc 参数传递给异步分析器。“512k”
lockstring锁分析采样配置。它作为 --lock 参数传递给异步分析器。“10ms”

有关异步分析器配置的更多信息,请参阅 profiler-options

为收集器设置权限

您必须以 root 用户身份运行收集器(推荐使用 Grafana Alloy 或使用传统的 Agent),并在主机 pid 命名空间内运行,才能使 pyroscope.javadiscover.process 组件正常工作。

启动收集器

要启动 Grafana Alloy v1.2:将 configuration.alloy 替换为您配置的文件名

bash
alloy run configuration.alloy

要启动 Grafana Alloy v1.0/1.1:将 configuration.alloy 替换为您配置的文件名

bash
alloy run --stability.level=public-preview configuration.alloy

stability.level 选项对于使用 Alloy v1.0 或 v1.1 的 pyroscope.scrape 是必需的。有关 stability.level 的更多信息,请参阅 The run command 文档。

要启动 Grafana Agent,请将 configuration.river 替换为您配置的文件名:grafana-agent-flow run configuration.river

将数据发送到 Grafana Cloud Profiles

当发送到 Grafana Cloud Profiles 时,您可以使用以下 pyroscope.write 组件配置,该配置使用环境变量。

确保您已正确配置 GC_URLGC_USERGC_PASSWORD 环境变量。

river
pyroscope.write "endpoint" {
    endpoint {
        basic_auth {
            password = env("GC_PASSWORD")
            username = env("GC_USER")
        }
        url = env("GC_URL")
    }
}

示例

分析本地进程

river
discovery.process "all" {
}

discovery.relabel "java" {
    targets = discovery.process.all.targets
    // Filter only java processes
    rule {
        source_labels = ["__meta_process_exe"]
        action = "keep"
        regex = ".*/java$"
    }
    // Filter processes. For example: only processes with command line containing "FastSlow"
    rule {
        source_labels = ["__meta_process_commandline"]
        regex = "java FastSlow"
        action = "keep"
    }
    // Provide a service name for the process, otherwise it will be unspecified.
    rule {
        action = "replace"
        target_label = "service_name"
        replacement = "java-fast-slow"
    }
}

pyroscope.java "java" {
  forward_to = [pyroscope.write.example.receiver]
  targets = discovery.relabel.java.output
}

pyroscope.write "example" {
  endpoint {
    url = "http://pyroscope:4040"
  }
}

分析 Docker 容器

river
discovery.docker "local_containers" {
  host = "unix:///var/run/docker.sock"
}

discovery.process "all" {
  join = discovery.docker.local_containers.targets
}

discovery.relabel "java" {
    targets = discovery.process.all.targets
    // Filter only java processes
    rule {
        source_labels = ["__meta_process_exe"]
        action = "keep"
        regex = ".*/java$"
    }
    // Filter only needed containers
    rule {
        source_labels = ["__meta_docker_container_name"]
        regex = ".*suspicious_pascal"
        action = "keep"
    }
    // Provide a service name for the process, otherwise it will default to the value of __meta_docker_container_name label.
    rule {
        action = "replace"
        target_label = "service_name"
        replacement = "java-fast-slow"
    }
}

pyroscope.java "java" {
  forward_to = [pyroscope.write.example.receiver]
  targets = discovery.relabel.java.output
}

pyroscope.write "example" {
  endpoint {
    url = "http://pyroscope:4040"
  }
}

分析 Kubernetes Pod

river

discovery.kubernetes "local_pods" {
  selectors {
    field = "spec.nodeName=" + env("HOSTNAME")
    role = "pod"
  }
  role = "pod"
}

discovery.process "all" {
  join = discovery.kubernetes.local_pods.targets
}

discovery.relabel "java_pods" {
  targets = discovery.process.all.targets
  // Filter only java processes
  rule {
    source_labels = ["__meta_process_exe"]
    action = "keep"
    regex = ".*/java$"
  }
  rule {
    action = "drop"
    regex = "Succeeded|Failed|Completed"
    source_labels = ["__meta_kubernetes_pod_phase"]
  }
  rule {
    action = "replace"
    source_labels = ["__meta_kubernetes_namespace"]
    target_label = "namespace"
  }
  rule {
    action = "replace"
    source_labels = ["__meta_kubernetes_pod_name"]
    target_label = "pod"
  }
  rule {
    action = "replace"
    source_labels = ["__meta_kubernetes_pod_node_name"]
    target_label = "node"
  }
  rule {
    action = "replace"
    source_labels = ["__meta_kubernetes_pod_container_name"]
    target_label = "container"
  }
  // Provide arbitrary service_name label, otherwise it will be inferred from discovery labels automatically
  rule {
    action = "replace"
    regex = "(.*)@(.*)"
    replacement = "java/${1}/${2}"
    separator = "@"
    source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
    target_label = "service_name"
  }
  // Filter only needed services
  rule {
    action = "keep"
    regex = "(java/ns1/.*)|(java/ns2/container-.*0)"
    source_labels = ["service_name"]
  }
}

pyroscope.java "java" {
  forward_to = [pyroscope.write.example.receiver]
  targets = discovery.relabel.java.output
}

pyroscope.write "example" {
  endpoint {
    url = "http://pyroscope:4040"
  }
}

参考

有关更多信息

Grafana Alloy

Grafana Agent