菜单
开源 RSS

使用 Grafana Alloy 设置 Java 分析

Grafana Alloy 支持 Java 分析。采集器配置文件由用于收集、转换和发送数据的组件组成。Alloy 配置文件使用 Alloy 配置语法

配置组件

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

alloy
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 参数将进程目标与其他发现(如 discovery.kubernetesdiscovery.dockerdiscovery.dockerswarm)结合起来。您可以使用 discovery.relabel 组件重新标记发现的目标并设置自己的标签。有关更多信息,请参阅组件文档。

forward_to 参数应指向 pyroscope.write 组件,以将收集的分析数据发送到您的 Pyroscope Server 或 Grafana Cloud

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

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

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

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

它支持以下参数

名称类型描述默认值必需
intervalduration从目标收集分析数据的频率。“60s”
cpubool一个标志,用于使用 itimer async-profiler 事件启用 CPU 分析。true
sample_rateintCPU 分析采样率。它从 Hz 转换为 interval,并作为 -i 参数传递给 async-profiler。100
allocstring分配分析采样配置。它作为 --alloc 参数传递给 async-profiler。“512k”
lockstring锁分析采样配置。它作为 --lock 参数传递给 async-profiler。“10ms”

有关 async-profiler 配置的更多信息,请参阅profiler-options

设置采集器权限

您必须以 root 身份并在主机 pid 命名空间内运行采集器(如 Alloy),以便 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

对于 Alloy v1.0 或 v1.1,pyroscope.scrape 需要 stability.level 选项。有关 stability.level 的更多信息,请参阅运行命令文档。

将数据发送到 Grafana Cloud Profiles

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

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

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

示例

有关更详细的示例,请参阅 Pyroscope 仓库中的Grafana Alloy 和 Agent 自动插桩示例。

分析本地进程

alloy
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 容器

有关工作示例,请参阅Docker 中通过自动插桩进行 Java 分析的示例

alloy
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 Pods

有关工作示例,请参阅使用 Kubernetes 通过自动插桩进行 Grafana Alloy Java 分析的示例

alloy
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_pods.output
}

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

参考

更多信息