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/)