github.com/grafana/pyroscope@v1.18.0/docs/sources/configure-client/grafana-alloy/go_pull.md (about)

     1  ---
     2  title: Set up Go profiling in pull mode
     3  menuTitle: Set up Go profiling in pull mode
     4  description: Learn how to set up Go profiling in pull mode.
     5  weight: 10
     6  ---
     7  
     8  # Set up Go profiling in pull mode
     9  
    10  In pull mode, the collector, Grafana Alloy, periodically retrieves profiles from Golang applications, specifically targeting the
    11  `/debug/pprof/*` endpoints.
    12  
    13  To set up Golang profiling in pull mode, you need to:
    14  
    15  1. Expose pprof endpoints.
    16  2. Install a collector, such as Grafana Alloy.
    17  3. Prepare the collector's configuration file.
    18  4. Start the collector.
    19  
    20  ## Expose pprof endpoints
    21  
    22  Ensure your Golang application exposes pprof endpoints.
    23  
    24  1. Get `godeltaprof` package
    25  
    26      ```bash
    27      go get github.com/grafana/pyroscope-go/godeltaprof@latest
    28      ```
    29  
    30  2. Import `net/http/pprof` and `godeltaprof/http/pprof` packages at the start of your application.
    31  
    32      ```go
    33      import _ "net/http/pprof"
    34      import _ "github.com/grafana/pyroscope-go/godeltaprof/http/pprof"
    35      ```
    36  
    37  ## Install the collector
    38  
    39  [//]: # (TODO(korniltsev) What should go here?)
    40  
    41  You can use the sample Alloy collector configuration file to send data to Pyroscope.
    42  
    43  To install Alloy, refer to [Grafana Alloy installation](https://grafana.com/docs/alloy/<ALLOY_VERSION>/get-started/install/).
    44  
    45  ### Prepare the collector configuration file
    46  
    47  In the Alloy configuration file, you need to add at least two blocks: `pyroscope.write` and `pyroscope.scrape`.
    48  
    49  1. Add `pyroscope.write` block.
    50  
    51      ```alloy
    52      pyroscope.write "write_job_name" {
    53              endpoint {
    54                      url = "http://localhost:4040"
    55              }
    56      }
    57      ```
    58  
    59  1. Add `pyroscope.scrape` block.
    60  
    61      ```alloy
    62      pyroscope.scrape "scrape_job_name" {
    63              targets    = [{"__address__" = "localhost:4040", "service_name" = "example_service"}]
    64              forward_to = [pyroscope.write.write_job_name.receiver]
    65  
    66              profiling_config {
    67                      profile.process_cpu {
    68                              enabled = true
    69                      }
    70  
    71                      profile.godeltaprof_memory {
    72                              enabled = true
    73                      }
    74  
    75                      profile.memory { // disable memory, use godeltaprof_memory instead
    76                              enabled = false
    77                      }
    78  
    79                      profile.godeltaprof_mutex {
    80                              enabled = true
    81                      }
    82  
    83                      profile.mutex { // disable mutex, use godeltaprof_mutex instead
    84                              enabled = false
    85                      }
    86  
    87                      profile.godeltaprof_block {
    88                              enabled = true
    89                      }
    90  
    91                      profile.block { // disable block, use godeltaprof_block instead
    92                              enabled = false
    93                      }
    94  
    95                      profile.goroutine {
    96                              enabled = true
    97                      }
    98              }
    99      }
   100  
   101      ```
   102  
   103  1. Save the changes to the file.
   104  
   105  ### Start the collector
   106  
   107  1. Start a local Pyroscope instance for testing purposes:
   108      ```bash
   109      docker run -p 4040:4040 grafana/pyroscope
   110      ```
   111  
   112  1. To start Alloy v1.2 and later: Replace `configuration.alloy` with your configuration filename: <br> `alloy run configuration.alloy`
   113  
   114  1. Open a browser to `http://localhost:4040`. The page should list profiles.
   115  
   116  ## Examples
   117  
   118  ### Send data to Grafana Cloud
   119  
   120  Your Grafana Cloud URL, username, and password can be found on the "Details Page" for Pyroscope from your stack on
   121  grafana.com.
   122  On this same page, create a token and use it as the Basic authentication password.
   123  
   124  ```alloy
   125  pyroscope.write "write_job_name" {
   126          endpoint {
   127                  url = "<Grafana Cloud URL>"
   128  
   129                  basic_auth {
   130                          username = "<Grafana Cloud User>"
   131                          password = "<Grafana Cloud Password>"
   132                  }
   133          }
   134  
   135  }
   136  ```
   137  
   138  ### Discover Kubernetes targets
   139  
   140  1. Select all pods
   141  
   142    ```alloy
   143    discovery.kubernetes "all_pods" {
   144            role = "pod"
   145    }
   146    ```
   147  
   148  1. Drop not running pods, create `namespace`, `pod`, `node` and `container` labels.
   149    Compose `service_name` label based on `namespace` and `container` labels.
   150    Select only services matching regex pattern `(ns1/.*)|(ns2/container-.*0)`.
   151      ```alloy
   152  
   153      discovery.relabel "specific_pods" {
   154              targets = discovery.kubernetes.all_pods.targets
   155  
   156              rule {
   157                      action        = "drop"
   158                      regex         = "Succeeded|Failed|Completed"
   159                      source_labels = ["__meta_kubernetes_pod_phase"]
   160              }
   161  
   162              rule {
   163                      action        = "replace"
   164                      source_labels = ["__meta_kubernetes_namespace"]
   165                      target_label  = "namespace"
   166              }
   167  
   168              rule {
   169                      action        = "replace"
   170                      source_labels = ["__meta_kubernetes_pod_name"]
   171                      target_label  = "pod"
   172              }
   173  
   174              rule {
   175                      action        = "replace"
   176                      source_labels = ["__meta_kubernetes_node_name"]
   177                      target_label  = "node"
   178              }
   179  
   180              rule {
   181                      action        = "replace"
   182                      source_labels = ["__meta_kubernetes_pod_container_name"]
   183                      target_label  = "container"
   184              }
   185  
   186              rule {
   187                      action        = "replace"
   188                      regex         = "(.*)@(.*)"
   189                      replacement   = "${1}/${2}"
   190                      separator     = "@"
   191                      source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
   192                      target_label  = "service_name"
   193              }
   194  
   195              rule {
   196                      action        = "keep"
   197                      regex         = "(ns1/.*)|(ns2/container-.*0)"
   198                      source_labels = ["service_name"]
   199              }
   200      }
   201      ```
   202  
   203  1. Use `discovery.relabel.specific_pods.output` as a target for `pyroscope.scrape` block.
   204  
   205      ```alloy
   206          pyroscope.scrape "scrape_job_name" {
   207                  targets    = discovery.relabel.specific_pods.output
   208                  ...
   209          }
   210      ```
   211  
   212  ### Exposing pprof endpoints
   213  
   214  If you don't use `http.DefaultServeMux`, you can register `/debug/pprof/*` handlers to your own `http.ServeMux`:
   215  
   216  ```go
   217  var mux *http.ServeMux
   218  mux.Handle("/debug/pprof/", http.DefaultServeMux)
   219  ```
   220  
   221  Or, if you use gorilla/mux:
   222  
   223  ```go
   224  var router *mux.Router
   225  router.PathPrefix("/debug/pprof").Handler(http.DefaultServeMux)
   226  ```
   227  
   228  ## References
   229  
   230  - [Grafana Alloy](https://grafana.com/docs/alloy/<ALLOY_VERSION>/)
   231  - [pyroscope.scrape](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/pyroscope/pyroscope.scrape/)
   232  - [pyroscope.write](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/pyroscope/pyroscope.write/)
   233  - [discovery.kubernetes](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.kubernetes/)
   234  - [discovery.docker](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.docker/)
   235  - [discovery.relabel](https://grafana.com/docs/alloy/<ALLOY_VERSION>/reference/components/discovery/discovery.relabel/)