github.com/grafana/pyroscope@v1.18.0/docs/sources/configure-client/grafana-alloy/java/_index.md (about) 1 --- 2 title: "Set up Java profiling using Grafana Alloy" 3 menuTitle: "Set up Java profiling" 4 description: "Learn about using Grafana Alloy for continuous Java profiling processes for performance optimization." 5 weight: 20 6 --- 7 8 # Set up Java profiling using Grafana Alloy 9 10 Grafana Alloy supports Java profiling. 11 The collector configuration file is composed of components that are used to collect, 12 transform, and send data. 13 The Alloy configuration files use the Alloy [configuration syntax](https://grafana.com/docs/alloy/<ALLOY_VERSION>/concepts/configuration-syntax/). 14 15 ## Configure the components 16 17 The [`pyroscope.java` component](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/pyroscope/pyroscope.java/) is used to continuously profile Java processes running on the local Linux OS 18 using [async-profiler](https://github.com/async-profiler/async-profiler). 19 20 ```alloy 21 pyroscope.java "java" { 22 profiling_config { 23 interval = "15s" 24 alloc = "512k" 25 cpu = true 26 lock = "10ms" 27 sample_rate = 100 28 } 29 forward_to = [pyroscope.write.endpoint.receiver] 30 targets = discovery.relabel.java.output 31 } 32 ``` 33 34 Using the `targets` argument, you can specify which processes and containers to profile on the machine. 35 36 The `targets` can be from `discovery.process` component. 37 You can use `discovery.process` join argument to join process targets with extra discoveries such as [`discovery.kubernetes`](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.kubernetes/), [`discovery.docker`](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.docker/), and [`discovery.dockerswarm`](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.dockerswarm/). 38 You can use the [`discovery.relabel`](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.relabel/) component to relabel discovered targets and set your own labels. 39 For more information, refer to the [Components](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/) documentation. 40 41 The `forward_to` parameter should point to a [`pyroscope.write`](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/pyroscope/pyroscope.write/) component to send the collected profiles to your 42 Pyroscope Server or [Grafana Cloud](/products/cloud/). 43 44 | Name | Type | Description | Default | Required | 45 |--------------|--------------------------|--------------------------------------------------|---------|----------| 46 | `targets` | `list(map(string))` | List of java process targets to profile. | | yes | 47 | `forward_to` | `list(ProfilesReceiver)` | List of receivers to send collected profiles to. | | yes | 48 | `tmp_dir` | `string` | Temporary directory to store async-profiler. | `/tmp` | no | 49 50 The special label `__process_pid__` _must always_ be present in each target of `targets` and corresponds to the `PID` of 51 the process to profile. 52 53 The special label `service_name` is required and must always be present. 54 If `service_name` isn't specified, `pyroscope.java` attempts to infer it from discovery meta labels. 55 If `service_name` isn't specified and couldn't be inferred, then it's set to `unspecified`. 56 57 The `profiling_config` block describes how async-profiler is invoked. 58 59 It supports the following arguments: 60 61 | Name | Type | Description | Default | Required | 62 |---------------|------------|----------------------------------------------------------------------------------------------------------|---------|----------| 63 | `interval` | `duration` | How frequently to collect profiles from the targets. | "60s" | no | 64 | `cpu` | `bool` | A flag to enable CPU profiling, using `itimer` async-profiler event. | true | no | 65 | `sample_rate` | `int` | CPU profiling sample rate. It's converted from Hz to interval and passed as `-i` arg to async-profiler. | 100 | no | 66 | `alloc` | `string` | Allocation profiling sampling configuration It's passed as `--alloc` arg to async-profiler. | "512k" | no | 67 | `lock` | `string` | Lock profiling sampling configuration. It's passed as `--lock` arg to async-profiler. | "10ms" | no | 68 69 For more information on async-profiler configuration, 70 see [profiler-options](https://github.com/async-profiler/async-profiler?tab=readme-ov-file#profiler-options). 71 72 ### Set privileges for the collector 73 74 You must run the collector, such Alloy, as root and inside host `pid` namespace for the `pyroscope.java` and `discover.process` components to work. 75 76 ### Start the collector 77 78 To start Grafana Alloy v1.2 and later, replace `configuration.alloy` with your configuration filename: 79 80 ```bash 81 alloy run configuration.alloy 82 ``` 83 84 To start Grafana Alloy v1.0 or 1.1, replace `configuration.alloy` with your configuration file name: 85 86 ```bash 87 alloy run --stability.level=public-preview configuration.alloy 88 ``` 89 90 The `stability.level` option is required for `pyroscope.scrape` with Alloy v1.0 or v1.1. For more information about `stability.level`, refer to [the run command](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/cli/run/#permitted-stability-levels) documentation. 91 92 93 ### Send data to Grafana Cloud Profiles 94 95 When sending to Grafana Cloud Profiles, you can use the following `pyroscope.write` component configuration which uses environment variables. 96 97 Ensure that you have appropriately configured the `GC_URL`, `GC_USER`, and `GC_PASSWORD` environment variables. 98 99 ```alloy 100 pyroscope.write "endpoint" { 101 endpoint { 102 basic_auth { 103 password = env("GC_PASSWORD") 104 username = env("GC_USER") 105 } 106 url = env("GC_URL") 107 } 108 } 109 ``` 110 111 ## Examples 112 113 For more robust examples, refer to the [Grafana Alloy and Agent Auto-instrumentation](https://github.com/grafana/pyroscope/tree/main/examples/grafana-alloy-auto-instrumentation) examples in the Pyroscope repository. 114 115 ### Profiling local process 116 117 ```alloy 118 discovery.process "all" { 119 } 120 121 discovery.relabel "java" { 122 targets = discovery.process.all.targets 123 // Filter only java processes 124 rule { 125 source_labels = ["__meta_process_exe"] 126 action = "keep" 127 regex = ".*/java$" 128 } 129 // Filter processes. For example: only processes with command line containing "FastSlow" 130 rule { 131 source_labels = ["__meta_process_commandline"] 132 regex = "java FastSlow" 133 action = "keep" 134 } 135 // Provide a service name for the process, otherwise it will be unspecified. 136 rule { 137 action = "replace" 138 target_label = "service_name" 139 replacement = "java-fast-slow" 140 } 141 } 142 143 pyroscope.java "java" { 144 forward_to = [pyroscope.write.example.receiver] 145 targets = discovery.relabel.java.output 146 } 147 148 pyroscope.write "example" { 149 endpoint { 150 url = "http://pyroscope:4040" 151 } 152 } 153 154 ``` 155 156 ### Profiling Docker containers 157 158 For a working example, refer to [Java profiling via auto-instrumentation example in Docker](https://github.com/grafana/pyroscope/tree/main/examples/grafana-alloy-auto-instrumentation/java/docker). 159 160 ```alloy 161 discovery.docker "local_containers" { 162 host = "unix:///var/run/docker.sock" 163 } 164 165 discovery.process "all" { 166 join = discovery.docker.local_containers.targets 167 } 168 169 discovery.relabel "java" { 170 targets = discovery.process.all.targets 171 // Filter only java processes 172 rule { 173 source_labels = ["__meta_process_exe"] 174 action = "keep" 175 regex = ".*/java$" 176 } 177 // Filter only needed containers 178 rule { 179 source_labels = ["__meta_docker_container_name"] 180 regex = ".*suspicious_pascal" 181 action = "keep" 182 } 183 // Provide a service name for the process, otherwise it will default to the value of __meta_docker_container_name label. 184 rule { 185 action = "replace" 186 target_label = "service_name" 187 replacement = "java-fast-slow" 188 } 189 } 190 191 pyroscope.java "java" { 192 forward_to = [pyroscope.write.example.receiver] 193 targets = discovery.relabel.java.output 194 } 195 196 pyroscope.write "example" { 197 endpoint { 198 url = "http://pyroscope:4040" 199 } 200 } 201 ``` 202 203 ### Profiling Kubernetes pods 204 205 For a working example, refer to [Grafana Alloy Java profiling via auto-instrumentation with Kubernetes](https://github.com/grafana/pyroscope/tree/main/examples/grafana-alloy-auto-instrumentation/java/kubernetes). 206 207 ```alloy 208 discovery.kubernetes "local_pods" { 209 selectors { 210 field = "spec.nodeName=" + env("HOSTNAME") 211 role = "pod" 212 } 213 role = "pod" 214 } 215 216 discovery.process "all" { 217 join = discovery.kubernetes.local_pods.targets 218 } 219 220 discovery.relabel "java_pods" { 221 targets = discovery.process.all.targets 222 // Filter only java processes 223 rule { 224 source_labels = ["__meta_process_exe"] 225 action = "keep" 226 regex = ".*/java$" 227 } 228 rule { 229 action = "drop" 230 regex = "Succeeded|Failed|Completed" 231 source_labels = ["__meta_kubernetes_pod_phase"] 232 } 233 rule { 234 action = "replace" 235 source_labels = ["__meta_kubernetes_namespace"] 236 target_label = "namespace" 237 } 238 rule { 239 action = "replace" 240 source_labels = ["__meta_kubernetes_pod_name"] 241 target_label = "pod" 242 } 243 rule { 244 action = "replace" 245 source_labels = ["__meta_kubernetes_pod_node_name"] 246 target_label = "node" 247 } 248 rule { 249 action = "replace" 250 source_labels = ["__meta_kubernetes_pod_container_name"] 251 target_label = "container" 252 } 253 // Provide arbitrary service_name label, otherwise it will be inferred from discovery labels automatically 254 rule { 255 action = "replace" 256 regex = "(.*)@(.*)" 257 replacement = "java/${1}/${2}" 258 separator = "@" 259 source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"] 260 target_label = "service_name" 261 } 262 // Filter only needed services 263 rule { 264 action = "keep" 265 regex = "(java/ns1/.*)|(java/ns2/container-.*0)" 266 source_labels = ["service_name"] 267 } 268 } 269 270 pyroscope.java "java" { 271 forward_to = [pyroscope.write.example.receiver] 272 targets = discovery.relabel.java_pods.output 273 } 274 275 pyroscope.write "example" { 276 endpoint { 277 url = "http://pyroscope:4040" 278 } 279 } 280 ``` 281 282 ## References 283 284 For more information: 285 286 * [Examples](https://github.com/grafana/pyroscope/tree/main/examples/grafana-alloy-auto-instrumentation/java) 287 288 - [Grafana Alloy](https://grafana.com/docs/alloy/<ALLOY_VERSION>/) 289 - [pyroscope.scrape](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/pyroscope/pyroscope.scrape/) 290 - [pyroscope.write](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/pyroscope/pyroscope.write/) 291 - [discovery.kubernetes](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.kubernetes/) 292 - [discovery.docker](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.docker/) 293 - [discovery.relabel](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.relabel/)